coze-coding-dev-sdk 0.5.18__tar.gz → 0.5.20__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.

Potentially problematic release.


This version of coze-coding-dev-sdk might be problematic. Click here for more details.

Files changed (110) hide show
  1. {coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk.egg-info → coze_coding_dev_sdk-0.5.20}/PKG-INFO +7 -2
  2. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/README.md +1 -1
  3. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/cli/db.py +96 -0
  4. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/cli/supabase.py +139 -0
  5. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/core/__init__.py +12 -0
  6. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/core/client.py +37 -31
  7. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/config.py +97 -0
  8. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/desktop_credential.py +37 -0
  9. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/developer_credential.py +46 -0
  10. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/endpoints.py +8 -0
  11. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/integration_request.py +51 -0
  12. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/project_env.py +109 -0
  13. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/runtime.py +207 -0
  14. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/core/runtime_resource_cache.py +61 -0
  15. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/database/__init__.py +2 -0
  16. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/database/client.py +35 -26
  17. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/database/environment.py +45 -0
  18. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/database/migration.py +24 -17
  19. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/database/setup.py +45 -0
  20. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/fetch/client.py +4 -3
  21. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/llm/client.py +3 -2
  22. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/client.py +14 -18
  23. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/s3/__init__.py +2 -0
  24. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/s3/client.py +116 -72
  25. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/s3/environment.py +57 -0
  26. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/s3/setup.py +36 -0
  27. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/supabase/__init__.py +31 -0
  28. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/supabase/client.py +164 -0
  29. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/supabase/models.py +96 -0
  30. coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk/supabase/setup.py +47 -0
  31. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video/client.py +4 -4
  32. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video/models.py +1 -1
  33. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20/coze_coding_dev_sdk.egg-info}/PKG-INFO +7 -2
  34. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk.egg-info/SOURCES.txt +12 -0
  35. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk.egg-info/requires.txt +5 -0
  36. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/pyproject.toml +6 -1
  37. coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk/cli/db.py +0 -156
  38. coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk/cli/supabase.py +0 -727
  39. coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk/core/config.py +0 -58
  40. coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk/supabase/__init__.py +0 -57
  41. coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk/supabase/client.py +0 -494
  42. coze_coding_dev_sdk-0.5.18/coze_coding_dev_sdk/supabase/models.py +0 -244
  43. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/CHANGELOG.md +0 -0
  44. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/LICENSE +0 -0
  45. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/MANIFEST.in +0 -0
  46. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/__init__.py +0 -0
  47. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/__init__.py +0 -0
  48. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/chat.py +0 -0
  49. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/cli.py +0 -0
  50. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/constants.py +0 -0
  51. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/document.py +0 -0
  52. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/embedding.py +0 -0
  53. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/image.py +0 -0
  54. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/knowledge.py +0 -0
  55. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/search.py +0 -0
  56. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/storage.py +0 -0
  57. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/utils.py +0 -0
  58. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/video.py +0 -0
  59. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/video_edit.py +0 -0
  60. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/cli/voice.py +0 -0
  61. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/core/exceptions.py +0 -0
  62. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/core/url_utils.py +0 -0
  63. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/__init__.py +0 -0
  64. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/client.py +0 -0
  65. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/docx_generator.py +0 -0
  66. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/models.py +0 -0
  67. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/pdf_generator.py +0 -0
  68. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/pptx_generator.py +0 -0
  69. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/document/xlsx_generator.py +0 -0
  70. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/embedding/__init__.py +0 -0
  71. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/embedding/client.py +0 -0
  72. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/embedding/models.py +0 -0
  73. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/fetch/__init__.py +0 -0
  74. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/fetch/models.py +0 -0
  75. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/image/__init__.py +0 -0
  76. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/image/client.py +0 -0
  77. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/image/models.py +0 -0
  78. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/knowledge/__init__.py +0 -0
  79. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/knowledge/client.py +0 -0
  80. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/knowledge/models.py +0 -0
  81. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/llm/__init__.py +0 -0
  82. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/llm/models.py +0 -0
  83. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/memory/__init__.py +0 -0
  84. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/memory/client.py +0 -0
  85. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/__init__.py +0 -0
  86. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/buffer.py +0 -0
  87. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/interceptors/__init__.py +0 -0
  88. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/interceptors/boto3_hook.py +0 -0
  89. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/interceptors/httpx_transport.py +0 -0
  90. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/models.py +0 -0
  91. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/singleton.py +0 -0
  92. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/report/utils.py +0 -0
  93. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/s3/models.py +0 -0
  94. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/search/__init__.py +0 -0
  95. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/search/client.py +0 -0
  96. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/search/models.py +0 -0
  97. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video/__init__.py +0 -0
  98. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video_edit/__init__.py +0 -0
  99. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video_edit/examples.py +0 -0
  100. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video_edit/frame_extractor.py +0 -0
  101. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video_edit/models.py +0 -0
  102. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/video_edit/video_edit.py +0 -0
  103. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/voice/__init__.py +0 -0
  104. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/voice/asr.py +0 -0
  105. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/voice/models.py +0 -0
  106. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk/voice/tts.py +0 -0
  107. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk.egg-info/dependency_links.txt +0 -0
  108. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk.egg-info/entry_points.txt +0 -0
  109. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/coze_coding_dev_sdk.egg-info/top_level.txt +0 -0
  110. {coze_coding_dev_sdk-0.5.18 → coze_coding_dev_sdk-0.5.20}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coze-coding-dev-sdk
3
- Version: 0.5.18
3
+ Version: 0.5.20
4
4
  Summary: Coze Coding Dev SDK - 优雅的多功能 AI SDK,支持图片生成、视频生成、语音合成、语音识别、大语言模型、联网搜索和文本/多模态 Embedding。包含命令行工具 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>
@@ -44,8 +44,13 @@ Requires-Dist: click>=8.0.0
44
44
  Requires-Dist: rich>=13.0.0
45
45
  Requires-Dist: supabase==2.27.3
46
46
  Requires-Dist: httpx==0.28.1
47
+ Requires-Dist: beautifulsoup4>=4.12.0
47
48
  Requires-Dist: markdown>=3.0.0
49
+ Requires-Dist: numpy>=1.26.0
50
+ Requires-Dist: openpyxl>=3.1.0
51
+ Requires-Dist: Pillow>=10.0.0
48
52
  Requires-Dist: python-docx>=1.0.0
53
+ Requires-Dist: python-pptx>=1.0.0
49
54
  Requires-Dist: reportlab>=4.0.0
50
55
  Requires-Dist: cssutils>=2.0.0
51
56
  Provides-Extra: dev
@@ -107,7 +112,7 @@ pip install -e ".[dev]"
107
112
  #### 必需配置
108
113
 
109
114
  ```bash
110
- export COZE_WORKLOAD_IDENTITY_API_KEY="your_api_key"
115
+ export COZE_API_TOKEN="your_user_token"
111
116
  export COZE_INTEGRATION_BASE_URL="https://api.coze.com"
112
117
  export COZE_INTEGRATION_MODEL_BASE_URL="https://model.coze.com"
113
118
  ```
@@ -50,7 +50,7 @@ pip install -e ".[dev]"
50
50
  #### 必需配置
51
51
 
52
52
  ```bash
53
- export COZE_WORKLOAD_IDENTITY_API_KEY="your_api_key"
53
+ export COZE_API_TOKEN="your_user_token"
54
54
  export COZE_INTEGRATION_BASE_URL="https://api.coze.com"
55
55
  export COZE_INTEGRATION_MODEL_BASE_URL="https://model.coze.com"
56
56
  ```
@@ -0,0 +1,96 @@
1
+ """
2
+ 数据库 CLI 命令
3
+ """
4
+
5
+ import os
6
+
7
+ import click
8
+ from rich.console import Console
9
+
10
+ # 默认路径
11
+ DEFAULT_MODEL_OUTPUT = "src/storage/database/shared/model.py"
12
+ DEFAULT_MODEL_IMPORT_PATH = "storage.database.shared.model"
13
+ DEFAULT_MODEL_PATH = "src"
14
+
15
+ console = Console()
16
+
17
+
18
+ def _get_workspace_path() -> str:
19
+ """获取工程根目录:`.env` 的 PROJECT_PATH 优先,其次环境变量 WORKSPACE_PATH。
20
+
21
+ 两者都读不到即明确报错(不静默退回 cwd,避免把文件写到错误目录)。
22
+ """
23
+ from coze_coding_dev_sdk.core.runtime import resolve_workspace_path
24
+
25
+ workspace = resolve_workspace_path()
26
+ if not workspace:
27
+ console.print(
28
+ "[red]未能确定工程根目录:请在当前目录 .env 中设置 PROJECT_PATH"
29
+ "(或由运行时注入 WORKSPACE_PATH)。[/red]"
30
+ )
31
+ raise SystemExit(1)
32
+ return workspace
33
+
34
+
35
+ @click.group()
36
+ def db():
37
+ """Database management commands."""
38
+ pass
39
+
40
+
41
+ @db.command()
42
+ @click.argument("output_path", required=False, default=None)
43
+ @click.option("--verbose", "-v", is_flag=True, help="Verbose output")
44
+ def generate_models(output_path: str, verbose: bool):
45
+ """
46
+ Generate ORM models from database.
47
+
48
+ OUTPUT_PATH: Path to output model file (default: src/storage/database/shared/model.py)
49
+ """
50
+ from coze_coding_dev_sdk.database import generate_models as _generate_models
51
+
52
+ if output_path is None:
53
+ workspace = _get_workspace_path()
54
+ output_path = os.path.join(workspace, DEFAULT_MODEL_OUTPUT)
55
+
56
+ try:
57
+ _generate_models(output_path, verbose=verbose)
58
+ click.echo(f"Models generated at {output_path}")
59
+ except Exception as e:
60
+ click.echo(f"Error: {e}", err=True)
61
+ raise SystemExit(1)
62
+
63
+ @db.command()
64
+ @click.option(
65
+ "--model-import-path",
66
+ default=DEFAULT_MODEL_IMPORT_PATH,
67
+ help=f"Model import path (default: {DEFAULT_MODEL_IMPORT_PATH})",
68
+ )
69
+ @click.option(
70
+ "--model-path",
71
+ default=None,
72
+ help=f"Path to add to sys.path for model import (default: $WORKSPACE_PATH/{DEFAULT_MODEL_PATH})",
73
+ )
74
+ @click.option("--verbose", "-v", is_flag=True, help="Verbose output")
75
+ def upgrade(model_import_path: str, model_path: str, verbose: bool):
76
+ """
77
+ Run database migrations.
78
+
79
+ Automatically generates migration and upgrades to head.
80
+ """
81
+ from coze_coding_dev_sdk.database import upgrade as _upgrade
82
+
83
+ if model_path is None:
84
+ workspace = _get_workspace_path()
85
+ model_path = os.path.join(workspace, DEFAULT_MODEL_PATH)
86
+
87
+ try:
88
+ _upgrade(
89
+ model_import_path=model_import_path,
90
+ model_path=model_path,
91
+ verbose=verbose,
92
+ )
93
+ click.echo("Database upgraded successfully")
94
+ except Exception as e:
95
+ click.echo(f"Error: {e}", err=True)
96
+ raise SystemExit(1)
@@ -0,0 +1,139 @@
1
+ """Supabase Edge Function and Auth CLI; Storage CRUD uses the dedicated S3 command."""
2
+
3
+ import json
4
+ from typing import Optional
5
+
6
+ import click
7
+ from rich.console import Console
8
+
9
+ from ..core.config import Config
10
+ from ..supabase import SupabaseClient
11
+ from .utils import parse_headers
12
+
13
+ console = Console()
14
+
15
+
16
+ @click.group()
17
+ def supabase():
18
+ """Supabase Edge Functions 与 Auth 配置管理命令。"""
19
+
20
+
21
+ @supabase.group("functions")
22
+ def functions():
23
+ """Edge Functions 管理命令。"""
24
+
25
+
26
+ @functions.command("list")
27
+ @click.option("--header", "-H", multiple=True, help="自定义 HTTP 请求头")
28
+ def functions_list(header: tuple):
29
+ """列出 Edge Functions。"""
30
+ response = SupabaseClient(Config(), custom_headers=parse_headers(header) or {}).list_functions()
31
+ if response.code != 0:
32
+ raise click.ClickException(response.msg)
33
+ console.print_json(json.dumps([item.__dict__ for item in response.functions], ensure_ascii=False))
34
+
35
+
36
+ @functions.command("get")
37
+ @click.argument("slug")
38
+ @click.option("--header", "-H", multiple=True, help="自定义 HTTP 请求头")
39
+ def functions_get(slug: str, header: tuple):
40
+ """获取 Edge Function 详情和源码。"""
41
+ response = SupabaseClient(Config(), custom_headers=parse_headers(header) or {}).get_function(slug)
42
+ if response.code != 0:
43
+ raise click.ClickException(response.msg)
44
+ console.print_json(json.dumps({"function": response.function.__dict__ if response.function else None, "files": [item.__dict__ for item in response.files]}, ensure_ascii=False))
45
+
46
+
47
+ @functions.command("deploy")
48
+ @click.argument("slug")
49
+ @click.option("--code", help="单文件函数源码")
50
+ @click.option("--file", "files", multiple=True, nargs=2, help="多文件函数的名称和内容对,可重复传入")
51
+ @click.option("--name")
52
+ @click.option("--entrypoint")
53
+ @click.option("--verify-jwt/--no-verify-jwt", default=None)
54
+ @click.option("--header", "-H", multiple=True, help="自定义 HTTP 请求头")
55
+ def functions_deploy(slug: str, code: Optional[str], files: tuple, name: Optional[str], entrypoint: Optional[str], verify_jwt: Optional[bool], header: tuple):
56
+ """部署或更新 Edge Function。"""
57
+ if not code and not files:
58
+ raise click.UsageError("必须提供 --code 或 --file")
59
+ options = {"code": code, "files": [{"name": item[0], "content": item[1]} for item in files] or None, "name": name, "entrypoint": entrypoint, "verify_jwt": verify_jwt}
60
+ response = SupabaseClient(Config(), custom_headers=parse_headers(header) or {}).deploy_function(slug, **{key: value for key, value in options.items() if value is not None})
61
+ if response.code != 0 or not response.success:
62
+ raise click.ClickException(response.msg or "Edge Function deployment failed")
63
+ console.print_json(json.dumps(response.__dict__, ensure_ascii=False))
64
+
65
+
66
+ @functions.command("delete")
67
+ @click.argument("slug")
68
+ @click.option("--header", "-H", multiple=True, help="自定义 HTTP 请求头")
69
+ def functions_delete(slug: str, header: tuple):
70
+ """删除 Edge Function。"""
71
+ response = SupabaseClient(Config(), custom_headers=parse_headers(header) or {}).delete_function(slug)
72
+ if response.code != 0 or not response.success:
73
+ raise click.ClickException(response.msg or "Edge Function deletion failed")
74
+ console.print_json(json.dumps(response.__dict__, ensure_ascii=False))
75
+
76
+
77
+ @supabase.group("auth")
78
+ def auth():
79
+ """Auth(认证配置)管理命令。"""
80
+
81
+
82
+ @auth.command("get-config-v2")
83
+ @click.option("--mock", is_flag=True, help="使用 mock 模式(测试运行,不会真正执行操作)")
84
+ @click.option("--header", "-H", multiple=True, help="自定义 HTTP 请求头")
85
+ def auth_get_config(mock: bool, header: tuple):
86
+ """获取 Auth 认证配置。"""
87
+ if mock:
88
+ console.print_json(json.dumps({"config": {}, "mock": True}))
89
+ return
90
+ response = SupabaseClient(Config(), custom_headers=parse_headers(header) or {}).get_auth_config_v2()
91
+ if response.code != 0 or response.status != 3:
92
+ raise click.ClickException(response.msg or f"Auth status={response.status}")
93
+ config = response.config
94
+ console.print_json(json.dumps({"status": response.status, "config": {
95
+ "project_id": config.project_id,
96
+ "icon_url": config.icon_url,
97
+ "name": config.name,
98
+ "email_config": config.email_config.__dict__ if config.email_config else None,
99
+ "phone_config": config.phone_config.__dict__ if config.phone_config else None,
100
+ }} if config else None, ensure_ascii=False))
101
+
102
+
103
+ @auth.command("update-config-v2")
104
+ @click.option("--name")
105
+ @click.option("--site-url")
106
+ @click.option("--disable-signup/--enable-signup", default=None)
107
+ @click.option("--external-email-enabled/--external-email-disabled", default=None)
108
+ @click.option("--external-phone-enabled/--external-phone-disabled", default=None)
109
+ @click.option("--mock", is_flag=True, help="使用 mock 模式(测试运行,不会真正执行操作)")
110
+ @click.option("--header", "-H", multiple=True, help="自定义 HTTP 请求头")
111
+ def auth_update_config(
112
+ name: Optional[str], site_url: Optional[str], disable_signup: Optional[bool],
113
+ external_email_enabled: Optional[bool], external_phone_enabled: Optional[bool],
114
+ mock: bool, header: tuple,
115
+ ):
116
+ """更新 Auth 认证配置(V2)。"""
117
+ payload = {}
118
+ if name is not None:
119
+ payload["app_name"] = name
120
+ email_config = {}
121
+ if site_url is not None:
122
+ email_config["site_url"] = site_url
123
+ if disable_signup is not None:
124
+ email_config["disable_signup"] = disable_signup
125
+ if external_email_enabled is not None:
126
+ email_config["external_email_enabled"] = external_email_enabled
127
+ if email_config:
128
+ payload["email_config"] = email_config
129
+ if external_phone_enabled is not None:
130
+ payload["phone_config"] = {"external_phone_enabled": external_phone_enabled}
131
+ if not payload:
132
+ raise click.UsageError("至少需要提供一个配置项")
133
+ if mock:
134
+ console.print_json(json.dumps({"success": True, "should_update_ui": False, "mock": True}))
135
+ return
136
+ response = SupabaseClient(Config(), custom_headers=parse_headers(header) or {}).update_auth_config_v2(payload)
137
+ if response.code != 0:
138
+ raise click.ClickException(response.msg)
139
+ console.print_json(json.dumps({"success": response.success, "should_update_ui": response.should_update_ui}))
@@ -1,5 +1,11 @@
1
1
  from .client import BaseClient
2
2
  from .config import Config
3
+ from .endpoints import (
4
+ IDE_API_BASE_URL,
5
+ INTEGRATION_BASE_URL,
6
+ INTEGRATION_MODEL_BASE_URL,
7
+ S3_PROXY_ENDPOINT_URL,
8
+ )
3
9
  from .exceptions import (
4
10
  CozeSDKError,
5
11
  ConfigurationError,
@@ -8,6 +14,7 @@ from .exceptions import (
8
14
  ValidationError
9
15
  )
10
16
  from .url_utils import validate_url, URLValidationError
17
+ from .runtime import runtime_platform
11
18
 
12
19
  try:
13
20
  from .. import __version__
@@ -17,10 +24,15 @@ except ImportError:
17
24
  __all__ = [
18
25
  "BaseClient",
19
26
  "Config",
27
+ "INTEGRATION_BASE_URL",
28
+ "INTEGRATION_MODEL_BASE_URL",
29
+ "IDE_API_BASE_URL",
30
+ "S3_PROXY_ENDPOINT_URL",
20
31
  "CozeSDKError",
21
32
  "ConfigurationError",
22
33
  "APIError",
23
34
  "NetworkError",
24
35
  "ValidationError",
36
+ "runtime_platform",
25
37
  "__version__",
26
38
  ]
@@ -14,6 +14,17 @@ from .exceptions import APIError, NetworkError
14
14
  console = Console()
15
15
 
16
16
 
17
+ def sanitize_payload_for_log(value):
18
+ if isinstance(value, dict):
19
+ return {
20
+ key: "[REDACTED]" if key.lower() in {"smtp_pass", "password", "secret"} else sanitize_payload_for_log(item)
21
+ for key, item in value.items()
22
+ }
23
+ if isinstance(value, list):
24
+ return [sanitize_payload_for_log(item) for item in value]
25
+ return value
26
+
27
+
17
28
  class BaseClient:
18
29
  def __init__(
19
30
  self,
@@ -41,8 +52,9 @@ class BaseClient:
41
52
  if self.custom_headers:
42
53
  request_headers.update(self.custom_headers)
43
54
 
44
- config_headers = self.config.get_headers(headers)
45
- request_headers.update(config_headers)
55
+ if headers:
56
+ request_headers.update(headers)
57
+ request_headers = self.config.get_headers(request_headers)
46
58
 
47
59
  response = self._make_request(
48
60
  method=method, url=url, headers=request_headers, **kwargs
@@ -61,8 +73,9 @@ class BaseClient:
61
73
  if self.custom_headers:
62
74
  request_headers.update(self.custom_headers)
63
75
 
64
- config_headers = self.config.get_headers(headers)
65
- request_headers.update(config_headers)
76
+ if headers:
77
+ request_headers.update(headers)
78
+ request_headers = self.config.get_headers(request_headers)
66
79
 
67
80
  response = self._make_request(
68
81
  method=method, url=url, headers=request_headers, **kwargs
@@ -81,8 +94,9 @@ class BaseClient:
81
94
  if self.custom_headers:
82
95
  request_headers.update(self.custom_headers)
83
96
 
84
- config_headers = self.config.get_headers(headers)
85
- request_headers.update(config_headers)
97
+ if headers:
98
+ request_headers.update(headers)
99
+ request_headers = self.config.get_headers(request_headers)
86
100
 
87
101
  kwargs["stream"] = True
88
102
  return self._make_request(
@@ -91,14 +105,14 @@ class BaseClient:
91
105
 
92
106
  def _sanitize_headers(self, headers: Dict[str, str]) -> Dict[str, str]:
93
107
  sanitized = headers.copy()
94
- if "Authorization" in sanitized:
95
- token = sanitized["Authorization"]
96
- if token.startswith("Bearer "):
97
- token = token[7:]
98
- if len(token) > 16:
99
- sanitized["Authorization"] = f"Bearer {token[:8]}...{token[-4:]}"
100
- else:
101
- sanitized["Authorization"] = "Bearer ****"
108
+ for key in list(sanitized):
109
+ if key.lower() not in {"authorization", "x-coze-token", "x-storage-token"}:
110
+ continue
111
+ token = str(sanitized[key])
112
+ if key.lower() == "authorization" and token.startswith("Bearer "):
113
+ sanitized[key] = "Bearer ****"
114
+ else:
115
+ sanitized[key] = "****"
102
116
  return sanitized
103
117
 
104
118
  def _log_request(self, method: str, url: str, **kwargs):
@@ -119,7 +133,7 @@ class BaseClient:
119
133
  if "json" in kwargs and kwargs["json"]:
120
134
  parts.append("[bold]Body:[/bold]")
121
135
  try:
122
- json_str = json.dumps(kwargs["json"], ensure_ascii=False, indent=2)
136
+ json_str = json.dumps(sanitize_payload_for_log(kwargs["json"]), ensure_ascii=False, indent=2)
123
137
  parts.append("")
124
138
  except Exception:
125
139
  json_str = str(kwargs["json"])
@@ -136,7 +150,7 @@ class BaseClient:
136
150
 
137
151
  if "json" in kwargs and kwargs["json"]:
138
152
  try:
139
- json_str = json.dumps(kwargs["json"], ensure_ascii=False, indent=2)
153
+ json_str = json.dumps(sanitize_payload_for_log(kwargs["json"]), ensure_ascii=False, indent=2)
140
154
  console.print(
141
155
  Syntax(json_str, "json", theme="monokai", line_numbers=False)
142
156
  )
@@ -184,16 +198,10 @@ class BaseClient:
184
198
  )
185
199
 
186
200
  try:
187
- response_data = response.json()
188
- json_str = json.dumps(response_data, ensure_ascii=False, indent=2)
189
- if len(json_str) > 2000:
190
- json_str = json_str[:2000] + "\n... (truncated)"
191
- console.print(Syntax(json_str, "json", theme="monokai", line_numbers=False))
201
+ response.json()
202
+ console.print(" [response body redacted]")
192
203
  except Exception:
193
- body_text = response.text[:500]
194
- if len(response.text) > 500:
195
- body_text += "... (truncated)"
196
- console.print(f" {body_text}")
204
+ console.print(" [non-JSON response body redacted]")
197
205
 
198
206
  console.print()
199
207
 
@@ -226,10 +234,10 @@ class BaseClient:
226
234
  def _handle_response(self, response: requests.Response) -> dict:
227
235
  try:
228
236
  data = response.json()
229
- except Exception as e:
237
+ except Exception:
230
238
  logid = response.headers.get("X-Tt-Logid")
231
239
  raise APIError(
232
- f"响应解析失败: {str(e)}, logid: {logid}, 响应内容: {response.text[:200]}",
240
+ f"响应解析失败: status={response.status_code}, logid: {logid}",
233
241
  status_code=response.status_code,
234
242
  )
235
243
 
@@ -237,11 +245,9 @@ class BaseClient:
237
245
  response.raise_for_status()
238
246
  except requests.exceptions.HTTPError as e:
239
247
  logid = response.headers.get("X-Tt-Logid")
240
- error_msg = f"HTTP 错误: {str(e)}, logid: {logid}"
241
- if data:
242
- error_msg += f", 响应数据: {data}"
248
+ error_msg = f"HTTP 错误: status={response.status_code}, logid: {logid}"
243
249
  raise APIError(
244
- error_msg, status_code=response.status_code, response_data=data
250
+ error_msg, status_code=response.status_code
245
251
  )
246
252
 
247
253
  return data
@@ -0,0 +1,97 @@
1
+ import os
2
+ from typing import Optional
3
+
4
+ from . import runtime
5
+ from .desktop_credential import desktop_pat_token
6
+ from .endpoints import INTEGRATION_BASE_URL, INTEGRATION_MODEL_BASE_URL
7
+ from .exceptions import ConfigurationError
8
+
9
+ class Config:
10
+ DEFAULT_RETRY_TIMES = 1
11
+ DEFAULT_RETRY_DELAY = 1.0
12
+ DEFAULT_TIMEOUT = 900
13
+
14
+ def __init__(
15
+ self,
16
+ api_key: Optional[str] = None,
17
+ base_url: Optional[str] = None,
18
+ base_model_url: Optional[str] = None,
19
+ retry_times: int = DEFAULT_RETRY_TIMES,
20
+ retry_delay: float = DEFAULT_RETRY_DELAY,
21
+ timeout: int = DEFAULT_TIMEOUT,
22
+ ):
23
+ # 确保「当前目录 .env 优先、环境变量兜底」的加载已完成,再读取任何配置。
24
+ runtime.ensure_env_loaded()
25
+
26
+ project_runtime_auth = runtime.uses_project_runtime_auth()
27
+ project_id_from_runtime = runtime.get_project_id()
28
+ api_token = runtime.get_api_token()
29
+ desktop_token = desktop_pat_token()
30
+
31
+ self._explicit_api_key = api_key is not None
32
+ self.api_key = desktop_token or (
33
+ api_token if project_runtime_auth else api_key or api_token or runtime.get_legacy_workload_token()
34
+ )
35
+ self._uses_user_access_token = project_runtime_auth and bool(desktop_token or api_token)
36
+
37
+ # 本地/云端由运行环境决定,不根据 token 来源猜测:COZE_DEVBOX_ENV
38
+ # 非空表示云端 Devbox,空或未设置表示本地。
39
+ self.runtime_platform = runtime.runtime_platform()
40
+ self.base_url = (
41
+ base_url or os.getenv("COZE_INTEGRATION_BASE_URL") or INTEGRATION_BASE_URL
42
+ )
43
+ self.base_model_url = base_model_url or os.getenv(
44
+ "COZE_INTEGRATION_MODEL_BASE_URL"
45
+ ) or INTEGRATION_MODEL_BASE_URL
46
+ # 项目 scope 只能来自项目根目录 .coze,不能由环境变量或调用参数覆盖。
47
+ self.project_id = str(project_id_from_runtime) if project_id_from_runtime else None
48
+ self.app_id = runtime.get_app_id() if project_runtime_auth else None
49
+
50
+ self.retry_times = retry_times
51
+ self.retry_delay = retry_delay
52
+ self.timeout = timeout
53
+
54
+ self._validate()
55
+
56
+ def _validate(self):
57
+ if not self.api_key:
58
+ raise ConfigurationError(
59
+ "API Key 未配置:请设置 COZE_API_TOKEN 或提供 api_key"
60
+ )
61
+
62
+ def get_headers(self, ctx_headers: Optional[dict] = None) -> dict:
63
+ try:
64
+ from .. import __version__
65
+ except ImportError:
66
+ __version__ = "0.0.0"
67
+
68
+ headers = {}
69
+ if ctx_headers:
70
+ headers.update(ctx_headers)
71
+ for key, value in runtime.ppe_headers().items():
72
+ if not any(existing_key.lower() == key.lower() for existing_key in headers):
73
+ headers[key] = value
74
+ headers.setdefault("Content-Type", "application/json")
75
+ if self._uses_user_access_token:
76
+ headers["Authorization"] = f"Bearer {self.api_key}"
77
+ else:
78
+ headers.setdefault("Authorization", f"Bearer {self.api_key}")
79
+ headers.setdefault("X-Client-Sdk", f"coze-coding-dev-sdk-python/{__version__}")
80
+ if runtime.project_resource_env() != runtime.PROJECT_ENV_PROD:
81
+ for key in list(headers):
82
+ if key.lower() == runtime.APP_ID_HEADER.lower():
83
+ del headers[key]
84
+ if self.uses_user_runtime_auth():
85
+ for key in list(headers):
86
+ if key.lower() == runtime.APP_ID_HEADER.lower():
87
+ del headers[key]
88
+ if key.lower() == runtime.PROJECT_ID_HEADER.lower():
89
+ del headers[key]
90
+ headers.update(runtime.request_headers())
91
+ return headers
92
+
93
+ def uses_user_runtime_auth(self) -> bool:
94
+ return (
95
+ runtime.uses_project_runtime_auth()
96
+ and self._uses_user_access_token
97
+ )
@@ -0,0 +1,37 @@
1
+ """Developer credential published by the Coze Desktop runtime files."""
2
+
3
+ import json
4
+ import time
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ # Coze Desktop writes the beta lane first; either file may be absent or omit
9
+ # patToken entirely, so both are optional candidates.
10
+ RUNTIME_FILES = ("runtime.beta.json", "runtime.json")
11
+
12
+
13
+ def _read_pat_token(path: Path) -> Optional[str]:
14
+ try:
15
+ payload = json.loads(path.read_text(encoding="utf-8"))
16
+ except (OSError, ValueError):
17
+ return None
18
+ pat_token = payload.get("patToken") if isinstance(payload, dict) else None
19
+ if not isinstance(pat_token, dict):
20
+ return None
21
+ access_token = pat_token.get("accessToken")
22
+ if not isinstance(access_token, str) or not access_token.strip():
23
+ return None
24
+ expires_in = pat_token.get("expiresIn")
25
+ # expiresIn is an absolute Unix second rather than a duration. A non-numeric
26
+ # value carries no expiry information, so the token stays usable.
27
+ if isinstance(expires_in, (int, float)) and expires_in <= time.time():
28
+ return None
29
+ return access_token.strip()
30
+
31
+
32
+ def desktop_pat_token() -> Optional[str]:
33
+ for name in RUNTIME_FILES:
34
+ token = _read_pat_token(Path.home() / ".coze" / "desktop" / name)
35
+ if token:
36
+ return token
37
+ return None
@@ -0,0 +1,46 @@
1
+ import json
2
+ from pathlib import Path
3
+ from typing import Callable, Optional
4
+
5
+ from .desktop_credential import desktop_pat_token
6
+ from .exceptions import ConfigurationError
7
+ from .runtime import get_api_token, uses_project_runtime_auth
8
+
9
+ _provider: Optional[Callable[[], str]] = None
10
+
11
+
12
+ def set_developer_credential_provider(provider: Optional[Callable[[], str]]) -> None:
13
+ global _provider
14
+ _provider = provider
15
+
16
+
17
+ def resolve_developer_credential() -> str:
18
+ desktop_token = desktop_pat_token()
19
+ if desktop_token:
20
+ return desktop_token
21
+ if uses_project_runtime_auth():
22
+ api_token = (get_api_token() or "").strip()
23
+ if api_token:
24
+ return api_token
25
+ raise ConfigurationError("项目必须设置 COZE_API_TOKEN")
26
+ if _provider:
27
+ value = (_provider() or "").strip()
28
+ if value:
29
+ return value
30
+ api_token = (get_api_token() or "").strip()
31
+ if api_token:
32
+ return api_token
33
+ bridge = Path.home() / ".coze" / "bridge" / "pat-token"
34
+ if bridge.exists():
35
+ value = bridge.read_text(encoding="utf-8").strip()
36
+ if value:
37
+ return value
38
+ config = Path.home() / ".coze" / "cli" / "config.json"
39
+ if config.exists():
40
+ try:
41
+ value = str(json.loads(config.read_text(encoding="utf-8")).get("accessToken") or "").strip()
42
+ except (OSError, ValueError, TypeError):
43
+ value = ""
44
+ if value:
45
+ return value
46
+ raise ConfigurationError("开发者凭证不可用,请先登录 Coze CLI")
@@ -0,0 +1,8 @@
1
+ """Public online endpoint defaults for the Coze Coding Integration SDK."""
2
+
3
+ INTEGRATION_BASE_URL = "https://integration.coze.cn"
4
+ INTEGRATION_MODEL_BASE_URL = f"{INTEGRATION_BASE_URL}/api/v3"
5
+ # Integration control-plane APIs share the public Integration gateway. The
6
+ # API path is part of each endpoint declaration, so this base has no suffix.
7
+ IDE_API_BASE_URL = INTEGRATION_BASE_URL
8
+ S3_PROXY_ENDPOINT_URL = f"{INTEGRATION_BASE_URL}/coze-coding-s3proxy/v1"