
人工智能AI Agent代码智能体Agent 编排CLIAI 应用【免费下载链接】gsd-2A powerful meta-prompting, context engineering and spec-driven development system that enables agents to work for long periods of time autonomously without losing track of the big picture项目地址https://gitcode.com/gh_mirrors/gs/gsd-2点击查看免费下载导读ExtensionContextctx是 pi 扩展系统中连接扩展代码与 agent 运行时状态的关键桥梁每个事件处理器event handler都会收到一个ctx参数通过它可以与用户交互、读取会话状态、获取当前模型与上下文用量甚至编程式地触发压缩compaction与优雅退出。本文以 gsd-2 仓库中 docs/dev/extending-pi/08-extensioncontext-what-you-can-access.md 为骨架结合 packages/pi-coding-agent/src/core/extensions/types.ts 中的接口定义与 packages/pi-coding-agent/src/core/extensions/runner.ts 的运行时实现完整讲解ctx上每个字段的含义、使用方式与底层原理。读完本文你将能正确地在自定义扩展中读写运行时状态、调用 UI 原语、监控上下文水位并触发压缩写出健壮且符合 pi 运行时约束的扩展。一、ExtensionContext 是什么pi 的扩展系统允许扩展订阅 agent 生命周期事件session_start、agent_start、context、tool_call、stop等。每一个事件处理器都会被传入ctx: ExtensionContext它是扩展观察并操作 pi 运行时状态的窗口。其接口定义位于 packages/pi-coding-agent/src/core/extensions/types.tsexport interface ExtensionContext { /** UI methods for user interaction */ ui: ExtensionUIContext; /** Whether UI is available (false in print/RPC mode) */ hasUI: boolean; /** Current working directory */ cwd: string; /** Session manager (read-only) */ sessionManager: ReadonlySessionManager; /** Model registry for API key resolution */ modelRegistry: ModelRegistry; /** Current model (may be undefined) */ model: Modelany | undefined; /** Whether the agent is idle (not streaming) */ isIdle(): boolean; /** Abort the current agent operation */ abort(): void; /** Whether there are queued messages waiting */ hasPendingMessages(): boolean; /** Gracefully shutdown pi and exit. Available in all contexts. */ shutdown(): void; /** Get current context usage for the active model. */ getContextUsage(): ContextUsage | undefined; /** Trigger compaction without awaiting completion. */ compact(options?: CompactOptions): void; /** Get the current effective system prompt. */ getSystemPrompt(): string; /** Set or clear an in-memory compaction threshold-percent override (0 value 1). */ setCompactionThresholdOverride(percent: number | undefined): void; }ctx上的方法均为**在调用时解析resolved at call time**的 getter 或代理函数而非创建时快照。在 runner.ts 的createContext()中可以看到model等字段被实现为每次读取都调用当前绑定函数的 gettercwd也通过currentCwd()动态取值。这意味着即使扩展安装后 agent 状态发生变化例如切换了模型、进入了 idlectx读到的一直是最新值。关于ctx的构造过程、事件分发与扩展生命周期可进一步阅读 01-what-are-extensions.md 与 07-events-the-nervous-system.md。二、ctx.ui用户交互入口ctx.ui是与用户交互的主要方式其完整签名定义在 types.ts 的ExtensionUIContext中。原文档将 UI 方法分为两类阻塞式对话框Dialogs等待用户响应const choice await ctx.ui.select(Pick one:, [A, B, C]); const ok await ctx.ui.confirm(Delete?, This cannot be undone); const name await ctx.ui.input(Name:, placeholder); const text await ctx.ui.editor(Edit:, prefilled text);这四个方法都返回Promise调用方会一直等到用户作出响应。结合源码它们的精确签名与可选参数如下select(title: string, options: string[], opts?): Promisestring | string[] | undefined——选项选择器当opts.allowMultiple为true时返回值类型变为string[]confirm(title: string, message: string, opts?): Promiseboolean——确认对话框input(title: string, placeholder?: string, opts?): Promisestring | undefined——文本输入框placeholder可选editor(title: string, prefill?: string): Promisestring | undefined——多行文本编辑器。每个对话框方法还接受ExtensionUIDialogOptionstypes.ts包含三个值得注意的能力选项类型说明signalAbortSignal通过 AbortSignal 编程式关闭对话框timeoutnumber超时毫秒对话框自动关闭并实时倒计时显示allowMultipleboolean仅select有效允许多选返回string[]secureboolean文本输入类对话框隐藏输入字符若客户端表面支持非阻塞式 UIctx.ui.notify(Done!, info); // Toast notification ctx.ui.setStatus(my-ext, Active); // Footer status ctx.ui.setWidget(my-id, [Line 1]); // Widget above/below editor ctx.ui.setTitle(pi - my project); // Terminal title ctx.ui.setEditorText(Prefill text); // Set editor content ctx.ui.setWorkingMessage(Thinking...); // Working message during streaming这些方法立即返回用于向用户呈现非阻断信息notify(message, type?)——Toast 通知type取值为info | warning | error | successsetStatus(key, text)——在底部状态栏设置状态文本传入undefined可清除该 key 的状态见 types.tssetWidget(key, content)——在编辑器上方/下方渲染组件接受字符串数组或组件工厂函数可通过ExtensionWidgetOptions.placementaboveEditor | belowEditor默认aboveEditor控制位置types.tssetTitle(title)——设置终端窗口/标签页标题setEditorText(text)——设置核心输入编辑器的内容另有getEditorText()读取、pasteToEditor(text)模拟粘贴并触发大内容折叠处理setWorkingMessage(message)——设置流式输出期间的工作中提示不传参恢复默认传null可完全抑制。此外ExtensionUIContext还提供了setFooter/setHeader自定义底部/顶部组件、custom自定义带键盘焦点的组件支持overlay与overlayOptions、setEditorComponent自定义编辑器如文档注释中给出的 Vim 风格编辑器示例、主题相关方法getAllThemes/getTheme/setTheme与工具展开控制getToolsExpanded/setToolsExpanded。UI 架构与自定义组件的完整指南见 docs/dev/pi-ui-tui/README.md 和 12-custom-ui-visual-components.md。三、ctx.hasUI调用对话框前的必检项hasUI表示当前运行模式下 UI 是否可用falseprint 模式-p和 JSON 模式true交互模式interactive和 RPC 模式。原文档强调在非交互上下文中调用对话框方法之前务必先检查hasUI。其底层原因可以在 runner 源码中找到当没有 UI 上下文时runner 会使用noOpUIContextrunner.ts其中的select/input/editor静默返回undefined、confirm静默返回false、notify等为 no-opsetTheme返回{ success: false, error: UI not available }而hasUI()的实现正是this.uiContext ! noOpUIContextrunner.ts。因此若扩展在-p模式下调用await ctx.ui.confirm(...)会立即得到false而不打扰任何用户。推荐的防御性写法if (ctx.hasUI) { const ok await ctx.ui.confirm(Delete?, This cannot be undone); }runner 测试 runner.test.ts 也覆盖了createContext()的行为包括ctx.cwd与ctx.shutdown()的调用路径可作为回归参考。四、ctx.cwd当前工作目录ctx.cwd是一个字符串表示 agent 当前的进程工作目录在 runner 中通过currentCwd()动态读取runner.ts。它也是多个事件如before_commit、verify_result、milestone_start携带的标准字段之一。扩展在执行文件操作、拼接路径或调用子进程时应以ctx.cwd为基准。五、ctx.sessionManager会话状态只读sessionManager以只读方式暴露当前会话。原文档列出的方法如下ctx.sessionManager.getEntries() // All entries in session ctx.sessionManager.getBranch() // Current branch entries ctx.sessionManager.getLeafId() // Current leaf entry ID ctx.sessionManager.getSessionFile() // Path to session JSONL file ctx.sessionManager.getLabel(entryId) // Get label on entry结合 packages/pi-coding-agent/src/core/session-manager.ts 的实现这些方法的精确语义为方法返回源码位置与语义getEntries()SessionEntry[]session-manager.ts返回全部会话条目不含 header的浅拷贝会话是追加式的条目不可修改或删除getBranch(fromId?)SessionEntry[]session-manager.ts从指定条目默认当前 leaf沿 parent 链走到根按路径顺序返回包含消息、compaction、model change 等全部条目类型getLeafId()string \| nullsession-manager.ts当前分支叶条目 IDgetSessionFile()string \| undefinedsession-manager.ts会话 JSONL 文件路径getLabel(entryId)string \| undefinedsession-manager.ts获取条目的用户标签用于书签/导航除此之外只读接口还提供了getLeafEntry()、getEntry(id)、getChildren(parentId)、getTree()、getHeader()、getUsageTotals()、buildSessionContext()等方法供扩展更精细地遍历会话树。注意会话中的custom类型条目可被扩展用来持久化自己的状态但它不参与 LLM 上下文见 session-manager.ts 与 13-state-management-persistence.md。六、ctx.modelRegistry 与 ctx.model模型与密钥ctx.modelRegistry: ModelRegistry——模型注册表主要用于API key 解析。其getApiKey(model, sessionId?)会依据 provider 的鉴权模式如 OAuth从认证存储中取回密钥见 model-registry.ts。ctx.model: Modelany | undefined——当前模型可能为undefined例如 agent 尚未选择模型时。访问时需做空值判断。扩展可以利用modelRegistry在代表用户调用第三方 API 时复用已配置的凭证而不需要自己管理密钥。七、ctx.isIdle() / ctx.abort() / ctx.hasPendingMessages()控制流助手这三个方法用于检查与干预 agent 的运行状态ctx.isIdle()——agent 是否处于空闲不在流式输出中。在 agent-session.ts 中其实现为!this.isStreamingctx.abort()——中止当前的 agent 操作。实现为this.abort({ origin: user })即以“用户中止”的语义触发中止流程ctx.hasPendingMessages()——是否存在排队等待的消息。实现为this.pendingMessageCount 0agent-session.ts。典型场景扩展在收到notification事件idle类型时可结合isIdle()决定是否需要唤醒 agent 或发起新指令在需要停止耗时操作时调用abort()。八、ctx.shutdown()优雅退出ctx.shutdown()请求优雅关闭关闭会被推迟到 agent 空闲时才真正执行退出前会触发session_shutdown事件对应 types.ts 中的SessionShutdownEvent。从源码可以看到一个重要的安全约束在agent_end、stop、session_end这三个“关闭守卫事件”shutdown-guarded events的处理器中runner 会通过createEventContext()runner.ts注入一个会抛出异常的shutdown版本防止扩展在 agent 收尾阶段请求关闭造成竞态其余事件则直接使用createContext()runner.ts。九、ctx.getContextUsage()上下文用量监控getContextUsage()返回当前上下文 token 用量用于触发压缩或展示统计。ContextUsage的结构types.tsexport interface ContextUsage { /** Estimated context tokens, or null if unknown */ tokens: number | null; contextWindow: number; /** Context usage as percentage of context window, or null if tokens is unknown */ percent: number | null; }原文档给出的用法示例const usage ctx.getContextUsage(); if (usage usage.tokens 100_000) { // Context is getting large }底层实现位于 agent-session.ts值得注意的边界行为当前没有模型或模型contextWindow 0时返回undefinedtokens可能为null紧凑压缩compaction之后、下一次 LLM 响应到来之前上下文 token 数未知。因为最近一次压缩前的 assistant usage 反映的是压缩前的大小只有压缩边界之后成功响应的 assistant 消息的 usage 才可信当tokens未知时percent同样为null。因此扩展代码里usage.tokens 100_000的写法只应在tokens ! null时比较稳妥写法是if (usage usage.tokens ! null usage.tokens 100_000)。十、ctx.compact(options?)编程式触发压缩compact()以不等待完成的方式触发上下文压缩。原文档示例ctx.compact({ customInstructions: Focus on recent changes, onComplete: (result) ctx.ui.notify(Compacted!, info), onError: (error) ctx.ui.notify(Failed: ${error.message}, error), });CompactOptionstypes.ts与源码实现agent-session.ts说明customInstructions——可选的压缩指令字符串例如指示压缩摘要侧重哪些内容onComplete(result)——压缩完成后回调result为CompactionResultonError(error)——压缩失败时回调。源码中将compact包装为异步 IIFE先await this.compact(customInstructions)成功走onComplete失败捕获后走onError。压缩过程的生命周期事件session_before_compact可取消或定制、session_compact在压缩后触发及结果结构见 types.ts 与 16-compaction-session-control.md。十一、ctx.getSystemPrompt()当前生效的系统提示词getSystemPrompt()返回当前生效的系统提示词effective system prompt包含before_agent_start阶段对系统提示词的任何修改。其实现为() this.systemPromptagent-session.ts。结合 15-system-prompt-modification.md 可知扩展可以在before_agent_start事件处理器中返回新的systemPrompt覆盖默认提示词而ctx.getSystemPrompt()读取到的正是叠加了这些修改之后的最终版本。这在需要审计当前 agent 实际看到的系统提示词或依据提示词内容决定后续行为的场景中非常有用。十二、setCompactionThresholdOverride压缩阈值临时覆盖源码补充该方法是接口中的最后一个成员原文档未展开但它在自动压缩控制中很有价值ctx.setCompactionThresholdOverride(percent: number | undefined);设置一个仅存在于内存中的压缩阈值百分比覆盖0 value 1例如0.7表示上下文用到 70% 时触发压缩传undefined清除覆盖覆盖不会被持久化宿主集成需要在每次session_start时重新应用。该行为在 compaction-threshold.test.ts 中有完整覆盖setCompactionThresholdOverride applies in-memory、clears a prior override、preserves other compaction fields等用例其实现最终落到settingsManager.setCompactionThresholdOverrideagent-session.ts。十三、命令处理器专属ExtensionCommandContext普通事件处理器拿到的是上述ExtensionContext而命令处理器command handlers收到的是扩展版本ExtensionCommandContexttypes.ts它在ExtensionContext基础上追加了仅在用户主动发起的命令中安全的会话控制方法ctx.waitForIdle(); // Wait for the agent to finish streaming ctx.newSession(options?); // Start a new session, optionally with initialization ctx.fork(entryId); // Fork from a specific entry, creating a new session file ctx.navigateTree(...); // Navigate to a different point in the session tree ctx.switchSession(path); // Switch to a different session file ctx.reload(); // Reload extensions, skills, prompts, and themes其中newSession支持parentSession、setup(sessionManager)与workspaceRoot参数navigateTree支持summarize、customInstructions、replaceInstructions、label选项这些选项会透传给session_before_tree事件中的TreePreparation。在 runner 中createCommandContext()runner.ts把这些方法绑定到bindCommandContext()注入的处理函数上若命令上下文尚未绑定早期生命周期调用这些方法会抛出Command context not yet bound的明确错误runner.ts。十四、扩展开发中的实用建议综合原文档与源码行为编写使用ctx的扩展时可遵循以下实践调用对话框前必查hasUI——否则在-p/ JSON 模式下静默返回undefined/false可能造成逻辑偏差区分usage.tokens的null值——压缩后立即查询会得到null做阈值比较前先判空把getContextUsage()与compact()结合可以实现上下文接近阈值时自动压缩并通知用户的自主扩展尊重shutdown的守卫——不要在agent_end/stop/session_end处理器中调用shutdown()它会被 runner 显式拒绝需要结束整个进程应通过ctx.shutdown()空闲时才会真正执行并会触发session_shutdown事件善用只读会话数据——sessionManager.getBranch()可用于在扩展内重建当前分支的完整消息路径getTree()用于渲染会话树 UI上下文在调用时解析——ctx.model等字段每次读取都是最新值无需自行缓存刷新但也因此不要在构造时提前解构保存ctx.model否则可能读到过期状态。关于扩展的安装、事件订阅与工具注册的完整上手流程参见 03-getting-started.mdctx与ExtensionAPI的能力边界什么该用ctx、什么该用api详见 09-extensionapi-what-you-can-do.md。赞分享人工智能AI Agent代码智能体Agent 编排CLIAI 应用【免费下载链接】gsd-2A powerful meta-prompting, context engineering and spec-driven development system that enables agents to work for long periods of time autonomously without losing track of the big picture项目地址https://gitcode.com/gh_mirrors/gs/gsd-2点击查看免费下载相关推荐Apache Druid JavaScript 扩展开发指南运行时动态扩展的七类能力与安全实践Apache Druid JavaScript 扩展开发指南运行时动态扩展的七类能力与安全实践 Apache Druid 允许通过 JavaScript 在运数据库OLAP大数据后端Nuxt useNuxtApp() 深入指南访问与扩展应用级运行时上下文Nuxt useNuxtApp 深入指南访问与扩展应用级运行时上下文 useNuxtApp 是 Nuxt 内置的组合式函数composable用于访问前端后端Web框架SSROctotree性能监控实时跟踪扩展运行状态Octotree性能监控实时跟踪扩展运行状态 你是否曾遇到GitHub仓库加载缓慢的问题是否想知道Octotree扩展在后台如何工作本文将带你深入了解Oc开发工具上一篇如何快速搭建智能交易系统TradingAgents-CN实战指南下一篇翻译 PDF 还能保住版式5 分钟装好 BabelDOC 并跑通第一次输出创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考