跳转到内容
Crystal CodeDocs
简简体中文

Crystal 消费

交互回合使用 IStreamingChatClient 和 ToolExecutor。所选模型声明 imageInput 且其适配器支持时,会话使用 IStreamingMultimodalChatClient 和保持同一审批策略的宿主执行器。会话拥有这些客户端,并可以在 /model 时替换它们。它不把 Crystal.Agents.Agent 用于活动 UI:该 Agent 完成模型回合时没有 token 流。

活动会话尚未使用 Crystal.Harness.AgentHarness。父子 Agent 组合是推迟的产品工作;实现该拓扑时,宿主消费 AgentHarness 以获得命名调用谱系和共享预算,同时保留对提示、工具、审批、持久化和终端投影的所有权。

审批是提供给 ToolExecutor 的 ToolInvocationPolicy。拒绝返回 Harness 编写的 ToolOutput。工具异常只通过 Harness ToolExceptionMapper 变为模型可见。

CrystalCode.Engine 拥有图像附加、MIME 签名验证、会话持久化、记录标记,以及向 Crystal 类型化多模态契约的投影。前端只拥有如何在输入框中呈现和编辑标记。[Image #N] 是呈现和持久化元数据;提供商收到类型化的 ImageContent,从不用标记代替其字节。粘贴的标记是带不同颜色的原子输入框跨度:光标移动和删除不能留下部分附加标记。用户输入的相同拼写文本仍是纯文本。提交时,只有已附加的跨度收到不可见的来源前缀;记录项中只有带前缀的标记产生模型图像。显示和仅文本的模型请求会移除该前缀。会话 JSON 记录标记是否有此前缀。没有该标志的旧会话在加载时给其已保存图像的引用打标签,保留先前语义。删除的未发送图像在空闲时立即丢弃,并在活动回合的提交时丢弃。工作区和剪贴板图像在进入会话前对照 20 MiB 上限检查,并按 MIME 签名验证;媒体存储在写入前再次验证。已保存的图像字节位于 ~/.crystal/media/<sha256> 下仅所有者、按内容寻址的文件中。会话 JSON 存储哈希和 MIME 类型,不是 Base64 字节。媒体文件在会话引用它之前写入,两次写入都使用临时文件然后原子替换。会话只持久化存档或模型上下文引用的图像。缺失、截断或被修改的媒体文件在恢复时被跳过,文本和其他附件仍然可用;操作者收到一条说明,其引用在之后的保存中保留,以便恢复该文件可以修复会话。内联 data 是受支持的会话表示;本地保存把它的图像字节移到媒体存储。JSON 会话导出保留标记来源,并把可用图像字节内联到 data,使其内容不依赖 Home 媒体文件。引用的媒体文件不可用时,其元数据留在导出中,但无法包含字节。存储不会自动删除未被引用的媒体文件。支持内联图像字节和绝对图像 URI。进程内插件、dotnet 操作者工具的原生 IMultimodalTool 路径,或 "output": "content" 的 exec 工具返回的图像被分配相同标记,并成为下一轮模型的输入。仅文本的回合拒绝 exec 图像结果,而不是丢弃它们。剪贴板粘贴在等待操作系统读取器之前保留图像编号。工具图像通过同一会话锁保留编号,该锁也保护图像查找和变更。失败的粘贴留下空号,而不是复用其编号。输入批次按顺序分发按键,因此 Ctrl+V 在随后的 Enter 提交提示之前完成附加。所选模型或提供商不支持图像输入时,dotnet 多模态工具从活动目录中省略。声明的 audioInput 或 videoInput 不会保留它们。config.json 的 imageModel 点名一个目录条目有 imageInput 的提供商和模型时,describe_image 是 Plan 和 Work 上的文本工具。它把该文件发给带图像描述提示的附带多模态客户端,并把回复作为文本返回。附带请求没有工具,不写入会话记录,并通过与宿主相同的档位映射使用 imageModel.thinkingEffort。view_image 只为支持图像的回合注册。它把文件作为 ImageContent 返回,使当前模型在下一轮看到它。两者都遵循 read 路径围栏。缺少图像模型凭据会使工具调用失败,且不阻止会话启动。

Responses、OpenAI 兼容 Chat Completions、DeepSeek Chat Completions、Anthropic Messages、Gemini GenerateContent 和 Ollama Chat 适配器接受文本和图像输入,只发出文本、推理和工具调用事件。原生 Gemini 适配器把工具结果图像作为 functionResponse 上的 inlineData 部分发送。那是 Gemini 3 多模态函数响应字段;较旧的模型可能拒绝该请求。原生 Ollama 适配器把它们发送在工具消息的 images 数组上。两种情况下记录都保留标记。Chat Completions 和 Anthropic 图像限制在用户和工具消息,以匹配其线路契约。剪贴板图像输入在 Windows 上通过 Windows PowerShell 读取,在 macOS 上通过 macOS 系统 osascript,在 Linux 上通过 wl-paste 或 xclip;它不捕获屏幕。Windows 在回退到位图转换前读取剪贴板 PNG 字节,并把 Base64 文本从 PowerShell 传给宿主。macOS 按该顺序尝试 PNG、JPEG 和 GIF 剪贴板表示。Linux 检查声明的剪贴板类型,并按该顺序尝试 PNG、JPEG、GIF 和 WebP。读取器输出和临时文件受图像大小上限约束。缺失的读取器、空图像剪贴板、不支持的图像字节、过大的图像和读取器失败有分开的操作者错误。读取器命令在运行时是可选的,它们缺失不阻止应用程序启动。模型必须用 imageInput: true 选择加入;不支持的组合在发送请求前被拒绝。audioInput 和 videoInput 是存储的声明。它们发布在插件模型事实和 PluginClientRequest 上,且不改变适配器能力、工具注册、附加、持久化或出站请求。所选服务层级和速度也发布在两个契约上;自定义协议工厂必须应用非空槽,或在创建客户端时拒绝它。内置适配器仍只接受文本和图像输入。接受音频或视频,以及非文本模型输出,仍然是 TODO。MCP 媒体传输是 TODO。

CrystalCode 不捕获截图,不控制浏览器、手机、虚拟机,不解释坐标,也不定义帧/设备协议。外部插件拥有这些行为,并可以通过通用工具边界返回普通的类型化图像。