Metadata-Version: 2.4
Name: licos-platform-sdk
Version: 0.9.7
Summary: LICOS platform SDK package shell
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Requires-Dist: jsonschema<5,>=4.23
Requires-Dist: rfc3339-validator<1,>=0.1.4
Requires-Dist: typing-extensions<5,>=4.12
Requires-Dist: websockets<16,>=15.0.1
Description-Content-Type: text/markdown

# licos-platform-sdk

## 数据库失效通知与筛选（0.9.6 起）

`async_database.query(..., count=True, head=True)` 只读取匹配数量，不传输记录正文。过滤支持 `json_contains`（单个对象）、`json_contains_any`（非空对象列表，OR）及 `is_null_or_gt`；需要同时升级支持这些操作的平台后端。

`async_database.events(topics)` 按当前项目及 dev/prod 环境订阅 `ready/invalidated/heartbeat` 信号。先等 `ready` 再读数据库；`rpc(..., notify_topics=[...])` 在成功提交后通知，失败或回滚不通知。同步 `database.rpc` 也接受该可选参数。信号不含业务数据、不持久化、可能合并；数据库日志与业务游标负责重连补读。连接错误会抛出，调用方按原游标重建连接；不要重新执行已提交的写入。旧调用不传参数时保持原行为。

## 项目完整运行接口（0.9.2 起）

`ProjectRuntimeClient` 提供低代码智能体、编程智能体和编程工作流的完整受控接口，以及单次调用、项目会话和后台订阅的结果流。普通 Python 服务可独立使用，不要求安装 LangGraph。

按实际安装版本定位 [接入指南](src/licos_platform_sdk/docs/project-runtime.md) 和 [完整接口索引](src/licos_platform_sdk/docs/project-runtime-api.md)：

```python
from importlib.resources import files
print(files("licos_platform_sdk").joinpath("docs/project-runtime.md"))
```

异步客户端按当前用户请求创建，通过上下文管理器释放连接；原生响应、分页和断线续接规则见指南。

## 企业项目查询（0.9.1 起）

`enterprise_projects` 查询当前用户可见的在线企业项目，类型限定为低代码智能体 `AGENT`、AI 编程智能体 `AICODING_AGENT` 和 AI 编程工作流 `AICODING_WORKFLOW`。每次显式传入当前用户 `user_token`，不要求项目运行上下文。

```python
from licos_platform_sdk import enterprise_projects

page = enterprise_projects.list_projects(query="发票", page=1, page_size=50, user_token=token)
all_matches = list(enterprise_projects.iter_projects(query="发票", user_token=token))
publication = enterprise_projects.get_project(selected_record_id, user_token=token)
contract = enterprise_projects.current_capability(selected_resource, user_token=token)
```

`list_projects` 返回 `items/page/page_size/total/has_next`；`iter_projects` 读取所有匹配页。可传 `resource_types` 精确筛选三类资源。每项的 `resource` 含 `tenant_id/workspace_id/resource_type/resource_id`，`record_id/version/source_id` 描述本次发布，`invocation` 含 `enabled/callable/unavailable_reason`。关闭调用或未就绪的可见项目仍返回；`get_project` 读取同样的发布摘要。

`capability(record_id, user_token=...)` 读取精确发布契约；`current_capability(resource, user_token=...)` 按完整稳定标识解析当前契约，返回平台的 `record_id/contract_revision/input_schema/output_schema/capabilities` 等字段。不可调用时保留平台错误，不能将权限错误当作空目录。

普通服务端项目执行使用本 SDK 的 `ProjectRuntimeClient`；`licos-agent-runtime` 原 `EnterpriseProjectClient` 保持兼容。受管智能体图内 `invoke_enterprise` 的中断和恢复语义查 Runtime 的 `docs/enterprise-projects.md`。查询不启用调用，代码不通过部署 URL 绕过企业发布授权。

LICOS 项目服务端 SDK，提供项目数据库、对象存储、企业知识库、本体和 OAuth 等平台能力。

## 项目登录身份

有内置登录用项目当前会话，没有内置登录用 LICOS 网页登录。显式配置模式，不按凭证是否存在切换身份：

```python
from licos_platform_sdk import ProjectAuth, get_current_user

project_auth = ProjectAuth("platform")
token = project_auth.user_token(request)
user = get_current_user(user_token=token)
```

`platform` 模式接受调用方明确提供的 Bearer Token，或浏览器登录桥签发的 `X-Licos-User-Ticket`；两者同时出现会报错。票据只兑换一次，绑定 `LICOS_PROJECT_ID`，服务端使用 `LICOS_AI_AGENT_TOKEN` 兑换；不会根据初始化用户换 Token。

内置登录使用 `ProjectAuth("builtin", resolve_builtin_token=已有会话取值函数)`，取值函数只返回该登录用户已授权的 LICOS Token。它缺失或失效时返回内置登录错误，不读取平台票据或容器用户。业务自签 JWT 不能直接传给平台 SDK。

Agent/Workflow 的请求节点使用 `ctx.identity.user_token`。异步 HTTP 处理器用 `await asyncio.to_thread(project_auth.user_token, request)` 完成票据兑换，避免阻塞事件循环。

沿用现有 OAuth 授权范围与接口权限。凭证无权访问目标接口时返回现有鉴权错误，不扩大权限或换用其他身份。

## 当前使用者信息（0.6.1 起）

```python
from licos_platform_sdk import get_current_user

# token 是当前请求的用户 Bearer Token，不包含 "Bearer " 前缀。
sys_user = get_current_user(user_token=token)
print(sys_user["displayName"])
print(sys_user["departments"])
print(sys_user["primaryPosition"])
```

返回对象与低代码系统变量 `sys_user` 相同，保留平台的 camelCase 字段名：
`id`、`username`、`displayName`、`avatarUrl`、`tenantId`、`tenantName`、
`primaryDepartment`、`departments`、`organizationAssignments`、`primaryPosition`、`primaryJobTitle`。
部门包含 ID、名称、组织路径、ID 路径及主部门标志；组织任职包含岗位、职务和部门负责人标志。

SDK 自动读取 `LICOS_PLATFORM_API_BASE_URL`、`LICOS_AI_AGENT_TOKEN` 和项目工作空间。
`workspace_id` 可由服务端指定执行工作空间；默认依次读取 `LICOS_WORKSPACE_ID`、
`LICOS_OWNER_WORKSPACE_ID`、`AGENT_WORKSPACE_ID`。企业按执行工作空间确定，与低代码一致。
无企业时企业字段为 `None`；未加入执行企业的使用者，部门和任职为空，不能返回项目所有者的信息。

多用户服务每次传入当前请求的 Token。智能体/工作流可传 `ctx.identity.user_token`；
在异步节点中使用 `await asyncio.to_thread(get_current_user, user_token=token)`。
结果不做全局缓存。Token 无效时直接报错，由调用方处理登录失效。

从 0.7.0 起必须显式传入 `user_token`。`LICOS_CURRENT_USER_ID` 只是容器初始化用户，不能代表网页登录者。
本接口仅供服务端使用；`LICOS_AI_AGENT_TOKEN` 不得发送到浏览器。


## 企业本体

本体接口仅供项目服务端使用，通过平台网关 `/ontology-api` 调用。先搜索当前用户的授权目录，再按返回的参数 Schema 和模式调用：

```python
from licos_platform_sdk import ontology

# token 来自本次请求的认证会话，不含 Bearer 前缀。
catalog = ontology.search_tools("查询设备状态", user_token=token)
selected = next(
    item for item in catalog["items"]
    if item["selection"] == "MATCH" and item["mode"] == "READ"
    and item["definition"]["function"]["name"] == requested_tool_name
)
result = ontology.invoke_tool(
    selected["definition"]["function"]["name"],
    arguments_from_validated_request,
    user_token=token,
    catalog_version=catalog["catalogVersion"],
    required_mode="READ",
)
```

- `elementId` 是已解析的部署实例 ID，用于上下文、属性、关系和数据查询。`objectTypeId` 从实例上下文读取，是对象模板 ID，与 `template.templateId` 一致；不能混用。
- 函数使用目录条目的 `apiName` 和 `version`，业务输入 `input` 按 `inputSchema` 填写；`objects` 是对象导入描述，最多 8 组，每组 `pageSize` 为 1–100。动作仍使用列表 `id` 作为 `actionTypeId`。

已发布本体从 0.8.0 起提供专门接口。编辑阶段用 `ontology.list_releases(user_token=token)`、`get_package(release_id, user_token=token)` 查看语义，再用 `create_binding(release_id, objects, functions, user_token=token)` 保存版本、属性和函数范围。`objects` 为 `[{"elementId": "部署ID", "attributeIds": ["属性ID"]}]`，`functions` 为 `[{"apiName": "函数名", "version": "函数版本"}]`；这些标识取自真实返回。

从 0.9.0 起，默认自动选择最新正式版可使用 `get_latest_package(root_object_id, user_token=token)`、`create_latest_binding(root_object_id, objects, functions, user_token=token)`。保存的配置 `{versionPolicy: "latestPublished", rootObjectId, binding}` 用 `resolve_binding(configuration, user_token=token)` 在每次新运行开始解析一次，持久化并复用返回绑定；恢复执行直接读取原绑定。`pinned` 或省略策略保留固定版本语义。新版缺少已选范围时直接报错，函数版本不自动变更，业务记录仍实时查询。

```python
# binding 从应用可信配置读取；token 是本次调用身份，不来自模型参数。
context = ontology.validate_binding(binding, user_token=token)
evidence = ontology.query_package_objects(binding, element_id, {
    "attributeIds": selected_attribute_ids,
    "pagination": {"mode": "OFFSET", "pageNum": 1, "pageSize": 20},
}, user_token=token)
result = ontology.invoke_package_function(
    binding, api_name, function_version, business_input, user_token=token,
)
```

每次消费都重新读取指定发布，核对身份及哈希元数据，不回退 CURRENT。查询保留主键、分页和上游数据时间；`hasMore=true` 表示结果未取全。函数 `objects` 导入会读取全部属性，因此属性受限的部署实例不能整对象导入。历史画布函数可查看但不可执行。新发布包动作暂不开放；旧动作继续使用其原有确认协议。绑定是应用范围约束，不替代上游实时权限；SDK 不授予权限、不重算缺少规范的产物哈希。
- 动作预览携带选定部署实例的 `objectElementId`、真实实例键 `objectKey` 和参数。用户确认后使用同一预览的 `confirmationId` 执行，目标或参数变化时重新预览。
- SDK 严格按动态目录校验。动作列表 AI 接口目前只接受 `objectTypeId`，列表按模板查询，预览指定 `objectElementId`；列表按实例过滤需要上游补齐接口契约。
- 实时订阅使用 `ontology.subscribe_realtime(element_ids, user_token=token)`；HTTP 401/403 终止订阅，由调用方更新 Token。异步服务通过工作线程调用同步 SDK。
- SDK 使用用户 Token 查询计划并通过目录中的 `createUnsRealtimeClient` 申请一次性接入地址，原样连接返回的 `websocketUrl`，不向 WebSocket 发送登录 Token。断线重连重新申请地址，收到 `uns.subscribed` 才报告成功。`expiresAt` 是接入授权截止时间（epoch 毫秒），不是连接存活时间；接入地址和 `clientId` 不进入模型上下文或日志。

## 身份选择（0.7.0 起）

`LICOS_CURRENT_USER_ID` 表示容器启动时配置的执行用户。SDK 不用它推断当前网页登录者，也不从进程级 `LICOS_USER_TOKEN` 取得本次请求凭证。项目身份指运行时配置的项目所有者身份，按接口选择：

| 接口 | 调用身份 |
| --- | --- |
| `get_current_user` | 必须显式传入本次用户的 `user_token` |
| `enterprise_knowledge` 全部接口 | 必须传 `user_token`，企业范围和权限由平台认证结果确定 |
| 本体 `search_tools`、`resolve_tool`、`invoke_tool`、`subscribe_realtime` | 必须传执行用户的 `user_token`；网页登录请求使用本次登录会话的 Token |
| 普通 `knowledge` 接口 | 默认项目身份；需要用户权限时显式传 `user_token` |
| 数据库、对象存储、`oauth` 应用管理 | 项目身份 |
| `oauth_runtime` 授权码交换、刷新、userinfo、撤销 | 按 OAuth 协议传对应凭证，不使用容器用户替代 |

`user_token` 不含 `Bearer ` 前缀。用户标识、名称和企业信息以平台认证结果为准；项目所有者、工作空间等资源归属字段单独保留。

```python
from licos_platform_sdk import enterprise_knowledge, get_current_user, knowledge, ontology

# token 来自本次请求的认证会话。
user = get_current_user(user_token=token)
resources = enterprise_knowledge.tree(user_token=token)
catalog = ontology.search_tools('设备状态', user_token=token)
result = knowledge.search('资料', user_token=token)
```

网页登录请求缺少 Token 时，业务入口应返回登录错误，不能改用容器用户或项目所有者。每次调用显式传入 Token，不把请求 Token 或用户 ID 写入 `os.environ`，也不跨用户共享请求身份。

显式传入的 Token 失效时直接返回鉴权错误，由调用方更新登录凭证。实时订阅遇到网络中断会携带原 Token 重新检查授权并订阅，401/403 终止；取得新 Token 后重新创建订阅。后台常驻的项目订阅由调用方显式传项目所有者 Token。

独立 `licos-platform` CLI 的用户操作才默认按 `LICOS_CURRENT_USER_ID` 和运行时服务凭证换 Token。HTTP 服务通过 CLI 调用用户接口时使用 `--token-stdin`，不依赖容器默认用户。升级到 0.7.0 时，已有企业知识库和本体调用必须补上 `user_token` 参数。
