coze-coding-dev-sdk 0.4.1__tar.gz → 0.4.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 (42) hide show
  1. {coze_coding_dev_sdk-0.4.1/coze_coding_dev_sdk.egg-info → coze_coding_dev_sdk-0.4.2}/PKG-INFO +5 -1
  2. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/README.md +4 -0
  3. coze_coding_dev_sdk-0.4.2/coze_coding_dev_sdk/cli/constants.py +7 -0
  4. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/image.py +69 -33
  5. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/video.py +90 -51
  6. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/voice.py +136 -66
  7. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/core/client.py +7 -1
  8. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/image/client.py +30 -28
  9. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/search/client.py +31 -39
  10. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/video/client.py +8 -3
  11. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/voice/asr.py +8 -3
  12. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/voice/tts.py +8 -3
  13. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2/coze_coding_dev_sdk.egg-info}/PKG-INFO +5 -1
  14. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk.egg-info/SOURCES.txt +1 -0
  15. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/pyproject.toml +1 -1
  16. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/CHANGELOG.md +0 -0
  17. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/LICENSE +0 -0
  18. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/MANIFEST.in +0 -0
  19. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/__init__.py +0 -0
  20. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/__init__.py +0 -0
  21. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/chat.py +0 -0
  22. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/cli.py +0 -0
  23. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/cli/search.py +0 -0
  24. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/core/__init__.py +0 -0
  25. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/core/config.py +0 -0
  26. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/core/exceptions.py +0 -0
  27. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/image/__init__.py +0 -0
  28. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/image/models.py +0 -0
  29. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/llm/__init__.py +0 -0
  30. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/llm/client.py +0 -0
  31. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/llm/models.py +0 -0
  32. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/search/__init__.py +0 -0
  33. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/search/models.py +0 -0
  34. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/video/__init__.py +0 -0
  35. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/video/models.py +0 -0
  36. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/voice/__init__.py +0 -0
  37. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk/voice/models.py +0 -0
  38. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk.egg-info/dependency_links.txt +0 -0
  39. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk.egg-info/entry_points.txt +0 -0
  40. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk.egg-info/requires.txt +0 -0
  41. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/coze_coding_dev_sdk.egg-info/top_level.txt +0 -0
  42. {coze_coding_dev_sdk-0.4.1 → coze_coding_dev_sdk-0.4.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coze-coding-dev-sdk
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Coze Coding Dev SDK - 优雅的多功能 AI SDK,支持图片生成、视频生成、语音合成、语音识别、大语言模型和联网搜索。包含命令行工具 coze-coding-ai,支持 Context 上下文追踪
5
5
  Author-email: Coze Coding Integration Team <support@coze.com>
6
6
  Maintainer-email: Coze Coding Integration Team <support@coze.com>
@@ -513,6 +513,10 @@ coze-coding-ai video \
513
513
 
514
514
  # 查询任务状态
515
515
  coze-coding-ai video-status <task-id>
516
+
517
+ # Mock 模式(测试运行,不消耗配额)
518
+ coze-coding-ai video -p "Test video" --mock --poll
519
+ coze-coding-ai video-status <task-id> --mock
516
520
  ```
517
521
 
518
522
  ### Chat 对话
@@ -470,6 +470,10 @@ coze-coding-ai video \
470
470
 
471
471
  # 查询任务状态
472
472
  coze-coding-ai video-status <task-id>
473
+
474
+ # Mock 模式(测试运行,不消耗配额)
475
+ coze-coding-ai video -p "Test video" --mock --poll
476
+ coze-coding-ai video-status <task-id> --mock
473
477
  ```
474
478
 
475
479
  ### Chat 对话
@@ -0,0 +1,7 @@
1
+ """
2
+ CLI 常量定义
3
+ """
4
+
5
+ RUN_MODE_HEADER = "x-run-mode"
6
+ RUN_MODE_TEST = "test_run"
7
+ RUN_MODE_PRODUCTION = "production"
@@ -1,11 +1,15 @@
1
- import os
2
1
  import base64
2
+ import os
3
+ import time
3
4
  from typing import Optional
5
+
4
6
  import click
7
+ from coze_coding_utils.runtime_ctx.context import Context
5
8
  from rich.console import Console
6
9
 
7
- from ..image import ImageGenerationClient
8
10
  from ..core.config import Config
11
+ from ..image import ImageGenerationClient
12
+ from .constants import RUN_MODE_HEADER, RUN_MODE_TEST
9
13
 
10
14
  console = Console()
11
15
 
@@ -13,41 +17,70 @@ console = Console()
13
17
  def validate_and_normalize_size(size: str) -> str:
14
18
  if size in ["2K", "4K"]:
15
19
  return size
16
-
20
+
17
21
  try:
18
- width, height = size.split('x')
22
+ width, height = size.split("x")
19
23
  w, h = int(width), int(height)
20
-
24
+
21
25
  if 2560 <= w <= 4096 and 1440 <= h <= 4096:
22
26
  return size
23
27
  else:
24
- console.print(f"[yellow]Warning: Size {size} is out of range [2560x1440, 4096x4096], using default 2K[/yellow]")
28
+ console.print(
29
+ f"[yellow]Warning: Size {size} is out of range [2560x1440, 4096x4096], using default 2K[/yellow]"
30
+ )
25
31
  return "2K"
26
32
  except (ValueError, AttributeError):
27
- console.print(f"[yellow]Warning: Invalid size format {size}, using default 2K[/yellow]")
33
+ console.print(
34
+ f"[yellow]Warning: Invalid size format {size}, using default 2K[/yellow]"
35
+ )
28
36
  return "2K"
29
37
 
30
38
 
31
39
  @click.command()
32
40
  @click.option("--prompt", "-p", required=True, help="Text description of the image")
33
- @click.option("--output", "-o", required=True, type=click.Path(), help="Output file path")
34
- @click.option("--size", "-s", default="2K", help="Image size (2K, 4K, or WIDTHxHEIGHT in range [2560x1440, 4096x4096])")
35
- @click.option("--image", "-i", help="Reference image URL or path (for image-to-image generation)")
36
- @click.option("--images", multiple=True, help="Multiple reference image URLs or paths (can be used multiple times)")
37
- def image(prompt: str, output: str, size: str, image: Optional[str], images: tuple):
41
+ @click.option(
42
+ "--output", "-o", required=True, type=click.Path(), help="Output file path"
43
+ )
44
+ @click.option(
45
+ "--size",
46
+ "-s",
47
+ default="2K",
48
+ help="Image size (2K, 4K, or WIDTHxHEIGHT in range [2560x1440, 4096x4096])",
49
+ )
50
+ @click.option(
51
+ "--image", "-i", help="Reference image URL or path (for image-to-image generation)"
52
+ )
53
+ @click.option(
54
+ "--images",
55
+ multiple=True,
56
+ help="Multiple reference image URLs or paths (can be used multiple times)",
57
+ )
58
+ @click.option("--mock", is_flag=True, help="使用 mock 模式(测试运行)")
59
+ def image(
60
+ prompt: str, output: str, size: str, image: Optional[str], images: tuple, mock: bool
61
+ ):
38
62
  """Generate image using AI."""
39
63
  try:
40
64
  config = Config()
41
- client = ImageGenerationClient(config)
42
-
65
+
66
+ ctx = None
67
+ if mock:
68
+ ctx = Context(
69
+ request_id=f"mock-req-{int(time.time())}",
70
+ headers={RUN_MODE_HEADER: RUN_MODE_TEST},
71
+ )
72
+ console.print("[yellow]🧪 Mock 模式已启用(测试运行)[/yellow]")
73
+
74
+ client = ImageGenerationClient(config, ctx=ctx)
75
+
43
76
  reference_images = None
44
77
  if image:
45
78
  reference_images = image
46
79
  elif images:
47
80
  reference_images = list(images)
48
-
81
+
49
82
  validated_size = validate_and_normalize_size(size)
50
-
83
+
51
84
  console.print(f"[bold cyan]Generating image...[/bold cyan]")
52
85
  console.print(f"Prompt: [yellow]{prompt}[/yellow]")
53
86
  console.print(f"Size: [yellow]{validated_size}[/yellow]")
@@ -55,48 +88,51 @@ def image(prompt: str, output: str, size: str, image: Optional[str], images: tup
55
88
  if isinstance(reference_images, str):
56
89
  console.print(f"Reference image: [blue]{reference_images}[/blue]")
57
90
  else:
58
- console.print(f"Reference images: [blue]{len(reference_images)} images[/blue]")
59
-
91
+ console.print(
92
+ f"Reference images: [blue]{len(reference_images)} images[/blue]"
93
+ )
94
+
60
95
  response = client.generate(
61
96
  prompt=prompt,
62
97
  size=validated_size,
63
98
  image=reference_images,
64
- response_format="b64_json"
99
+ response_format="b64_json",
65
100
  )
66
-
101
+
67
102
  if not response.data or len(response.data) == 0:
68
103
  raise ValueError("No image data returned")
69
-
104
+
70
105
  image_data = response.data[0]
71
-
106
+
72
107
  if image_data.error:
73
- error_msg = image_data.error.get('message', 'Unknown error')
108
+ error_msg = image_data.error.get("message", "Unknown error")
74
109
  raise Exception(f"Image generation failed: {error_msg}")
75
-
110
+
76
111
  if image_data.b64_json:
77
112
  image_bytes = base64.b64decode(image_data.b64_json)
78
-
113
+
79
114
  os.makedirs(os.path.dirname(os.path.abspath(output)), exist_ok=True)
80
-
81
- with open(output, 'wb') as f:
115
+
116
+ with open(output, "wb") as f:
82
117
  f.write(image_bytes)
83
-
118
+
84
119
  console.print(f"[green]✓[/green] Image saved to: [bold]{output}[/bold]")
85
120
  elif image_data.url:
86
121
  import requests
122
+
87
123
  img_response = requests.get(image_data.url)
88
124
  img_response.raise_for_status()
89
-
125
+
90
126
  os.makedirs(os.path.dirname(os.path.abspath(output)), exist_ok=True)
91
-
92
- with open(output, 'wb') as f:
127
+
128
+ with open(output, "wb") as f:
93
129
  f.write(img_response.content)
94
-
130
+
95
131
  console.print(f"[green]✓[/green] Image saved to: [bold]{output}[/bold]")
96
132
  console.print(f"Original URL: [blue]{image_data.url}[/blue]")
97
133
  else:
98
134
  raise ValueError("No image data (b64_json or url) in response")
99
-
135
+
100
136
  except Exception as e:
101
137
  console.print(f"[red]✗ Error: {str(e)}[/red]")
102
138
  raise click.Abort()
@@ -1,15 +1,18 @@
1
- import time
2
1
  import json
3
2
  import os
3
+ import time
4
4
  from typing import Optional
5
+
5
6
  import click
7
+ from coze_coding_utils.runtime_ctx.context import Context
6
8
  from rich.console import Console
7
9
  from rich.progress import Progress, SpinnerColumn, TextColumn
8
10
  from rich.table import Table
9
11
 
10
- from ..video import VideoGenerationClient, VideoConfig
11
12
  from ..core.config import Config
12
13
  from ..core.exceptions import APIError
14
+ from ..video import VideoConfig, VideoGenerationClient
15
+ from .constants import RUN_MODE_HEADER, RUN_MODE_TEST
13
16
 
14
17
  console = Console()
15
18
 
@@ -17,10 +20,10 @@ console = Console()
17
20
  def parse_resolution(size: Optional[str]) -> tuple[Optional[str], Optional[str]]:
18
21
  if not size:
19
22
  return None, None
20
-
21
- width, height = size.split('x')
23
+
24
+ width, height = size.split("x")
22
25
  w, h = int(width), int(height)
23
-
26
+
24
27
  if w == h:
25
28
  return "1:1", "720p" if w <= 1024 else "1080p"
26
29
  elif w > h:
@@ -32,16 +35,25 @@ def parse_resolution(size: Optional[str]) -> tuple[Optional[str], Optional[str]]
32
35
  @click.command()
33
36
  @click.option("--prompt", "-p", help="Text description of the video")
34
37
  @click.option("--image-url", "-i", help="Image URL (single or comma-separated pair)")
35
- @click.option("--quality", "-q", type=click.Choice(["speed", "quality"]), default="speed", help="Output mode")
38
+ @click.option(
39
+ "--quality",
40
+ "-q",
41
+ type=click.Choice(["speed", "quality"]),
42
+ default="speed",
43
+ help="Output mode",
44
+ )
36
45
  @click.option("--with-audio", is_flag=True, help="Generate AI audio effects")
37
46
  @click.option("--size", "-s", help="Video resolution (e.g., 1920x1080)")
38
47
  @click.option("--fps", type=int, help="Frame rate (30 or 60)")
39
48
  @click.option("--duration", "-d", type=int, help="Duration in seconds (5 or 10)")
40
49
  @click.option("--model", "-m", help="Model name to use")
41
50
  @click.option("--poll", is_flag=True, help="Auto-poll until task completes")
42
- @click.option("--poll-interval", type=int, default=5, help="Polling interval in seconds")
51
+ @click.option(
52
+ "--poll-interval", type=int, default=5, help="Polling interval in seconds"
53
+ )
43
54
  @click.option("--max-polls", type=int, default=60, help="Maximum poll attempts")
44
55
  @click.option("--output", "-o", type=click.Path(), help="Output file path (JSON)")
56
+ @click.option("--mock", is_flag=True, help="使用 mock 模式(测试运行)")
45
57
  def video(
46
58
  prompt: Optional[str],
47
59
  image_url: Optional[str],
@@ -54,38 +66,48 @@ def video(
54
66
  poll: bool,
55
67
  poll_interval: int,
56
68
  max_polls: int,
57
- output: Optional[str]
69
+ output: Optional[str],
70
+ mock: bool,
58
71
  ):
59
72
  """Generate video using AI."""
60
73
  try:
61
74
  config = Config()
62
- client = VideoGenerationClient(config)
63
-
75
+
76
+ ctx = None
77
+ if mock:
78
+ ctx = Context(
79
+ request_id=f"mock-req-{int(time.time())}",
80
+ headers={RUN_MODE_HEADER: RUN_MODE_TEST},
81
+ )
82
+ console.print("[yellow]🧪 Mock 模式已启用(测试运行)[/yellow]")
83
+
84
+ client = VideoGenerationClient(config, ctx=ctx)
85
+
64
86
  image_urls = None
65
87
  if image_url:
66
88
  image_urls = [url.strip() for url in image_url.split(",")]
67
-
89
+
68
90
  ratio, resolution = parse_resolution(size)
69
-
91
+
70
92
  video_config = VideoConfig(
71
93
  resolution=resolution or "720p",
72
94
  ratio=ratio or "16:9",
73
- duration=duration or 5
95
+ duration=duration or 5,
74
96
  )
75
-
97
+
76
98
  console.print("[bold cyan]Creating video generation task...[/bold cyan]")
77
-
99
+
78
100
  model_name = model or "doubao-seedance-1-0-pro-250528"
79
-
101
+
80
102
  if image_urls:
81
103
  if len(image_urls) == 1:
82
104
  task_id = client._create_task(
83
105
  model=model_name,
84
106
  content=[
85
107
  {"type": "text", "text": prompt or ""},
86
- {"type": "image_url", "image_url": {"url": image_urls[0]}}
108
+ {"type": "image_url", "image_url": {"url": image_urls[0]}},
87
109
  ],
88
- config=video_config
110
+ config=video_config,
89
111
  )
90
112
  elif len(image_urls) == 2:
91
113
  task_id = client._create_task(
@@ -93,78 +115,85 @@ def video(
93
115
  content=[
94
116
  {"type": "text", "text": prompt or ""},
95
117
  {"type": "image_url", "image_url": {"url": image_urls[0]}},
96
- {"type": "image_url", "image_url": {"url": image_urls[1]}}
118
+ {"type": "image_url", "image_url": {"url": image_urls[1]}},
97
119
  ],
98
- config=video_config
120
+ config=video_config,
99
121
  )
100
122
  else:
101
123
  raise ValueError("Only 1 or 2 images are supported")
102
124
  else:
103
125
  if not prompt:
104
126
  raise ValueError("Either --prompt or --image-url must be provided")
105
-
127
+
106
128
  task_id = client._create_task(
107
129
  model=model_name,
108
130
  content=[{"type": "text", "text": prompt}],
109
- config=video_config
131
+ config=video_config,
110
132
  )
111
-
133
+
112
134
  console.print(f"[green]✓[/green] Task created: [bold]{task_id}[/bold]")
113
-
135
+
114
136
  result = {"id": task_id, "status": "processing"}
115
-
137
+
116
138
  if poll:
117
139
  with Progress(
118
140
  SpinnerColumn(),
119
141
  TextColumn("[progress.description]{task.description}"),
120
- console=console
142
+ console=console,
121
143
  ) as progress:
122
144
  task = progress.add_task(
123
- f"[cyan]Generating video (Task ID: {task_id})...",
124
- total=None
145
+ f"[cyan]Generating video (Task ID: {task_id})...", total=None
125
146
  )
126
-
147
+
127
148
  max_wait_time = poll_interval * max_polls
128
149
  start_time = time.time()
129
-
150
+
130
151
  while time.time() - start_time < max_wait_time:
131
152
  task_result = client._get_task_status(task_id)
132
-
153
+
133
154
  if task_result.status == "completed":
134
- progress.update(task, description="[green]✓ Video generation completed!")
155
+ progress.update(
156
+ task, description="[green]✓ Video generation completed!"
157
+ )
135
158
  result = task_result.model_dump()
136
159
  break
137
160
  elif task_result.status == "failed":
138
- progress.update(task, description=f"[red]✗ Video generation failed")
161
+ progress.update(
162
+ task, description=f"[red]✗ Video generation failed"
163
+ )
139
164
  result = task_result.model_dump()
140
165
  break
141
-
166
+
142
167
  time.sleep(poll_interval)
143
168
  else:
144
- raise TimeoutError(f"Task did not complete within {max_wait_time} seconds")
145
-
169
+ raise TimeoutError(
170
+ f"Task did not complete within {max_wait_time} seconds"
171
+ )
172
+
146
173
  table = Table(title="Video Generation Result")
147
174
  table.add_column("Field", style="cyan")
148
175
  table.add_column("Value", style="green")
149
-
176
+
150
177
  table.add_row("Task ID", result.get("id", ""))
151
178
  table.add_row("Status", result.get("status", ""))
152
-
179
+
153
180
  if result.get("video_url"):
154
181
  table.add_row("Video URL", result.get("video_url"))
155
182
  if result.get("error_message"):
156
183
  table.add_row("Error", result.get("error_message"))
157
-
184
+
158
185
  console.print(table)
159
186
  else:
160
- console.print(f"\n[yellow]Use the following command to check status:[/yellow]")
187
+ console.print(
188
+ f"\n[yellow]Use the following command to check status:[/yellow]"
189
+ )
161
190
  console.print(f"coze-coding-ai video-status {task_id}")
162
-
191
+
163
192
  if output:
164
193
  with open(output, "w") as f:
165
194
  json.dump(result, f, indent=2)
166
195
  console.print(f"\n[green]✓[/green] Result saved to: {output}")
167
-
196
+
168
197
  except Exception as e:
169
198
  console.print(f"[red]✗ Error: {str(e)}[/red]")
170
199
  raise click.Abort()
@@ -173,34 +202,44 @@ def video(
173
202
  @click.command()
174
203
  @click.argument("task_id")
175
204
  @click.option("--output", "-o", type=click.Path(), help="Output file path (JSON)")
176
- def video_status(task_id: str, output: Optional[str]):
205
+ @click.option("--mock", is_flag=True, help="使用 mock 模式(测试运行)")
206
+ def video_status(task_id: str, output: Optional[str], mock: bool):
177
207
  """Check video generation task status."""
178
208
  try:
179
209
  config = Config()
180
- client = VideoGenerationClient(config)
181
-
210
+
211
+ ctx = None
212
+ if mock:
213
+ ctx = Context(
214
+ request_id=f"mock-req-{int(time.time())}",
215
+ headers={RUN_MODE_HEADER: RUN_MODE_TEST},
216
+ )
217
+ console.print("[yellow]🧪 Mock 模式已启用(测试运行)[/yellow]")
218
+
219
+ client = VideoGenerationClient(config, ctx=ctx)
220
+
182
221
  task_result = client._get_task_status(task_id)
183
222
  result = task_result.model_dump()
184
-
223
+
185
224
  table = Table(title=f"Task Status: {task_id}")
186
225
  table.add_column("Field", style="cyan")
187
226
  table.add_column("Value", style="green")
188
-
227
+
189
228
  table.add_row("Task ID", result.get("id", ""))
190
229
  table.add_row("Status", result.get("status", ""))
191
-
230
+
192
231
  if result.get("video_url"):
193
232
  table.add_row("Video URL", result.get("video_url"))
194
233
  if result.get("error_message"):
195
234
  table.add_row("Error", result.get("error_message"))
196
-
235
+
197
236
  console.print(table)
198
-
237
+
199
238
  if output:
200
239
  with open(output, "w") as f:
201
240
  json.dump(result, f, indent=2)
202
241
  console.print(f"\n[green]✓[/green] Result saved to: {output}")
203
-
242
+
204
243
  except Exception as e:
205
244
  console.print(f"[red]✗ Error: {str(e)}[/red]")
206
245
  raise click.Abort()