开发工具代码编辑器数据科学【免费下载链接】positronPositron, a next-generation data science IDE项目地址https://gitcode.com/gh_mirrors/po/positron点击查看免费下载导读Kallichorekcserver是 Positron Supervisor 背后的多语言内核编排服务而客户端与服务器之间几乎所有实时通信——内核状态、标准输出、执行归属信息——都通过一条 WebSocket 连接承载。本文以 extensions/positron-supervisor/src/ws/ 目录下的 README 及其配套 TypeScript 源码为主线完整梳理 Kallichore WebSocket 消息的两大类别kernel与jupyter、消息类型的定义方式、客户端连接与分拣逻辑并沿调用链追踪消息最终如何被转换成 Positron 的LanguageRuntimeMessage呈现给用户。读完本文你将掌握该协议的消息格式、各字段含义以及从服务端收包到界面渲染的完整数据流。目录定位一份消息协议的契约文档extensions/positron-supervisor/src/ws/README.md用一句话定义了整个目录的职责该目录包含 Kallichore 服务器的 WebSocket 消息定义。这些消息是服务器与客户端通过 Kallichore 的 WebSocket 连接互相发送的内容。这段描述虽然简短但点明了三个关键事实消息方向服务器Kallichore→ 客户端Positron。README 明确指出这些是服务器与客户端之间发送的消息且 SocketMessage.ts 的注释进一步说明今天 Kallichore 只发送两种消息即这一协议当前是服务端单向推送为主传输载体WebSocket 长连接而非 HTTP 轮询协议边界消息分为Jupyter 协议消息与Kernel 元数据消息两大类。与 README 同目录的三个源文件构成了这份契约的完整实现分别是文件角色SocketMessage.ts消息根类型与kind判别字段KernelMessage.tsKernel 类消息的四种具体类型SocketSession.ts客户端 WebSocket 会话封装消息根类型SocketMessage与SocketMessageKind所有经 WebSocket 到达客户端的外层消息都实现SocketMessage接口。它只有一个字段kind用于判别消息类别SocketMessage.tsexport enum SocketMessageKind { /** Jupyter messages are messages conforming to the Jupyter protocol. */ Jupyter jupyter, /** Kernel messages are messages sent by Kallichore to deliver kernel status * and metadata. */ Kernel kernel, } export interface SocketMessage { /** The kind of message */ kind: SocketMessageKind; }这个判别字段是后续分拣逻辑的入口KallichoreSession.handleMessage()在收到每一条消息时首先检查data.kind是否存在然后据此走两条完全不同的处理路径KallichoreSession.tshandleMessage(data: any) { if (!data.kind) { this.log(Kallichore session ${this.metadata.sessionId} message has no kind: ${JSON.stringify(data)}, vscode.LogLevel.Warning); return; } switch (data.kind) { case kernel: this.handleKernelMessage(data); break; case jupyter: this.handleJupyterMessage(data); break; } }从源码结构看jupyter类消息承载的是符合 Jupyter 协议的通道流量iopub/shell 等而kernel类消息承载的是 Kallichore 自身的控制面信息。二者共用同一条 WebSocket 连接、共用同一个kind字段做路由这保证了协议扩展时只需要新增枚举值即可接入新的消息类别。Kernel 消息族状态、输出与执行归属KernelMessage.ts 定义了四种接口前三者直接实现SocketMessage第四个是嵌套的数据结构。它们对应的 JSON 载荷在handleKernelMessage()中通过hasOwnProperty逐个特征字段探测KallichoreSession.ts。1.KernelMessageStatus内核状态推送export interface KernelMessageStatus extends SocketMessage { status: string; }这是内核生命周期状态的最小载体。实际载荷中status是一个对象形如{ status: ..., reason: ... }客户端取出status.status与positron.RuntimeState枚举比对后驱动运行时状态迁移。源码中还存在两处去重逻辑当收到starting状态但当前运行时既非Uninitialized也非Exited时忽略避免重启场景下重复广播当收到ready但当前已是Idle时同样忽略。这类消息负责把内核正在启动/已就绪/忙碌/已退出等状态机事件推送给前端。2.KernelOutputMessage内核日志输出export interface KernelOutputMessage extends SocketMessage { /** * A 2-element array containing the stream name and the output text. */ output: [string, string]; }output是一个二元组第一个元素是流名称如stdout第二个是输出文本。客户端收到后将其原样追加到该会话专属的内核输出通道_kernelChannelKallichoreSession.ts。从类型设计看该消息用于呈现内核进程自身的日志输出与 Jupyter 协议中的stream消息面向代码执行结果职责分离。3.KernelExecutionRequestedMessage外部执行的归属宣告这是该协议中最有特色的消息。KernelExecutionRequestedMessage的载荷结构如下KernelMessage.tsexport interface KernelExecutionRequestedMessage extends SocketMessage { executionRequested: { /** The execute_request ID; the parent ID of everything it produces. */ msg_id: string; /** The code that is about to run. */ code: string; /** When the request was submitted, in ISO 8601 format. */ requested_at: string; /** Who requested the execution. */ attribution: KernelExecutionAttribution; }; }其中KernelExecutionAttribution镜像了 Kallichore 共享库kcshared中的ExecutionAttribution定义KernelMessage.tsexport interface KernelExecutionAttribution { /** The kind of actor that requested the execution, e.g. agent. */ source: string; /** The name the agent reported in the MCP clientInfo, e.g. claude-code. */ agent_name?: string; /** The version the agent reported in the MCP clientInfo. */ agent_version?: string; /** The MCP workspace whose token authorized the request. */ workspace_id: string; /** The MCP tool used, e.g. execute_code or evaluate_code. */ tool: string; }各字段的语义字段类型含义sourcestring发起执行的参与者类型例如agentagent_namestring可选Agent 在 MCPclientInfo中上报的名称例如claude-codeagent_versionstring可选Agent 在 MCPclientInfo中上报的版本号workspace_idstring授权该请求的 MCP workspace tokentoolstring所使用的 MCP 工具例如execute_code或evaluate_code这条消息出现的时机很有讲究它会在随之而来的 iopub 流量之前被发送。为什么需要它RuntimeMessageEmitter.ts 的注释给出了答案——Jupyter 协议本身无法告知客户端这段代码是谁执行的iopub 消息只携带 parent header不携带父消息的元数据。当外部 Agent 通过 supervisor 的 MCP 服务器提交了执行请求时Positron 仅凭 Jupyter 流量无法区分用户自己在 Console 里敲的代码和Agent 远程执行的代码。KernelExecutionRequestedMessage就是 supervisor 在 iopub 流量之前发来的预告让客户端能够正确归属并标记这段执行。4. 同类消息的扩展空间handleKernelMessage()中还存在resourceUsage、clientDisconnected、exited三个分支KallichoreSession.tsresourceUsage携带RuntimeResourceUsage客户端会补充内核的 OS 进程 ID 后触发资源占用事件新会话首次收到时还会惰性向 Kallichore API 拉取 PID并用 in-flight 标记防止并发刷接口clientDisconnected表明会话被转移给其他客户端本客户端关闭 socket、将运行时标记为Exitedreason 为Transferred并永久禁止重连exited触发onExited退出流程。这些分支当前并未在 KernelMessage.ts 中一一对应定义类型从源码结构看resourceUsage等字段直接透传为 Positron 侧类型这也印证了 README 中今天只有两种消息的表述——协议仍在演进中kind判别字段为后续扩展保留了清晰入口。Jupyter 消息流另一条通道与 Kernel 消息并列的jupyter类别承载标准 Jupyter 协议流量。其类型定义集中在 extensions/positron-supervisor/src/jupyter/ 目录该目录的 README 描述为Jupyter 消息的类型定义以及为 commands、requests、replies 增加结构的工具类。从目录内容可以看到消息类型覆盖了协议的主要面请求类ExecuteRequest、KernelInfoRequest、CommInfoRequest、DebugRequest、ShutdownRequest、IsCompleteRequest等命令/回复类CommOpenCommand、CommMsgCommand、CommCloseCommand、InputReplyCommand、RpcReplyCommand等事件类JupyterStreamOutput、JupyterDisplayData、JupyterExecuteInput、JupyterKernelStatus、JupyterInputRequest、JupyterErrorReply等。RuntimeMessageEmitter.emitJupyter()以msg.header.msg_type为键的巨型 switch 将各类 Jupyter 消息翻译为 Positron 的LanguageRuntimeMessageRuntimeMessageEmitter.ts例如stream→LanguageRuntimeStream、status→LanguageRuntimeState、input_request→LanguageRuntimePrompt、comm_open→LanguageRuntimeCommOpen。这意味着WebSocket 层只负责传输与分拣真正的协议翻译发生在RuntimeMessageEmitter层。客户端会话封装SocketSession与多传输支持SocketSession.ts 是协议的客户端落地实现本质是一个vscode.Disposable包装类export class SocketSession implements vscode.Disposable { public readonly userId: string; public readonly ws: WebSocket; constructor( public readonly uri: string, public readonly sessionId: string, public readonly channel: vscode.LogOutputChannel, headers?: { [key: string]: string } ) { this.ws createWebSocket(uri, undefined, { headers }); this.userId os.userInfo().username; } close() { this.ws.close(); } dispose() { this.close(); } }值得注意的细节构造时通过os.userInfo().username记录当前用户 ID源码注释说明它会附加到客户端发出的每条消息上用于服务端做同用户校验WebSocket 实例并非直接new WebSocket(...)而是经由createWebSocket()工厂创建NamedPipeHttpAgent.ts该工厂会识别wsnpipe://前缀并返回支持 Windows 命名管道的NamedPipeWebSocket。三种传输形态的 URI 构造Kallichore 的 API base path 可能对应 TCP、Unix 域套接字或 Windows 命名管道三种传输KallichoreSession.getWebsocketUri()分别构造 WebSocket URIKallichoreSession.ts传输URI 形态构造方式TCPws:///wss://由 HTTP base path 直接替换 scheme路径为/sessions/{sessionId}/channelsUnix 域套接字wsunix://{socketPath}:/api/channels/{sessionId}调用channelsUpgradeAPI 获取 socket 路径处理带/不带前缀两种情况Windows 命名管道wsnpipe://{pipeName}:/api/channels/{sessionId}同样经由channelsUpgrade获取管道名并补齐\\.\pipe\前缀NamedPipeWebSocket的实现方式是解析wsnpipe://URL、提取管道名与路径将其转换为ws://localhost{path}并注入自定义 HTTP AgentNamedPipeHttpAgent重写createConnection用net.connect直连命名管道从而复用标准ws库完成 WebSocket 握手。连接生命周期与重连屏障消息协议最终依赖一条健壮的连接。KallichoreSession.connect()KallichoreSession.ts展示了完整的生命周期管理前置校验_canConnect为 false 时拒绝重连防止转移给其他客户端的会话被本端重新拉起URI 解析调用getWebsocketUri()按传输类型构造 URI认证从 API configuration 的 baseOptions headers 中取出 Bearer token 作为 WebSocket 握手请求头缺失时仅记录 Warning 不中断事件挂钩onopen打开_connected屏障Barrier允许后续消息发送若此前发生过断线则触发_onDidReconnectonerror连接建立后出错则关闭屏障并弹窗报错未建立则 rejectonclose若允许重连则派发DisconnectedEvent依据运行时是否Exited决定 reason 为Exit还是Unknown并关闭屏障、清空 socket 引用onmessageJSON.parse后交给handleMessage()分拣解析失败只记错误日志不影响连接。屏障_connected机制是整个协议可靠性的核心所有向内核发送的请求sendRequest等都等待屏障打开后才真正发出断线期间发送方会等待而非直接失败会话被 dispose 或转移时屏障被 cancel发送方立即收到明确错误。重启场景下restart()屏障会被替换为新的实例保证对替换后内核的连接可以继续发送。消息消费链路全景综合以上源码一条内核消息从服务端到 UI 的完整链路可以归纳为Kallichore (kcserver) │ 通过 WebSocket 推送 SocketMessagekind: kernel | jupyter ▼ SocketSession.ws.onmessage ── JSON.parse ──► KallichoreSession.handleMessage() │ ├── kindkernel ──► handleKernelMessage() │ ├── status ──► onStateChange()运行时状态机 │ ├── output ──► _kernelChannel内核日志面板 │ ├── resourceUsage ──► _resourceUsage 事件 │ ├── executionRequested ──► RuntimeMessageEmitter.onExecutionRequested() │ └── exited / clientDisconnected ──► 退出/转移流程 │ └── kindjupyter ──► handleJupyterMessage() ──► RuntimeMessageEmitter.emitJupyter() └── 按 msg_type 翻译为 LanguageRuntimeMessage ──► Positron 前端其中onExecutionRequested的实现揭示了执行归属消息的最终用途RuntimeMessageEmitter.ts它将消息转换为LanguageRuntimeExecutionRequested把attribution映射为CodeAttributionSource.Agent并使用agentLabel()将 Agent 上报的名称格式化为其规范名称源码注释说明 Console 用该规范名标记代码而非 Agent 自称的名字连同版本号与工具名写入 metadata。这样当 Console 中执行了代码时用户可以明确看到这段代码是由某个 Agent 通过哪个工具、在哪个 workspace 授权下执行的。调试与验证从源码看这套协议在运行时提供了丰富的可观测手段KallichoreSession的所有 WebSocket 事件连接、收发、错误、关闭均通过vscode.LogOutputChannel记录内核消息收包有专门的 RECV [kernel]: {...}调试日志handleMessage对缺少kind的消息、handleKernelMessage对未知状态值都会输出 Warning便于定位协议不兼容关联测试位于 extensions/positron-supervisor/src/test/如handshakeSocket.test.ts、server.test.ts、restartExitOrdering.test.ts、sendAfterExit.test.ts覆盖握手 socket、服务状态与重启/退出时序等周边行为。小结extensions/positron-supervisor/src/ws/目录虽然只有一份六行的 README但它所描述的协议层却是 Positron 数据科学 IDE 多语言内核通信的主动脉SocketMessage.kind提供了可扩展的消息判别机制KernelMessage.ts定义了内核状态、日志输出与执行归属三类控制面消息SocketSession则以一个可复用的会话封装支撑了 TCP / Unix 域套接字 / Windows 命名管道三种传输形态。理解这套协议有助于开发者阅读 supervisor 源码、排查内核通信问题或在扩展开发中正确消费运行时事件。赞分享开发工具代码编辑器数据科学【免费下载链接】positronPositron, a next-generation data science IDE项目地址https://gitcode.com/gh_mirrors/po/positron点击查看免费下载相关推荐Positron Supervisor 执行输出模型 ExecuteOutput 完全指南Kallichore 客户端三类输出消息解析Positron Supervisor 执行输出模型 ExecuteOutput 完全指南Kallichore 客户端三类输出消息解析 导读 本文围绕 Pos开发工具代码编辑器数据科学Tendermint Consensus P2P 消息协议详解四大通道与九种消息类型Tendermint Consensus P2P 消息协议详解四大通道与九种消息类型 本文基于 Tendermint Core 共识引擎的 P2P 消息规范区块链共识算法Tendermint P2P 消息协议详解通道协商、消息类型与六大组件实现Tendermint P2P 消息协议详解通道协商、消息类型与六大组件实现 本篇技术指南以 Tendermint 规范文档 spec/p2p/messages区块链共识算法上一篇d2l-en 高斯过程Gaussian Processes专题函数空间视角、核函数与 GPyTorch 回归实战下一篇TPFanCtrl2ThinkPad 双风扇静音控制的完整上手指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考