fiuai-sdk-python 0.2.7__tar.gz → 0.3.0__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 (19) hide show
  1. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/PKG-INFO +1 -1
  2. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/pyproject.toml +1 -1
  3. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/__init__.py +5 -1
  4. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/client.py +21 -4
  5. fiuai_sdk_python-0.3.0/src/fiuai_sdk_python/profile.py +95 -0
  6. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/setup.py +15 -10
  7. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/type.py +17 -1
  8. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/.gitignore +0 -0
  9. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/CHANGELOG.md +0 -0
  10. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/LICENSE +0 -0
  11. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/README.md +0 -0
  12. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/bank.py +0 -0
  13. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/company.py +0 -0
  14. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/const.py +0 -0
  15. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/error.py +0 -0
  16. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/item.py +0 -0
  17. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/perm.py +0 -0
  18. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/token.py +0 -0
  19. {fiuai_sdk_python-0.2.7 → fiuai_sdk_python-0.3.0}/src/fiuai_sdk_python/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fiuai_sdk_python
3
- Version: 0.2.7
3
+ Version: 0.3.0
4
4
  Summary: FiuAI Python SDK - 企业级AI服务集成开发工具包
5
5
  Project-URL: Homepage, https://github.com/fiuai/fiuai-sdk-python
6
6
  Project-URL: Documentation, https://github.com/fiuai/fiuai-sdk-python#readme
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fiuai_sdk_python"
3
- version = "0.2.7"
3
+ version = "0.3.0"
4
4
  description = "FiuAI Python SDK - 企业级AI服务集成开发工具包"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,10 +1,14 @@
1
1
  from .client import FiuaiSDK, get_client
2
2
  from .token import TokenConfig
3
3
  from .util import init_fiuai
4
+ from .profile import UserProfileInfo
5
+ from .type import UserProfile
4
6
 
5
7
  __all__ = [
6
8
  'FiuaiSDK',
7
9
  'TokenConfig',
8
10
  'init_fiuai',
9
- 'get_client'
11
+ 'get_client',
12
+ 'UserProfileInfo',
13
+ 'UserProfile'
10
14
  ]
@@ -4,10 +4,11 @@ import json
4
4
  from urllib.parse import quote
5
5
  from typing import Any, Literal
6
6
 
7
- from .util import create_headers, get_tokens, get_client_config, is_initialized
7
+ from .util import get_tokens, get_client_config, is_initialized
8
8
  from .error import FiuaiGeneralError, FiuaiAuthError
9
9
  from logging import getLogger
10
10
  from .type import UserProfile
11
+ from .profile import UserProfileInfo
11
12
 
12
13
 
13
14
  logger = getLogger(__name__)
@@ -140,6 +141,7 @@ class FiuaiSDK(object):
140
141
  return self.headers["Fiuai-Internal-Company"]
141
142
 
142
143
  def get_user_profile(self) -> UserProfile:
144
+ """获取简单的用户信息"""
143
145
  d = self.get_doc("User", self.username, fields=["name", "full_name", "email", "phone", "roles", "auth_tenant_id", "default_company_id"])
144
146
  return UserProfile(
145
147
  name=self.username,
@@ -151,6 +153,17 @@ class FiuaiSDK(object):
151
153
  default_company_id=d.get("default_company_id") or "",
152
154
  )
153
155
 
156
+
157
+ def get_user_profile_info(self, user_id: str) -> UserProfileInfo:
158
+ """获取详细的用户信息"""
159
+ d = self.get_v2_api(f"internal/user/profile/{user_id}")
160
+
161
+ if not d:
162
+ return None
163
+
164
+ return UserProfileInfo.model_validate(d)
165
+
166
+
154
167
  def get_list(self, doctype, fields='"*"', filters=None, limit_start=0, limit_page_length=0, order_by=None):
155
168
  '''Returns list of records of a particular type'''
156
169
  if not isinstance(fields, str):
@@ -234,10 +247,14 @@ class FiuaiSDK(object):
234
247
 
235
248
 
236
249
  docs = self.post_process(res)
237
- if isinstance(docs, list):
238
- return docs[0]
250
+
251
+ if not docs:
252
+ return None
239
253
  else:
240
- return docs
254
+ if isinstance(docs, list):
255
+ return docs[0]
256
+ else:
257
+ return docs
241
258
 
242
259
 
243
260
  def get_api(self, method, params={}):
@@ -0,0 +1,95 @@
1
+ # -- coding: utf-8 --
2
+ # Project: fiuai_sdk_python
3
+ # Created Date: 2025 09 Th
4
+ # Author: liming
5
+ # Email: lmlala@aliyun.com
6
+ # Copyright (c) 2025 FiuAI
7
+
8
+
9
+ # -- coding: utf-8 --
10
+ # Project: response
11
+ # Created Date: 2025 05 Tu
12
+ # Author: liming
13
+ # Email: lmlala@aliyun.com
14
+ # Copyright (c) 2025 FiuAI
15
+
16
+
17
+ from pydantic import BaseModel, Field
18
+ from typing import List, Literal
19
+
20
+
21
+ class UserCompanyInfo(BaseModel):
22
+ name: str = Field(description="公司id")
23
+ full_name: str = Field(description="公司名称")
24
+
25
+ class UserBaseInfo(BaseModel):
26
+ name: str = Field(description="用户名id")
27
+ email: str = Field(description="邮箱")
28
+ first_name: str = Field(description="名")
29
+ full_name: str = Field(description="全名")
30
+ language: str = Field(description="语言")
31
+ time_zone: str = Field(description="时区")
32
+ auth_tenant_id: str = Field(description="租户id")
33
+ current_company: str = Field(description="当前公司")
34
+ available_companies: List[UserCompanyInfo] = Field(description="用户在租户下可以访问的公司列表", default_factory=list)
35
+
36
+
37
+ class UserPermissionInfo(BaseModel):
38
+ can_select: List[str] = Field(description="可以查询的文档", default_factory=list)
39
+ can_read: List[str] = Field(description="可以读取的文档", default_factory=list)
40
+ can_write: List[str] = Field(description="可以写入的文档", default_factory=list)
41
+ can_create: List[str] = Field(description="可以创建的文档", default_factory=list)
42
+ can_delete: List[str] = Field(description="可以删除的文档", default_factory=list)
43
+ can_submit: List[str] = Field(description="可以提交的文档", default_factory=list)
44
+ can_cancel: List[str] = Field(description="可以取消的文档", default_factory=list)
45
+ can_search: List[str] = Field(description="可以搜索的文档", default_factory=list)
46
+
47
+ # def __init__(self, user: str):
48
+ # super().__init__()
49
+
50
+ # def can_select(self, doctype: str) -> bool:
51
+ # return doctype in self.can_select
52
+
53
+ # def can_read(self, doctype: str) -> bool:
54
+ # return doctype in self.can_read
55
+
56
+ # def can_write(self, doctype: str) -> bool:
57
+ # return doctype in self.can_write
58
+
59
+ # def can_create(self, doctype: str) -> bool:
60
+ # return doctype in self.can_create
61
+
62
+ # def can_delete(self, doctype: str) -> bool:
63
+ # return doctype in self.can_delete
64
+
65
+ # def can_submit(self, doctype: str) -> bool:
66
+ # return doctype in self.can_submit
67
+
68
+ # def can_cancel(self, doctype: str) -> bool:
69
+ # return doctype in self.can_cancel
70
+
71
+ # def can_search(self, doctype: str) -> bool:
72
+ # return doctype in self.can_search
73
+
74
+ class UserTenantInfo(BaseModel):
75
+ name: str = Field(description="租户id")
76
+ tenant_name: str = Field(description="租户名称")
77
+
78
+
79
+ class UserCurrentCompanyInfo(BaseModel):
80
+ name: str = Field(description="公司id")
81
+ full_name: str = Field(description="公司名称")
82
+ unique_no: str = Field(description="公司唯一编号")
83
+ country_region: str = Field(description="国家")
84
+ default_currency: str = Field(description="货币")
85
+ company_size: str = Field(description="公司规模")
86
+ entity_type: Literal["Enterprise", "Individual", "Other"] = Field(description="公司类型")
87
+ company_profile: str = Field(description="公司业务特点提示词", default="")
88
+
89
+ class UserProfileInfo(BaseModel):
90
+ user_base_info: UserBaseInfo = Field(description="用户基础信息")
91
+ user_permissions: UserPermissionInfo = Field(description="用户权限")
92
+ user_tenant_info: UserTenantInfo = Field(description="用户租户信息")
93
+ user_current_company_info: UserCurrentCompanyInfo = Field(description="用户当前公司信息")
94
+
95
+
@@ -73,7 +73,7 @@ def load_language_data(client: FiuaiSDK)-> List[Language]:
73
73
  )
74
74
  return [Language(name=language["name"], language_name=language["language_name"]) for language in language_list]
75
75
 
76
- def load_doctype_meta(client: FiuaiSDK, doctype: str, max_api_retry: int = 3)-> DocTypeMeta:
76
+ def load_doctype_meta(client: FiuaiSDK, doctype: str, max_api_retry: int = 3, only_has_prompt: bool = True, show_hidden: bool = False)-> DocTypeMeta:
77
77
  """
78
78
  从frappe获取doctype数据
79
79
  """
@@ -82,7 +82,7 @@ def load_doctype_meta(client: FiuaiSDK, doctype: str, max_api_retry: int = 3)->
82
82
  doc_meta = None
83
83
  while retry_count < max_api_retry:
84
84
 
85
- doc_meta = _get_meta(client, doctype)
85
+ doc_meta = _get_meta(client, doctype, only_has_prompt, show_hidden)
86
86
 
87
87
  if doc_meta:
88
88
  break
@@ -91,7 +91,7 @@ def load_doctype_meta(client: FiuaiSDK, doctype: str, max_api_retry: int = 3)->
91
91
 
92
92
  return doc_meta
93
93
 
94
- def _get_meta(client: FiuaiSDK, doctype: str) -> DocTypeMeta:
94
+ def _get_meta(client: FiuaiSDK, doctype: str, only_has_prompt: bool = True, show_hidden: bool = False) -> DocTypeMeta:
95
95
  try:
96
96
  m = client.get_meta(doctype)
97
97
 
@@ -109,6 +109,7 @@ def _get_meta(client: FiuaiSDK, doctype: str) -> DocTypeMeta:
109
109
  hidden = _f.get("hidden", 0)
110
110
  reqd = _f.get("reqd", 0)
111
111
  read_only = _f.get("read_only", 0)
112
+ description = _f.get("description", "")
112
113
 
113
114
  options = []
114
115
  match field_type:
@@ -124,22 +125,26 @@ def _get_meta(client: FiuaiSDK, doctype: str) -> DocTypeMeta:
124
125
  pass
125
126
 
126
127
 
127
- if field_prompt == "":
128
+ if field_prompt == "" and only_has_prompt:
128
129
  # 仅有prompt的field才是应该关心的字段,降低复杂度
129
130
  continue
130
- if hidden == 1:
131
+ if hidden == 1 and not show_hidden:
131
132
  continue
132
133
 
133
134
 
134
135
  _fields.append(DocField(
135
136
  fieldname=field_name,
137
+ description=description,
136
138
  fieldtype=field_type,
137
139
  hidden=True if _f.get("hidden", 0) == 1 else False,
138
140
  read_only=True if _f.get("read_only", 0) == 1 else False,
139
141
  reqd=True if _f.get("reqd", 0) == 1 else False,
140
142
  options=options,
141
143
  field_prompt=field_prompt,
142
- ai_recognition_value=AiRecognitionValue(value=None, confidence=0, ai_comment="")
144
+ mandatory=True if _f.get("mandatory", 0) == 1 else False,
145
+ in_list_view=True if _f.get("in_list_view", 0) == 1 else False,
146
+ in_mobile_view=True if _f.get("in_mobile_view", 0) == 1 else False,
147
+ # ai_recognition_value=AiRecognitionValue(value=None, confidence=0, ai_comment="")
143
148
  ))
144
149
 
145
150
  # links, child 去重
@@ -148,23 +153,23 @@ def _get_meta(client: FiuaiSDK, doctype: str) -> DocTypeMeta:
148
153
 
149
154
  doc_meta = DocTypeMeta(
150
155
  name=doctype,
151
- doctype_prompts=m["doctype_prompts"],
156
+ doctype_prompts=m.get("doctype_prompts", ""),
152
157
  fields=_fields,
153
158
  link_docs=links,
154
159
  child_docs=child_docs
155
160
  )
156
161
  return doc_meta
157
162
  except Exception as e:
158
- logger.error(f"load doctype meta failed: {e.args}")
163
+ logger.error(f"load doctype {doctype} meta failed: {e.args}")
159
164
  return None
160
165
 
161
166
 
162
- def load_all_allowed_doctype_meta(client: FiuaiSDK)-> List[DocTypeMeta]:
167
+ def load_all_allowed_doctype_meta(client: FiuaiSDK, only_has_prompt: bool = True, show_hidden: bool = False)-> List[DocTypeMeta]:
163
168
  """
164
169
  从frappe获取doctype数据
165
170
  """
166
171
  r = []
167
172
  for _d in AI_ALLOWED_DOCTYPE_META:
168
- m = load_doctype_meta(client, _d)
173
+ m = load_doctype_meta(client, _d, only_has_prompt, show_hidden)
169
174
  r.append(m)
170
175
  return r
@@ -124,12 +124,16 @@ class DocField(BaseModel):
124
124
  frappe 文档字段文档数据
125
125
  """
126
126
  fieldname: str = Field(description="字段名称,比如Invoice,Purchase Order,etc.")
127
+ description: str = Field(description="字段描述", default="")
127
128
  hidden: bool = Field(description="字段是否隐藏")
128
129
  reqd: bool = Field(description="字段是否必填")
129
130
  read_only: bool = Field(description="字段是否只读")
130
131
  fieldtype: str = Field(description="字段类型,比如Data,Float,Link,etc.")
131
132
  options: List[str] = Field(description="字段选项,Select类型的字段的枚举值, Link类型字段的Link目标表名")
132
133
  field_prompt: str = Field(description="字段对应的prompt")
134
+ mandatory: bool = Field(description="字段是否必填", default=False)
135
+ in_list_view: bool = Field(description="字段是否在列表视图中显示", default=False)
136
+ in_mobile_view: bool = Field(description="字段是否在移动端视图中显示", default=False)
133
137
  # ai_recognition_value: AiRecognitionValue = Field(description="字段对应的AI识别结果", default=None)
134
138
 
135
139
 
@@ -211,6 +215,18 @@ class DocTypeMeta(BaseModel):
211
215
  r.append(i.model_dump_json())
212
216
  return r
213
217
 
218
+
219
+ ##### 获取单个field
220
+ def get_field(self, fieldname: str) -> DocField | None:
221
+ for field in self.fields:
222
+ if field.fieldname == fieldname:
223
+ return field
224
+ return None
225
+
226
+
227
+
228
+
229
+ #### create datas
214
230
  def create_empty_data_json(self, mock_type: Literal["full", "json"]="json", with_child_tables: bool = False) -> str:
215
231
  return json.dumps(self.create_empty_data(mock_type, with_child_tables), indent=4)
216
232
 
@@ -248,7 +264,7 @@ class DocTypeMeta(BaseModel):
248
264
  if with_child_tables:
249
265
  try:
250
266
  # 动态导入避免循环依赖
251
- from pkg.fiuaiclient .setup import load_doctype_meta
267
+ from .setup import load_doctype_meta
252
268
  # 自动加载子表元数据
253
269
  child_meta = load_doctype_meta(child_doctype)
254
270
  if child_meta: