anna-agent 0.2.0__tar.gz → 0.2.2__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 (63) hide show
  1. {anna_agent-0.2.0 → anna_agent-0.2.2}/PKG-INFO +23 -23
  2. {anna_agent-0.2.0 → anna_agent-0.2.2}/README.md +22 -22
  3. {anna_agent-0.2.0 → anna_agent-0.2.2}/pyproject.toml +1 -1
  4. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/__init__.py +1 -1
  5. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/anna_agent_template.py +8 -5
  6. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/cli.py +153 -40
  7. anna_agent-0.2.2/src/anna_agent/complaint_elicitor.py +71 -0
  8. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/defaults.py +4 -4
  9. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/init_content.py +13 -12
  10. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/load_config.py +36 -19
  11. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/diagnostics.py +4 -2
  12. anna_agent-0.2.2/src/anna_agent/fill_scales.py +175 -0
  13. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/model_services.py +2 -2
  14. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/querier.py +8 -52
  15. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/runtime.py +11 -2
  16. anna_agent-0.2.2/src/anna_agent/short_term_memory.py +185 -0
  17. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent.egg-info/PKG-INFO +23 -23
  18. anna_agent-0.2.0/src/anna_agent/complaint_elicitor.py +0 -88
  19. anna_agent-0.2.0/src/anna_agent/fill_scales.py +0 -385
  20. anna_agent-0.2.0/src/anna_agent/short_term_memory.py +0 -286
  21. {anna_agent-0.2.0 → anna_agent-0.2.2}/LICENSE +0 -0
  22. {anna_agent-0.2.0 → anna_agent-0.2.2}/setup.cfg +0 -0
  23. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/__main__.py +0 -0
  24. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/assets.py +0 -0
  25. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/backbone.py +0 -0
  26. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/case_data.py +0 -0
  27. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/common/registry.py +0 -0
  28. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/common/tool_calls.py +0 -0
  29. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/complaint_chain.py +0 -0
  30. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/__init__.py +0 -0
  31. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/environment_reader.py +0 -0
  32. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/initialize.py +0 -0
  33. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/config/models/anna_engine_config.py +0 -0
  34. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/counselor.py +0 -0
  35. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/datasets/cbt-triggering-events.csv +0 -0
  36. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/emotion_modulator.py +0 -0
  37. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/emotion_pertuber.py +0 -0
  38. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/event_trigger.py +0 -0
  39. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/figure/readme.md +0 -0
  40. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/figure/whiteboard_exported_image_en.png +0 -0
  41. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/initialize.py +0 -0
  42. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/memory/__init__.py +0 -0
  43. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/memory/chunking.py +0 -0
  44. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/memory/embeddings.py +0 -0
  45. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/memory/models.py +0 -0
  46. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/memory/store.py +0 -0
  47. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/ms_patient.py +0 -0
  48. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/ms_patient_with_prompt.py +0 -0
  49. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/scales/__init__.py +0 -0
  50. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/scales/bdi.json +0 -0
  51. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/scales/ghq-28.json +0 -0
  52. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/scales/sass.json +0 -0
  53. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/server/complaint.sh +0 -0
  54. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/server/counselor.sh +0 -0
  55. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/server/emotion.sh +0 -0
  56. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/service.py +0 -0
  57. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/style_analyzer.py +0 -0
  58. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent/workspace.py +0 -0
  59. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent.egg-info/SOURCES.txt +0 -0
  60. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent.egg-info/dependency_links.txt +0 -0
  61. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent.egg-info/entry_points.txt +0 -0
  62. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent.egg-info/requires.txt +0 -0
  63. {anna_agent-0.2.0 → anna_agent-0.2.2}/src/anna_agent.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anna-agent
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Dynamic Evolution Agent System with Multi-Session Memory for Realistic Seeker Simulation
5
5
  Project-URL: Documentation, https://sci-m-wang.github.io/AnnaAgent/
6
6
  Project-URL: Repository, https://github.com/sci-m-wang/AnnaAgent
@@ -61,7 +61,7 @@ After installation, the short command `anna` is available in any terminal:
61
61
 
62
62
  ```bash
63
63
  anna --version
64
- anna init anna-workspace
64
+ anna create anna-workspace
65
65
  anna doctor --workspace anna-workspace
66
66
  ```
67
67
 
@@ -72,7 +72,7 @@ a workspace deployment environment on the Linux/GPU machine. This keeps the
72
72
  lightweight `anna` CLI install separate from heavy vLLM dependencies:
73
73
 
74
74
  ```bash
75
- anna init anna-workspace --deploy-env
75
+ anna create anna-workspace --deploy-env
76
76
 
77
77
  # Or add it later to an existing workspace.
78
78
  anna models env setup --workspace anna-workspace
@@ -117,17 +117,17 @@ First, create a workspace, choose whether to use the SFT modules, and let the CL
117
117
  write the resulting configuration:
118
118
 
119
119
  ```bash
120
- anna init anna-workspace
120
+ anna create anna-workspace
121
121
 
122
122
  # Optional on GPU machines: create anna-workspace/.anna-deploy-venv for vLLM.
123
- anna init anna-workspace --deploy-env
123
+ anna create anna-workspace --deploy-env
124
124
 
125
125
  # Fast path: use the base chat model for complaint-chain and emotion modules.
126
126
  anna models use-base --target all --workspace anna-workspace
127
127
 
128
128
  # SFT path: deploy local vLLM services from downloaded HuggingFace assets.
129
- anna assets pull paper --workspace anna-workspace
130
- anna models env setup --workspace anna-workspace # optional if init used --deploy-env
129
+ anna assets download paper --workspace anna-workspace
130
+ anna models env setup --workspace anna-workspace # optional if create used --deploy-env
131
131
  anna models deploy --target complaint --backend vllm --workspace anna-workspace \
132
132
  --gpu 0 --gpu-memory-utilization 0.85 --wait-timeout 900
133
133
  anna models deploy --target emotion --backend vllm --workspace anna-workspace \
@@ -169,7 +169,7 @@ AnnaAgent provides a Typer-based CLI organized around the reader journey from
169
169
  paper reproduction to application use. Start by creating an isolated workspace:
170
170
 
171
171
  ```bash
172
- anna init anna-workspace
172
+ anna create anna-workspace
173
173
  anna doctor --workspace anna-workspace
174
174
  ```
175
175
 
@@ -188,7 +188,7 @@ anna config validate --workspace anna-workspace
188
188
 
189
189
  `config wizard` and `config secrets` use hidden password-style prompts for API
190
190
  keys and write them to `.env`. The generated `.env` and `.env.example` files
191
- include commented placeholders showing exactly where to put base-model, SFT and
191
+ include commented placeholders showing exactly where to put backbone, SFT and
192
192
  embedding credentials if you prefer manual editing.
193
193
 
194
194
  Assets are manifest-driven. The default `paper` preset points to the released
@@ -197,23 +197,23 @@ HuggingFace SFT models and synthetic data, and you can override or extend it in
197
197
 
198
198
  ```bash
199
199
  anna assets list --workspace anna-workspace
200
- anna assets pull paper --workspace anna-workspace
200
+ anna assets download paper --workspace anna-workspace
201
201
  ```
202
202
 
203
- Always pass `--workspace` or `--manifest` when pulling assets. Without either,
204
- `anna assets pull` uses the current directory as the workspace and may download
205
- to `./assets/...` instead of your intended AnnaAgent workspace. You can pull one
203
+ Always pass `--workspace` or `--manifest` when downloading assets. Without either,
204
+ `anna assets download` uses the current directory as the workspace and may download
205
+ to `./assets/...` instead of your intended AnnaAgent workspace. You can download one
206
206
  specific resource or override the target directory explicitly:
207
207
 
208
208
  ```bash
209
- # Pull one asset from anna-workspace/assets/anna-assets.json.
210
- anna assets pull complaint-sft --workspace anna-workspace
209
+ # Download one asset from anna-workspace/assets/anna-assets.json.
210
+ anna assets download complaint-sft --workspace anna-workspace
211
211
 
212
212
  # Use an explicit manifest JSON, including absolute target paths in that file.
213
- anna assets pull complaint-sft --manifest anna-workspace/assets/anna-assets.json
213
+ anna assets download complaint-sft --manifest anna-workspace/assets/anna-assets.json
214
214
 
215
215
  # Override the target directory for exactly one selected asset.
216
- anna assets pull complaint-sft --workspace anna-workspace \
216
+ anna assets download complaint-sft --workspace anna-workspace \
217
217
  --target /path/to/models/complaint-sft
218
218
  ```
219
219
 
@@ -272,7 +272,7 @@ anna models deploy --target complaint --backend vllm --workspace anna-workspace
272
272
  ```
273
273
  When `--model-path` is omitted, deploy reads the corresponding SFT asset target
274
274
  from `assets/anna-assets.json`, including absolute paths. Pass the same
275
- `--workspace` or `--manifest` that you used during `assets pull`.
275
+ `--workspace` or `--manifest` that you used during `assets download`.
276
276
 
277
277
  If `models deploy` reports that vLLM is unavailable, run
278
278
  `anna models env setup --workspace anna-workspace` to create the workspace deploy
@@ -299,11 +299,11 @@ Initialization can be run as a full AnnaAgent initialization, or as a prompt-onl
299
299
  state for cheap dry-runs and reproducible prompt freezing:
300
300
 
301
301
  ```bash
302
- anna initialize prompt-only anna-workspace/cases/family_stress_case.json \
302
+ anna init prompt-only anna-workspace/cases/family_stress_case.json \
303
303
  --out anna-workspace/prompts/family.prompt.json
304
- anna initialize full anna-workspace/cases/family_stress_case.json \
304
+ anna init full anna-workspace/cases/family_stress_case.json \
305
305
  --out anna-workspace/prompts/family.full.json --workspace anna-workspace
306
- anna initialize from-prompt anna-workspace/prompts/family.prompt.json
306
+ anna init from-prompt anna-workspace/prompts/family.prompt.json
307
307
  ```
308
308
 
309
309
  Chat interactively from either a case file or a frozen prompt state:
@@ -458,8 +458,8 @@ the base model, or `true` to call the configured SFT endpoint.
458
458
 
459
459
  ```yaml
460
460
  model_service:
461
- model_name: counselor
462
- api_key: counselor
461
+ model_name: anna-backbone
462
+ api_key: anna-backbone
463
463
  base_url: http://localhost:8002/v1
464
464
  servers:
465
465
  complaint:
@@ -37,7 +37,7 @@ After installation, the short command `anna` is available in any terminal:
37
37
 
38
38
  ```bash
39
39
  anna --version
40
- anna init anna-workspace
40
+ anna create anna-workspace
41
41
  anna doctor --workspace anna-workspace
42
42
  ```
43
43
 
@@ -48,7 +48,7 @@ a workspace deployment environment on the Linux/GPU machine. This keeps the
48
48
  lightweight `anna` CLI install separate from heavy vLLM dependencies:
49
49
 
50
50
  ```bash
51
- anna init anna-workspace --deploy-env
51
+ anna create anna-workspace --deploy-env
52
52
 
53
53
  # Or add it later to an existing workspace.
54
54
  anna models env setup --workspace anna-workspace
@@ -93,17 +93,17 @@ First, create a workspace, choose whether to use the SFT modules, and let the CL
93
93
  write the resulting configuration:
94
94
 
95
95
  ```bash
96
- anna init anna-workspace
96
+ anna create anna-workspace
97
97
 
98
98
  # Optional on GPU machines: create anna-workspace/.anna-deploy-venv for vLLM.
99
- anna init anna-workspace --deploy-env
99
+ anna create anna-workspace --deploy-env
100
100
 
101
101
  # Fast path: use the base chat model for complaint-chain and emotion modules.
102
102
  anna models use-base --target all --workspace anna-workspace
103
103
 
104
104
  # SFT path: deploy local vLLM services from downloaded HuggingFace assets.
105
- anna assets pull paper --workspace anna-workspace
106
- anna models env setup --workspace anna-workspace # optional if init used --deploy-env
105
+ anna assets download paper --workspace anna-workspace
106
+ anna models env setup --workspace anna-workspace # optional if create used --deploy-env
107
107
  anna models deploy --target complaint --backend vllm --workspace anna-workspace \
108
108
  --gpu 0 --gpu-memory-utilization 0.85 --wait-timeout 900
109
109
  anna models deploy --target emotion --backend vllm --workspace anna-workspace \
@@ -145,7 +145,7 @@ AnnaAgent provides a Typer-based CLI organized around the reader journey from
145
145
  paper reproduction to application use. Start by creating an isolated workspace:
146
146
 
147
147
  ```bash
148
- anna init anna-workspace
148
+ anna create anna-workspace
149
149
  anna doctor --workspace anna-workspace
150
150
  ```
151
151
 
@@ -164,7 +164,7 @@ anna config validate --workspace anna-workspace
164
164
 
165
165
  `config wizard` and `config secrets` use hidden password-style prompts for API
166
166
  keys and write them to `.env`. The generated `.env` and `.env.example` files
167
- include commented placeholders showing exactly where to put base-model, SFT and
167
+ include commented placeholders showing exactly where to put backbone, SFT and
168
168
  embedding credentials if you prefer manual editing.
169
169
 
170
170
  Assets are manifest-driven. The default `paper` preset points to the released
@@ -173,23 +173,23 @@ HuggingFace SFT models and synthetic data, and you can override or extend it in
173
173
 
174
174
  ```bash
175
175
  anna assets list --workspace anna-workspace
176
- anna assets pull paper --workspace anna-workspace
176
+ anna assets download paper --workspace anna-workspace
177
177
  ```
178
178
 
179
- Always pass `--workspace` or `--manifest` when pulling assets. Without either,
180
- `anna assets pull` uses the current directory as the workspace and may download
181
- to `./assets/...` instead of your intended AnnaAgent workspace. You can pull one
179
+ Always pass `--workspace` or `--manifest` when downloading assets. Without either,
180
+ `anna assets download` uses the current directory as the workspace and may download
181
+ to `./assets/...` instead of your intended AnnaAgent workspace. You can download one
182
182
  specific resource or override the target directory explicitly:
183
183
 
184
184
  ```bash
185
- # Pull one asset from anna-workspace/assets/anna-assets.json.
186
- anna assets pull complaint-sft --workspace anna-workspace
185
+ # Download one asset from anna-workspace/assets/anna-assets.json.
186
+ anna assets download complaint-sft --workspace anna-workspace
187
187
 
188
188
  # Use an explicit manifest JSON, including absolute target paths in that file.
189
- anna assets pull complaint-sft --manifest anna-workspace/assets/anna-assets.json
189
+ anna assets download complaint-sft --manifest anna-workspace/assets/anna-assets.json
190
190
 
191
191
  # Override the target directory for exactly one selected asset.
192
- anna assets pull complaint-sft --workspace anna-workspace \
192
+ anna assets download complaint-sft --workspace anna-workspace \
193
193
  --target /path/to/models/complaint-sft
194
194
  ```
195
195
 
@@ -248,7 +248,7 @@ anna models deploy --target complaint --backend vllm --workspace anna-workspace
248
248
  ```
249
249
  When `--model-path` is omitted, deploy reads the corresponding SFT asset target
250
250
  from `assets/anna-assets.json`, including absolute paths. Pass the same
251
- `--workspace` or `--manifest` that you used during `assets pull`.
251
+ `--workspace` or `--manifest` that you used during `assets download`.
252
252
 
253
253
  If `models deploy` reports that vLLM is unavailable, run
254
254
  `anna models env setup --workspace anna-workspace` to create the workspace deploy
@@ -275,11 +275,11 @@ Initialization can be run as a full AnnaAgent initialization, or as a prompt-onl
275
275
  state for cheap dry-runs and reproducible prompt freezing:
276
276
 
277
277
  ```bash
278
- anna initialize prompt-only anna-workspace/cases/family_stress_case.json \
278
+ anna init prompt-only anna-workspace/cases/family_stress_case.json \
279
279
  --out anna-workspace/prompts/family.prompt.json
280
- anna initialize full anna-workspace/cases/family_stress_case.json \
280
+ anna init full anna-workspace/cases/family_stress_case.json \
281
281
  --out anna-workspace/prompts/family.full.json --workspace anna-workspace
282
- anna initialize from-prompt anna-workspace/prompts/family.prompt.json
282
+ anna init from-prompt anna-workspace/prompts/family.prompt.json
283
283
  ```
284
284
 
285
285
  Chat interactively from either a case file or a frozen prompt state:
@@ -434,8 +434,8 @@ the base model, or `true` to call the configured SFT endpoint.
434
434
 
435
435
  ```yaml
436
436
  model_service:
437
- model_name: counselor
438
- api_key: counselor
437
+ model_name: anna-backbone
438
+ api_key: anna-backbone
439
439
  base_url: http://localhost:8002/v1
440
440
  servers:
441
441
  complaint:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "anna-agent"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "Dynamic Evolution Agent System with Multi-Session Memory for Realistic Seeker Simulation"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = []
4
4
 
5
- __version__ = "0.2.0"
5
+ __version__ = "0.2.2"
@@ -1,17 +1,18 @@
1
1
  ## 主诉请求和情绪通过reminder来控制
2
2
 
3
3
  prompt_template = """
4
- 你正在扮演 心理障碍的患者,你正在cosplay 心理咨询患者。
5
- 结合历史内容的内容用一致性的语气回复。配合我进行演出,
6
- 请不要回答你是语言模型,永远记住你正在扮演 心理咨询患者
7
- 注意保持你的性格特点包括 {situation}
4
+ # Role: 心理咨询患者
8
5
 
9
6
  ## Profile
10
7
  - 性别: {gender}
11
8
  - 年龄: {age}
12
9
  - 职业: {occupation}
13
10
  - 婚姻状况: {marriage}
14
-
11
+
12
+ ## Situation
13
+ - 你是一个有心理障碍的患者,正在与心理咨询师进行对话。
14
+ {situation}
15
+
15
16
  ## Status
16
17
  {status}
17
18
 
@@ -24,4 +25,6 @@ prompt_template = """
24
25
  ## Constraints
25
26
  - 使用中文回复
26
27
  - 一次不能提及过多的症状信息,每轮最多讨论一个症状。
28
+ - 你应该用含糊和口语化的方式表达你的症状,并将其与你的生活经历联系起来。
29
+ - 不要使用专业术语。
27
30
  """
@@ -79,7 +79,8 @@ app.add_typer(config_app, name="config")
79
79
  app.add_typer(test_app, name="test")
80
80
  app.add_typer(data_app, name="data")
81
81
  app.add_typer(memory_app, name="memory")
82
- app.add_typer(initialize_app, name="initialize")
82
+ app.add_typer(initialize_app, name="init")
83
+ app.add_typer(initialize_app, name="initialize", hidden=True)
83
84
  app.add_typer(models_app, name="models")
84
85
  models_app.add_typer(models_env_app, name="env")
85
86
  app.add_typer(run_app, name="run")
@@ -147,8 +148,8 @@ def _render_config_summary(
147
148
  table.add_row("Workspace", str(workspace))
148
149
  if source:
149
150
  table.add_row(source_kind, str(source))
150
- table.add_row("Base model", cfg.model_name)
151
- table.add_row("Base endpoint", cfg.base_url)
151
+ table.add_row("AnnaAgent backbone model", cfg.model_name)
152
+ table.add_row("Backbone endpoint", cfg.base_url)
152
153
  table.add_row("Memory", "on" if cfg.memory_enabled else "off")
153
154
  table.add_row("Debug UI", "on" if debug_ui else "off")
154
155
  console.print(Panel(table, title="配置摘要", border_style="blue"))
@@ -195,17 +196,77 @@ def _print_deploy_env_status(status: dict[str, Any]) -> None:
195
196
  console.print(table)
196
197
 
197
198
 
198
- def _looks_like_connection_error(err: BaseException) -> bool:
199
+ def _iter_exception_chain(err: BaseException):
199
200
  current: BaseException | None = err
200
201
  while current is not None:
201
- if current.__class__.__name__ in {"APIConnectionError", "ConnectError"}:
202
- return True
202
+ yield current
203
203
  current = current.__cause__ or current.__context__
204
+
205
+
206
+ def _looks_like_connection_error(err: BaseException) -> bool:
207
+ for current in _iter_exception_chain(err):
208
+ if current.__class__.__name__ in {
209
+ "APIConnectionError",
210
+ "APITimeoutError",
211
+ "ConnectError",
212
+ "ConnectTimeout",
213
+ "ReadTimeout",
214
+ "TimeoutException",
215
+ }:
216
+ return True
217
+ return False
218
+
219
+
220
+ def _looks_like_auth_error(err: BaseException) -> bool:
221
+ for current in _iter_exception_chain(err):
222
+ class_name = current.__class__.__name__
223
+ status_code = getattr(current, "status_code", None)
224
+ text = str(current).lower()
225
+ if class_name in {"AuthenticationError", "PermissionDeniedError"}:
226
+ return True
227
+ if status_code in {401, 403}:
228
+ return True
229
+ if "invalid api key" in text or "invalid_key" in text:
230
+ return True
204
231
  return False
205
232
 
206
233
 
234
+ def _looks_like_model_service_error(err: BaseException) -> bool:
235
+ if _looks_like_connection_error(err) or _looks_like_auth_error(err):
236
+ return True
237
+ for current in _iter_exception_chain(err):
238
+ if current.__class__.__name__ in {"APIStatusError", "RateLimitError"}:
239
+ return True
240
+ return False
241
+
242
+
243
+ def _configured_secret_values() -> list[str]:
244
+ try:
245
+ cfg = registry.get("anna_engine_config")
246
+ except Exception:
247
+ return []
248
+ return [
249
+ cfg.api_key,
250
+ cfg.complaint_api_key,
251
+ cfg.counselor_api_key,
252
+ cfg.emotion_api_key,
253
+ cfg.embedding_api_key,
254
+ ]
255
+
256
+
207
257
  def _print_model_connection_help(workspace: Path, err: BaseException) -> None:
208
- console.print(f"[red]Model service connection failed:[/red] {escape(str(err))}")
258
+ detail = escape(_redact_text(str(err), _configured_secret_values()))
259
+ if _looks_like_auth_error(err):
260
+ console.print(f"[red]Model service authentication failed:[/red] {detail}")
261
+ console.print(
262
+ "Check [bold]ANNA_ENGINE_API_KEY[/bold] or [bold]MIMO_API_KEY[/bold] "
263
+ "in the workspace .env and ensure the key matches the configured "
264
+ "base_url/model."
265
+ )
266
+ elif _looks_like_connection_error(err):
267
+ console.print(f"[red]Model service connection failed:[/red] {detail}")
268
+ else:
269
+ console.print(f"[red]Model service request failed:[/red] {detail}")
209
270
  console.print(
210
271
  "Run [bold]anna doctor --workspace {workspace}[/bold] and "
211
272
  "[bold]anna models status --workspace {workspace}[/bold]. If you use "
@@ -397,8 +458,8 @@ def doctor(
397
458
  console.print(table)
398
459
 
399
460
 
400
- @app.command("init")
401
- def init_workspace(
461
+ @app.command("create")
462
+ def create_workspace(
402
463
  target: Path = typer.Argument(Path("anna-workspace"), help="Workspace directory."),
403
464
  force: bool = typer.Option(False, "--force", help="Overwrite generated files."),
404
465
  deploy_env: bool = typer.Option(
@@ -418,7 +479,7 @@ def init_workspace(
418
479
  ),
419
480
  ) -> None:
420
481
  initialize_workspace(target, force=force)
421
- console.print(f"[green]Workspace initialized:[/green] {target}")
482
+ console.print(f"[green]Workspace created:[/green] {target}")
422
483
  if deploy_env:
423
484
  try:
424
485
  status = setup_deploy_env(
@@ -464,8 +525,9 @@ def assets_list(
464
525
  console.print(table)
465
526
 
466
527
 
467
- @assets_app.command("pull")
468
- def assets_pull(
528
+ @assets_app.command("pull", hidden=True)
529
+ @assets_app.command("download")
530
+ def assets_download(
469
531
  names: list[str] = typer.Argument(None, help="Asset names or preset names."),
470
532
  workspace: Path = typer.Option(Path(), "--workspace", "--root", resolve_path=True),
471
533
  force: bool = typer.Option(False, "--force", help="Redownload existing files."),
@@ -488,7 +550,7 @@ def assets_pull(
488
550
  manifest_file=manifest,
489
551
  target_override=target,
490
552
  )
491
- table = Table(title="Asset Pull Results")
553
+ table = Table(title="Asset Download Results")
492
554
  table.add_column("Name")
493
555
  table.add_column("Status")
494
556
  table.add_column("Path")
@@ -533,11 +595,20 @@ def config_wizard(
533
595
  workspace: Path = typer.Option(Path(), "--workspace", "--root", resolve_path=True),
534
596
  ) -> None:
535
597
  data = load_settings(workspace)
598
+ console.print(
599
+ Panel(
600
+ "[bold]AnnaAgent backbone model[/bold]\n"
601
+ "This model drives AnnaAgent's internal seeker-simulation modules.",
602
+ border_style="cyan",
603
+ )
604
+ )
536
605
  data.setdefault("model_service", {})["model_name"] = typer.prompt(
537
- "Base model name", default=data.get("model_service", {}).get("model_name", "")
606
+ "AnnaAgent backbone model name",
607
+ default=data.get("model_service", {}).get("model_name", ""),
538
608
  )
539
609
  data["model_service"]["base_url"] = typer.prompt(
540
- "Base model base URL", default=data.get("model_service", {}).get("base_url", "")
610
+ "AnnaAgent backbone base URL",
611
+ default=data.get("model_service", {}).get("base_url", ""),
541
612
  )
542
613
  data.setdefault("embedding", {})["model_name"] = typer.prompt(
543
614
  "Embedding model", default=data.get("embedding", {}).get("model_name", "")
@@ -563,14 +634,14 @@ def config_secrets(
563
634
 
564
635
  def _prompt_and_write_secrets(workspace: Path, include_sft: bool = False) -> None:
565
636
  prompts = [
566
- ("ANNA_ENGINE_API_KEY", "Base model API key"),
637
+ ("ANNA_ENGINE_API_KEY", "AnnaAgent backbone API key"),
567
638
  ("ANNA_ENGINE_EMBEDDING_API_KEY", "Embedding API key"),
568
639
  ]
569
640
  if include_sft:
570
641
  prompts.extend(
571
642
  [
572
643
  ("ANNA_ENGINE_COMPLAINT_API_KEY", "Complaint SFT API key"),
573
- ("ANNA_ENGINE_COUNSELOR_API_KEY", "Counselor API key"),
644
+ ("ANNA_ENGINE_COUNSELOR_API_KEY", "Backbone fallback API key"),
574
645
  ("ANNA_ENGINE_EMOTION_API_KEY", "Emotion SFT API key"),
575
646
  ]
576
647
  )
@@ -612,10 +683,16 @@ def test_model(
612
683
  _configure(workspace)
613
684
  cfg = registry.get("anna_engine_config")
614
685
  client = backbone.get_openai_client()
615
- response = client.chat.completions.create(
616
- model=cfg.model_name,
617
- messages=[{"role": "user", "content": "Reply with OK."}],
618
- )
686
+ try:
687
+ response = client.chat.completions.create(
688
+ model=cfg.model_name,
689
+ messages=[{"role": "user", "content": "Reply with OK."}],
690
+ )
691
+ except Exception as err:
692
+ if _looks_like_model_service_error(err):
693
+ _print_model_connection_help(workspace, err)
694
+ raise typer.Exit(code=1) from None
695
+ raise
619
696
  console.print(
620
697
  f"[green]Model OK[/green] response={response.choices[0].message.content}"
621
698
  )
@@ -796,7 +873,10 @@ def initialize_prompt_only(
796
873
  case_file: Path = typer.Argument(..., help="Case file."),
797
874
  output: Path = typer.Option(Path("prompts/prompt_state.json"), "--out", "-o"),
798
875
  ) -> None:
876
+ console.print(Rule("[bold blue]Initialization · prompt-only[/bold blue]"))
877
+ console.print(f"[blue]Running:[/blue] load case and build prompt for {case_file}")
799
878
  state = build_prompt_only_state(case_file)
879
+ console.print(f"[blue]Running:[/blue] write initialization state to {output}")
800
880
  save_state(state, output)
801
881
  console.print(f"[green]Wrote prompt-only state[/green] {output}")
802
882
 
@@ -808,13 +888,26 @@ def initialize_full(
808
888
  workspace: Path = typer.Option(Path(), "--workspace", "--root", resolve_path=True),
809
889
  ) -> None:
810
890
  _configure(workspace)
891
+ events: list[tuple[str, str]] = []
892
+
893
+ def progress(stage: str, detail: str) -> None:
894
+ events.append((stage, detail))
895
+ console.print(f"[blue]Running {escape(stage)}:[/blue] {escape(detail)}")
896
+
897
+ console.print(Rule("[bold blue]Initialization · full[/bold blue]"))
898
+ console.print(
899
+ f"[blue]Running:[/blue] load case and configure services for {case_file}"
900
+ )
811
901
  try:
812
- state = build_full_state(case_file)
902
+ state = build_full_state(case_file, progress_callback=progress)
813
903
  except Exception as err:
814
- if _looks_like_connection_error(err):
904
+ if _looks_like_model_service_error(err):
815
905
  _print_model_connection_help(workspace, err)
816
906
  raise typer.Exit(code=1) from None
817
907
  raise
908
+ if events:
909
+ _render_initialization_events(events)
910
+ console.print(f"[blue]Running:[/blue] write initialization state to {output}")
818
911
  save_state(state, output)
819
912
  console.print(f"[green]Wrote full state[/green] {output}")
820
913
 
@@ -967,7 +1060,7 @@ def models_deploy(
967
1060
  None, help="Override vLLM max model length."
968
1061
  ),
969
1062
  pull: bool = typer.Option(
970
- True, "--pull/--no-pull", help="Download default asset if missing."
1063
+ True, "--download/--no-download", help="Download default asset if missing."
971
1064
  ),
972
1065
  background: bool = typer.Option(True, "--background/--foreground"),
973
1066
  dry_run: bool = typer.Option(
@@ -1121,11 +1214,17 @@ def chat(
1121
1214
  console.print(Rule("[bold blue]Stage 1/2 · Initialize[/bold blue]"))
1122
1215
  _configure(workspace)
1123
1216
  init_events: list[tuple[str, str]] = []
1217
+ compact_status: Any = None
1124
1218
 
1125
1219
  def progress(stage: str, detail: str) -> None:
1126
1220
  init_events.append((stage, detail))
1127
1221
  if debug_ui:
1128
1222
  console.print(f"[dim]• {escape(stage)}[/dim] {escape(detail)}")
1223
+ else:
1224
+ message = f"正在运行:{detail}"
1225
+ if compact_status is not None:
1226
+ compact_status.update(f"[blue]{escape(message)}...[/blue]")
1227
+ console.print(f"[blue]{escape(message)}[/blue]")
1129
1228
 
1130
1229
  if state:
1131
1230
  _render_config_summary(
@@ -1151,22 +1250,26 @@ def chat(
1151
1250
  progress_callback=progress,
1152
1251
  )
1153
1252
  except Exception as err:
1154
- if _looks_like_connection_error(err):
1253
+ if _looks_like_model_service_error(err):
1155
1254
  _print_model_connection_help(workspace, err)
1156
1255
  raise typer.Exit(code=1) from None
1157
1256
  raise
1158
1257
  else:
1159
1258
  try:
1160
- with console.status("[blue]初始化来访者状态...[/blue]"):
1161
- with _suppress_stdio(True):
1162
- seeker = MsPatient(
1163
- portrait,
1164
- report,
1165
- conversations,
1166
- progress_callback=progress,
1167
- )
1259
+ with console.status(
1260
+ "[blue]正在运行:初始化来访者状态...[/blue]"
1261
+ ) as status:
1262
+ compact_status = status
1263
+ seeker = MsPatient(
1264
+ portrait,
1265
+ report,
1266
+ conversations,
1267
+ progress_callback=progress,
1268
+ )
1269
+ compact_status = None
1168
1270
  except Exception as err:
1169
- if _looks_like_connection_error(err):
1271
+ compact_status = None
1272
+ if _looks_like_model_service_error(err):
1170
1273
  _print_model_connection_help(workspace, err)
1171
1274
  raise typer.Exit(code=1) from None
1172
1275
  raise
@@ -1215,12 +1318,18 @@ def run_batch(
1215
1318
  output.mkdir(parents=True, exist_ok=True)
1216
1319
  summary_path = output / "summary.jsonl"
1217
1320
  for case_file in case_files:
1218
- state = (
1219
- build_full_state(case_file)
1220
- if mode == "full"
1221
- else build_prompt_only_state(case_file)
1222
- )
1321
+ console.print(f"[blue]Running:[/blue] build {mode} state for {case_file}")
1322
+ if mode == "full":
1323
+ state = build_full_state(
1324
+ case_file,
1325
+ progress_callback=lambda stage, detail: console.print(
1326
+ f"[blue]Running {escape(stage)}:[/blue] {escape(detail)}"
1327
+ ),
1328
+ )
1329
+ else:
1330
+ state = build_prompt_only_state(case_file)
1223
1331
  state_path = output / f"{state['case_id']}.state.json"
1332
+ console.print(f"[blue]Running:[/blue] write state to {state_path}")
1224
1333
  save_state(state, state_path)
1225
1334
  record = {
1226
1335
  "case_id": state["case_id"],
@@ -1230,7 +1339,11 @@ def run_batch(
1230
1339
  if live and messages:
1231
1340
  session = FrozenPromptSession(state)
1232
1341
  transcript_path = output / f"{state['case_id']}.transcript.jsonl"
1233
- for message in messages:
1342
+ for index, message in enumerate(messages, start=1):
1343
+ console.print(
1344
+ f"[blue]Running:[/blue] live scripted turn {index} "
1345
+ f"for {state['case_id']}"
1346
+ )
1234
1347
  response = session.chat(message)
1235
1348
  append_jsonl(transcript_path, {"role": "Counselor", "content": message})
1236
1349
  append_jsonl(transcript_path, {"role": "Seeker", "content": response})