Metadata-Version: 2.4
Name: licos-agent-runtime
Version: 0.2.40
Summary: LICOS Python agent runtime for LangGraph/LangChain projects
Requires-Python: >=3.10
Requires-Dist: fastapi<1,>=0.121
Requires-Dist: filelock<4,>=3.16
Requires-Dist: httpx<1,>=0.27
Requires-Dist: langchain-openai<2,>=1.2
Requires-Dist: langchain<2,>=1.2
Requires-Dist: langgraph-checkpoint-postgres<4,>=3.0
Requires-Dist: langgraph-checkpoint<5,>=4
Requires-Dist: langgraph-prebuilt<2,>=1.0
Requires-Dist: langgraph-sdk<1,>=0.3
Requires-Dist: langgraph<2,>=1.1
Requires-Dist: langsmith<1,>=0.4
Requires-Dist: licos-platform-sdk>=0.5.7
Requires-Dist: pydantic<3,>=2.12
Requires-Dist: pyyaml<7,>=6
Requires-Dist: uvicorn<1,>=0.38
Requires-Dist: wcmatch<11,>=10
Description-Content-Type: text/markdown

# LICOS Agent Runtime

`build_agent_graph(model, tools, system_prompt=...)` 提供统一的输入 → 模型 → 工具循环，模型与工具由项目注册。`input`、`messages`、`event` 可以组合使用；模型调用保留完整工具消息对，多模态输入保持原始内容。

工具执行异常会作为 `status="error"` 的工具结果交回模型，由模型决定修正参数、调用其他工具或结束；失败工具的信息仍保留在运行记录中。取消执行和 LangGraph 中断仍按原语义处理。`recursion_limit` 限制图执行步数，包含模型和工具节点，不等于模型调用轮数；本运行时没有额外设置固定轮数。

## 项目技能和文件工具

Agent 模板使用 `licos_agent_runtime.project_agent.build_project_agent`，在工具循环上注册 `read_file`、`write_file`、`glob_file`、`list_files`、`list_skills` 和 `read_skill`。业务工具仍在项目的 `TOOLS` 和配置 `tools` 中同步注册，不能与内置工具重名。

技能放在项目 `skills/<name>/SKILL.md`，YAML 头必须包含与目录同名的 `name` 和非空 `description`。构图时发现名称与简介，全文和附属资源由模型按需调用 `read_skill(name, path)` 读取。`path` 相对技能目录，支持任意层级的文本文件和目录列表，例如 `references/guide.md`、`scripts/check.py`、`assets/template.md`；读取脚本不会执行它。技能目录里的资源变化参与源码指纹和热更新。

普通文件工具参照 Agent 内置工具：`read_file(path, offset=1, limit=None)` 按行读取并显示行号及截断提示；`write_file(path, content, mode="overwrite")` 支持覆盖和 `append` 追加；`glob_file(pattern, path=None)` 支持目录前缀、`**` 和花括号扩展，返回按修改时间倒序排列的路径。

运行时将聊天附件和普通文件放在平台数据目录 `.licos/agent-session-files/` 下，按项目、当前用户和 `session_id` 分开。工具中的相对路径从当前会话目录起算；不能访问其他会话或项目源码。`read_skill` 单独提供共享技能的只读访问。HTTP 文件访问通过 Bearer 令牌调用平台 `/api/v1/admin/auth/me` 确认用户，不采用客户端声明的用户 ID；程序直接调用需传入具有明确 `current_user_id` 的 `Context`。同一用户持续使用同一 `session_id` 才能复用文件，未提供会话 ID 时以本次 `run_id` 为独立范围。聊天消息仍来自调用方的 `messages`，文件隔离不会启用跨请求内存会话。

用户通过 `content.query.prompt` 的 `upload_file` 块提交附件时，运行时自动将 HTTP(S) URL 或 base64 data URL 保存到会话内 `assets/upload/`，不依赖模型调用下载工具。模型收到 `status: saved` 和本地相对路径后，可用 `read_file` 读取文本；失败消息包含具体原因，不把同名旧文件当作本次附件。图片、视频保留多模态内容；base64 编码不作为普通文本堆入模型上下文。附件上限 20 MiB，可通过 `LICOS_AGENT_ATTACHMENT_MAX_BYTES` 调低。

普通文本中的 URL 和顶层 `attachments` / `files` / `references` 业务字段不会自动下载。额外下载、上传及办公文件生成由业务项目按需接入：在 `create_agent(ctx)` 中将 `create_file_transfer_tools(project_root(), ctx=ctx)` 加入业务工具列表，并在配置 `tools` 中注册 `download_file`、`upload_file`。上传复用 `licos_platform_sdk.storage.upload_file` 和 `storage.share_url`，返回真实 `url` 与 `expiresAt`；不会把本地路径当作下载链接。`licos-dev-sdk` 的 Word、PDF、Excel 等生成接口可由业务工具封装，文件参数使用 `SessionFiles(project_root(), ctx).resolve(path)`，避免越出当前会话。

```bash
python -m licos_agent_runtime -m verify --cases tests/agent_cases.json --base-url http://127.0.0.1:5000 --report .tmp/agent-verification.json
```

验收连接已有预览，核对 HTTP、SSE、模型/业务工具调用与运行记录。业务场景在用例中指定 `required_tools` 和 `model_contains`；报告引用实际 run_id，错误导致非零退出码。

运行执行超时与验收 HTTP 等待时间统一读取 `LICOS_AGENT_RUN_TIMEOUT_SECONDS`，未设置时默认 900 秒。验收可以用 `--request-timeout` 显式覆盖 HTTP 等待时间，并在报告中记录实际值；该参数不修改服务端执行预算。HTTP 等待时间是请求各网络阶段的等待限制，服务端预算是一次图执行的总时限。空值、非数字、非有限数及非正数会明确失败；服务端在创建任务前校验配置。工具自身的 `TimeoutError` 保留原错误，不当作运行时预算耗尽。

项目导出的图在加载时校验 `ainvoke`、`stream`、`astream`、`astream_events` 接口及调用参数。统一传递 `config/context`；异步流还支持 `stream_mode`，调试事件使用 `version="v2"`。可以直接导出编译后的 LangGraph 图。接口不匹配、无法检查工厂签名或缺失流式方法会失败；执行异常不会触发换参数重试或切换执行方式。

## 本体事件执行

业务项目运行时可通过 `config/event_subscriptions.json` 管理后台订阅。默认空数组，不建立订阅。浏览器断开不影响已启动的服务；预览进程或项目实例休眠后订阅会停止，持续监听需要部署为常驻业务服务。该功能不保证唤醒已休眠的开发实例。

先对项目运行 `python -m licos_agent_runtime -m fingerprint` 取得当前源码版本，再配置绑定：

```json
[
  {
    "id": "process-observation",
    "workspace_id": "当前工作空间 ID",
    "project_id": "当前业务 AGENT 项目 ID",
    "project_version": "fingerprint 命令返回的 SHA256",
    "element_ids": ["已从本体目录解析的元素 ID"],
    "attribute_ids": ["已授权的属性 ID"],
    "enabled": true,
    "max_pending": 100
  }
]
```

`max_pending` 由业务配置，没有写死容量。每个绑定按接收顺序串行执行，绑定之间可并行。源码版本与运行时热更新使用同一份源文件集合；绑定配置本身不参与指纹，避免自引用。源码或模型配置变化后需要重新验收、更新版本绑定并重启服务。身份与当前项目不匹配、版本不匹配、参数或权限错误都会明确失败。

- `GET /agent/subscriptions` 查看绑定、连接状态及订阅错误。
- `GET /agent/subscriptions/{id}/deliveries?limit=...&offset=...` 分页查询投递记录及执行错误，返回 `records/total/limit/offset`。`limit` 必须显式传入正整数，`offset` 默认 0 且必须非负；不会固定截为 50 条或静默修改分页参数。未知绑定返回 404，非法参数返回 422。
- `POST /agent/subscriptions/{id}/stop` 停止当前订阅和执行。
- `POST /agent/subscriptions/{id}/start` 启动已加载的绑定。配置文件新增或修改绑定后重启服务使其加载。

0.2.37 起，订阅状态响应不再内嵌 `deliveries`，调用方通过分页接口读取投递记录。

0.2.38 起要求 Platform SDK 0.5.7：后台本体订阅断线（包括会话失效的 `1008`）后，由 SDK 持续重新鉴权并恢复原订阅范围，连接恢复前 `transport_state` 为 `reconnecting`。明确的权限拒绝和协议错误仍记录为失败；没有断线事件回放保证。

事件通过 SDK 接收后写入 `/workspace/.licos/event-subscriptions/deliveries.sqlite3`，直接调用本项目的业务图，不调用编程助手 `/messages`。已有日程任务针对会话，因此这里持久化业务运行时自己的投递队列，并复用工作区持久卷和运行记录。文件锁阻止共享同一工作区的多个运行时重复监听。实际执行前经过与 `/run` 相同的余额检查。

每次投递保留原始事件、绑定、源码/运行时版本以及 run_id，模型和工具证据可在 `/run_records/{run_id}` 查阅。待执行事件随服务重启恢复；运行中断标记为 `interrupted`，失败标记为 `failed`，均不自动重放。积压达到配置上限时记录该事件失败并停止订阅，错误可查询。

当前上游协议未承诺稳定事件身份或断线回放：相同时间和值的事件全部保留，运行时生成的投递 ID 仅用于本地追踪，不代表上游事件 ID。已接收且落盘的待执行事件可恢复，连接中断期间的上游事件无法保证补齐。人工/历史回放使用普通事件输入并保留真实来源，不能当作 WS 新事件验收。

## 用量

SSE 完成事件和运行记录共用模型用量汇总；`token_usage.complete=false` 表示至少一次模型调用没有用量记录。已统计数值仅是已知部分，不能把未上报当成零消耗。
