dsh-super-code 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -10
- package/client/index.js +576 -24
- package/cordis.patch.yml +1 -1
- package/docs/Changelog.md +9 -0
- package/docs/Compatibility.md +30 -0
- package/docs/UsageGuide.md +60 -0
- package/lib/connection/directories.d.ts +30 -0
- package/lib/connection/directories.d.ts.map +1 -0
- package/lib/connection/directories.js +82 -0
- package/lib/connection/directories.js.map +1 -0
- package/lib/connection/git.d.ts +5 -0
- package/lib/connection/git.d.ts.map +1 -0
- package/lib/connection/git.js +86 -0
- package/lib/connection/git.js.map +1 -0
- package/lib/connection/http.d.ts +38 -0
- package/lib/connection/http.d.ts.map +1 -0
- package/lib/connection/http.js +275 -0
- package/lib/connection/http.js.map +1 -0
- package/lib/connection/service.d.ts +57 -0
- package/lib/connection/service.d.ts.map +1 -0
- package/lib/connection/service.js +168 -0
- package/lib/connection/service.js.map +1 -0
- package/lib/connection/store.d.ts +21 -0
- package/lib/connection/store.d.ts.map +1 -0
- package/lib/connection/store.js +139 -0
- package/lib/connection/store.js.map +1 -0
- package/lib/connection/tasks.d.ts +84 -0
- package/lib/connection/tasks.d.ts.map +1 -0
- package/lib/connection/tasks.js +270 -0
- package/lib/connection/tasks.js.map +1 -0
- package/lib/connection/types.d.ts +90 -0
- package/lib/connection/types.d.ts.map +1 -0
- package/lib/connection/types.js +21 -0
- package/lib/connection/types.js.map +1 -0
- package/lib/dsh/connection-host.d.ts +81 -0
- package/lib/dsh/connection-host.d.ts.map +1 -0
- package/lib/dsh/connection-host.js +130 -0
- package/lib/dsh/connection-host.js.map +1 -0
- package/lib/dsh/connection.d.ts +72 -0
- package/lib/dsh/connection.d.ts.map +1 -0
- package/lib/dsh/connection.js +183 -0
- package/lib/dsh/connection.js.map +1 -0
- package/lib/dsh/index.d.ts.map +1 -1
- package/lib/dsh/index.js +2 -0
- package/lib/dsh/index.js.map +1 -1
- package/package.json +7 -6
- package/presets/super-code/agent.cordis.yml +1 -1
package/cordis.patch.yml
CHANGED
package/docs/Changelog.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# 版本记录 · Changelog
|
|
2
2
|
|
|
3
|
+
- **0.3.8 · 2026-10-26**:新增默认关闭、仅监听 `127.0.0.1` 且需凭证认证的 Streamable HTTP MCP 服务,提供 `dsh_sessions`、`dsh_run`、`dsh_wait`、`dsh_send`、`dsh_cancel` 与 `dsh_request_directory`。外部客户端可委派原生 DSH 对话、读取进度、跟进和取消,沿用宿主模型、预设及权限,不改变普通会话提示词,也不自动批准工具权限。保留幂等请求、重启中断状态、有界输出及 Git 工作区观察。[MCP 连接](UsageGuide.md#mcp-连接--mcp-connection)
|
|
4
|
+
**0.3.8 · 2026-10-26**: Adds an opt-in, token-authenticated Streamable HTTP MCP service bound to `127.0.0.1`, with `dsh_sessions`, `dsh_run`, `dsh_wait`, `dsh_send`, `dsh_cancel`, and `dsh_request_directory`. External clients can delegate native DSH conversations, inspect progress, follow up, and cancel using the host model, preset, and permissions. Normal conversation prompts and tool approvals are unchanged. Includes idempotent requests, interrupted-state recovery without automatic replay, bounded output, and Git workspace observations. [MCP connection](UsageGuide.md#mcp-连接--mcp-connection)
|
|
5
|
+
|
|
6
|
+
连接后可按允许目录查询本服务持有的最近对话与连接容量,由调用方明确复用指定任务或新建,不默认复用最新对话。最大连接数与任务并发同步,默认均为 3,保留用户已保存的上限。目录改为工作区与自定义目录勾选列表,每次打开刷新;外部申请新目录需要用户在 DSH 弹窗中批准,撤权后不能通过复用绕过限制。
|
|
7
|
+
Lists recent service-owned conversations and connection capacity by allowed directory, so callers explicitly reuse a selected task or create a new conversation; the latest conversation is never selected automatically. Connection and task-concurrency limits stay synchronized, default to three, and preserve saved user limits. Workspace and custom-directory checklists refresh when opened. External requests for new directories require consent in DSH, and reuse cannot bypass revoked directory access.
|
|
8
|
+
|
|
9
|
+
设置新增首页概览,集中展示预设状态与版本、删除保护等级、MCP 开关及在线/历史对话数量;客户端和关联会话详情归连接页,删除保护独立成页,预设配置直接展开。连接修改自动保存,凭证默认展开;修复工作区实体 getter 丢失导致“目录不可用”和无法启用连接的问题。保留 `0.1.5-alpha.1` 至 `0.2.1-rc.2` 的已适配范围,分批宿主验证及平台限制见[兼容性记录](Compatibility.md),本次不新增效果评测成绩。
|
|
10
|
+
Adds a Home overview for preset status and versions, deletion protection, the MCP switch, and connected/past conversation counts. Client and linked-session details live in Connection; deletion protection has a separate tab, and preset configuration displays directly. Connection changes save automatically and credentials open expanded. Fixes missing Workspace getters that marked valid directories unavailable and prevented activation. Retains the adapted `0.1.5-alpha.1`–`0.2.1-rc.2` range; see [compatibility records](Compatibility.md) for staged host checks and platform limits. No new effectiveness scores are claimed.
|
|
11
|
+
|
|
3
12
|
- **0.3.7 · 2026-10-24**:新增关闭、宽松、严格三档删除保护,默认宽松:提示优先使用可恢复的 `trash`,脚本中同样建议使用,用户明确要求时可用 `rm`;严格模式识别永久删除命令并逐次请求确认,官方预设另设开关且默认关闭。兼容旧布尔设置与 v4 日志。[删除保护](UsageGuide.md#删除保护--deletion-protection)
|
|
4
13
|
**0.3.7 · 2026-10-24**: Adds Off, Relaxed, and Strict deletion protection, defaulting to Relaxed: prefer recoverable `trash`, including in scripts, while honoring explicit `rm` requests. Strict mode recognizes permanent-deletion commands and requests per-call approval; official presets opt in separately. Supports legacy boolean settings and v4 journals. [Deletion protection](UsageGuide.md#删除保护--deletion-protection)
|
|
5
14
|
|
package/docs/Compatibility.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# 宿主兼容性 · Host Compatibility
|
|
2
2
|
|
|
3
|
+
## 0.3.8 · MCP 连接 · MCP Connection · 2026-10-26
|
|
4
|
+
|
|
5
|
+
**会话列表与显式复用增量(2026-10-26):** 253 项测试通过,覆盖真实 MCP HTTP 会话查询、目录过滤、显式复用/新建、连接容量、默认上限 3、旧配置迁移及撤权边界。日常 NEXT `2.0.19-next` 安装候选后,真实 MCP SDK 握手发现六个工具,按四个工作目录查询到六条历史任务;凭证、已有对话和用户上限 10 均保留,任务并发同步为 10,未发送模型提示词。最新会话列表/复用仅完成上述集成测试及 NEXT 增量验证,下述 26 目标基础矩阵和四端设置验证属于较早候选的证据,未全部重跑。每条对话的在线连接数反映当前关联连接(0 或 1),不代表多客户端租约或原子会话锁。
|
|
6
|
+
|
|
7
|
+
**Conversation-list and explicit-reuse delta (2026-10-26):** All 253 tests pass, including real MCP HTTP session queries, directory filtering, explicit reuse/create, connection capacity, the default limit of three, legacy-setting migration, and revocation boundaries. After installing the candidate on daily NEXT `2.0.19-next`, a real MCP SDK handshake discovers six tools and queries six historical tasks across four working directories. Credentials, conversations, and the user's limit of ten are preserved, with task concurrency synchronized to ten; no model prompt is sent. The latest list/reuse changes have only these integration and NEXT delta checks. The 26-target baseline and four-host settings checks below are evidence for earlier candidates, not a full rerun. Per-conversation connection counts reflect the current associated connection (zero or one), not multi-client leases or an atomic conversation lock.
|
|
8
|
+
|
|
9
|
+
**工作区目录与自动保存修复(2026-10-26):** 显式读取 Workspace 实体的路径、名称 getter,修复空路径被误判为“目录不可用”、无法选择有效目录启用 MCP 的问题。连接设置改为自动保存,移除保存/取消按钮;串行处理后续修改,无效输入与失败不误报成功,撤销最后一个允许目录时同时关闭 MCP。249 项测试、类型检查、构建与客户端语法检查通过。最低 Web `0.1.5-alpha.1`、最高已适配 Web `0.2.1-rc.2`、官方 macOS arm64 Desktop `0.2.1-rc.2`、NEXT `2.0.19-next` 均完成单实例串行增量验收:通过宿主公开 API 创建含中文、空格的真实工作区,确认路径/名称/可用性;修改端口与连接数自动持久化,真实 MCP SDK 客户端可认证并发现工具,目录撤权、重新启用与页面重载均通过。独立浏览器另验证切页保存、关闭设置时提交最后一次输入及无效值不落盘。四端页面脚本错误为零;此前目录测试未覆盖 Workspace 原型 getter,此次已补齐。中间版本保留此前记录,原生目录选择确认/取消限制不变。
|
|
10
|
+
|
|
11
|
+
**Workspace and automatic-save fix (2026-10-26):** Explicitly reading Workspace path/title getters fixes blank paths incorrectly marked unavailable, which prevented valid workspace selection and MCP activation. Connection changes now save automatically without save/cancel buttons. Writes are serialized, invalid inputs and failures are not reported as saved, and revoking the final directory also turns MCP off. All 249 tests, type checking, build and client syntax checks pass. Sequential single-instance checks pass on Web `0.1.5-alpha.1` and `0.2.1-rc.2`, official macOS arm64 Desktop `0.2.1-rc.2`, and NEXT `2.0.19-next`. They create real workspaces with Chinese characters and spaces through host APIs, verify getter-backed paths/titles and availability, persist port/connection limits automatically, authenticate a real MCP SDK client and discover tools, revoke access, re-enable and reload. Separate browser checks cover tab changes, flushing the last edit when settings close, and rejecting invalid values. No page script errors occurred. Earlier directory checks missed prototype getters; this regression now has coverage. Intermediate versions retain prior evidence and native-picker confirmation/cancellation remains outside the verified scope.
|
|
12
|
+
|
|
13
|
+
**设置第二轮与目录审批(2026-10-26):** 243 项测试、类型检查、构建和客户端语法检查通过。最低 Web `0.1.5-alpha.1`、最高已适配 Web `0.2.1-rc.2`、官方 macOS arm64 Desktop `0.2.1-rc.2`、已安装 NEXT `2.0.19-next`(Harness `0.2.1-rc.2`)完成单实例串行增量验收:五标签首页、预设状态归首页、保护独立保存、目录勾选、默认展示凭证、真实 MCP 客户端连接及设置关闭时的全局目录审批;批准后同一连接可在新目录创建并完成原生会话,拒绝不会授予访问权限。四端保存了截图,页面脚本错误为零。Web 的 SSH 启动情境另验证了网页目录浏览器和取消。原生目录选择器入口已调用,但系统辅助功能接口超时,尚未完成原生文件选择的确认/取消验收;不将它算作通过。下述 26 目标全矩阵仍是上一候选的历史证据,不宣称本轮全部复验。
|
|
14
|
+
|
|
15
|
+
**Settings and directory-consent delta (2026-10-26):** All 243 tests, type checking, build and client syntax checks pass. Single-instance sequential checks cover Web `0.1.5-alpha.1` and `0.2.1-rc.2`, official macOS arm64 Desktop `0.2.1-rc.2`, and installed NEXT `2.0.19-next` (Harness `0.2.1-rc.2`). They verify the Home overview, separate protection settings, directory checkboxes, expanded credentials, actual MCP connections and global consent with settings closed. Approval enables native session execution over the same connection; rejection grants nothing. Screenshots were saved with no page script errors. Web checks also exercise browse-directory selection and cancellation in an SSH launch scenario. The native picker entry was invoked, but OS accessibility timed out; native selection confirmation/cancellation remains unverified. The 26-target matrix below is evidence for the previous candidate, not a full rerun of this delta.
|
|
16
|
+
|
|
17
|
+
2026-10-26 后续布局调整:关联会话及客户端详情移至“连接”,首页仅展示在线/历史对话数量;预设配置改为直接展示,去掉折叠和重复标题。245 项测试、类型检查、构建和客户端语法检查通过。最低 Web `0.1.5-alpha.1`、最高已适配 Web `0.2.1-rc.2`、官方 macOS arm64 Desktop `0.2.1-rc.2` 与 NEXT `2.0.19-next` 完成单实例串行增量验收并保存截图,页面脚本错误为零:连接页断开后会话归入历史,经新连接明确继续后恢复在线且不重复显示;幂等找回仅更新关联,不重复派发。独立浏览器组件检查另覆盖空状态和打开会话。中间版本未重跑本次布局,原生目录选择确认/取消的限制仍同上。
|
|
18
|
+
|
|
19
|
+
The subsequent layout delta on 2026-10-26 moves client and linked-session details to Connection, keeps only connected/past conversation counts on Home, and displays the preset form directly without repeated headings. All 245 tests, type checking, build and client syntax checks pass. Sequential single-instance checks with screenshots pass on minimum Web `0.1.5-alpha.1`, latest adapted Web `0.2.1-rc.2`, official macOS arm64 Desktop `0.2.1-rc.2`, and NEXT `2.0.19-next`, with no page script errors. Disconnecting from Connection moves the conversation to history; an explicit follow-up over a new connection restores its connected status without duplication. Idempotent retries update the association without dispatching again. Separate browser component checks also cover empty states and opening conversations. Intermediate versions were not rerun for this layout; the native-picker confirmation/cancellation limitation above remains.
|
|
20
|
+
|
|
21
|
+
`0.3.8` 基于正式版 `0.3.7`,合入 `feat/mcp-delegation` 的默认关闭本机 MCP 服务与连接设置。下方运行预算矩阵中的 **20 个 Web 版本、5 个官方 macOS arm64 Desktop 版本及 DSH NEXT** 均通过基础连接验收:设置保存、真实 MCP SDK 客户端认证、原生 Super Code 根会话、重复请求去重、同会话补充要求与运行中取消。宿主使用隔离 profile,不修改日常配置。
|
|
22
|
+
|
|
23
|
+
Version `0.3.8`, based on released `0.3.7`, merges the opt-in local MCP service and connection settings from `feat/mcp-delegation`. The **20 Web versions, five official macOS arm64 Desktop versions and DSH NEXT** in the runtime-budget matrix below pass baseline connection checks: settings persistence, authentication with a real MCP SDK client, native Super Code root sessions, duplicate-request coalescing, follow-ups and live cancellation. Isolated profiles leave daily configuration untouched.
|
|
24
|
+
|
|
25
|
+
早期三标签候选的增量验收覆盖最低 Web `0.1.5-alpha.1`、已适配最高 Web `0.2.1-rc.2`、官方 Desktop `0.2.1-rc.2` 和 NEXT `2.0.17-next`。四端均通过三标签设置、独立连接草稿、凭证轮换时保留草稿、切页隐藏凭证、通用“连接 Prompt”、原生子 Agent 执行和整树取消。冷进程重启保留启用设置、凭证与任务 ID;未完成任务没有自动重发或误报成功,显式补充要求后可继续同一会话。官方 Desktop `0.2.0-rc.1/rc.2` 另通过上一 UI 候选的串行增量检查,其余版本保留基础候选记录,不宣称全部复验最终文案。
|
|
26
|
+
|
|
27
|
+
Earlier three-tab candidate checks cover minimum Web `0.1.5-alpha.1`, latest adapted Web `0.2.1-rc.2`, official Desktop `0.2.1-rc.2`, and NEXT `2.0.17-next`. All four pass three-tab settings, independent drafts, draft preservation during token rotation, token hiding on tab changes, the generic Connection Prompt, native child-Agent execution and whole-tree cancellation. Cold process restarts retain enabled settings, credentials and task IDs without replaying pending prompts or reporting false success; an explicit follow-up resumes the same session. Official Desktop `0.2.0-rc.1/rc.2` also passed serial delta checks on the preceding UI candidate. Other versions retain baseline evidence rather than a claim that all final wording was rerun.
|
|
28
|
+
|
|
29
|
+
上述早期增量与重启验收严格单实例串行运行,退出前一宿主后才启动下一宿主。241 项全量测试、类型检查、构建及客户端语法检查通过,包含真实 MCP HTTP、幂等冲突、任务归属、目录边界、断线、权限等待、取消、恢复和 Git 工作区观察。测试模型为本地确定性 LlmAdapter,经过真实宿主 Agent 与工具链;没有调用外部大模型,不代表模型效果评测。Web 使用 Chromium,原生仅覆盖 macOS arm64;Windows/Linux、macOS x64、Safari 专属行为与客户端根据 Prompt 自动配置连接的能力未验收。
|
|
30
|
+
|
|
31
|
+
Those earlier delta and restart runs use one DSH instance at a time, stopping the previous host before starting the next. All 241 tests, type checking, build and client syntax checks pass, including real MCP HTTP, idempotency conflicts, ownership, directory boundaries, disconnects, permission waits, cancellation, recovery and Git workspace observations. A local deterministic LlmAdapter drives actual host Agents and tools; no external model is called and this is not an effectiveness evaluation. Web uses Chromium and native coverage is macOS arm64 only. Windows/Linux, macOS x64, Safari-specific behavior and clients’ ability to configure MCP automatically from a prompt remain unvalidated.
|
|
32
|
+
|
|
3
33
|
## 0.3.7 · 删除保护与任务状态 · Deletion Protection and Task Status · 2026-10-24
|
|
4
34
|
|
|
5
35
|
正式发布候选保留稳定记忆库,未包含开发中的版本化记忆或任务 skills。229 项测试、类型检查、构建和客户端语法检查通过。下方相同的 20 个 Web、5 个官方 macOS arm64 Desktop 与 DSH NEXT,均在真实宿主组件上通过 25 项删除保护/任务投影检查,包含旧设置、官方预设隔离、逐次确认、旧/新日志、嵌套 PTC、文件归属和任务状态不干预模型请求的回归。
|
package/docs/UsageGuide.md
CHANGED
|
@@ -264,3 +264,63 @@ These are recorded host actions, not proof that the model understood or followed
|
|
|
264
264
|
历史会话的记忆可直接查看,不需要恢复 Agent 或再次调用模型。记忆库支持新增、编辑、取消、保存和删除。编辑时可修改类型、标题和内容;取消不保存,删除需要确认。手动保存的条目标为“手动维护”,仅保留当前内容,不保留版本历史。
|
|
265
265
|
|
|
266
266
|
You can browse memory from stored conversations without resuming an Agent or making another model call. The library supports Add, Edit, Cancel, Save, and Delete. Edit the type, title, and content; Cancel discards the draft, and Delete asks for confirmation. Manually saved entries are marked accordingly. Only current content is kept, with no version history.
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
## MCP 连接 · MCP Connection
|
|
270
|
+
|
|
271
|
+
设置 → Super Code 模式默认打开“首页”,集中显示预设状态与版本、保护等级、MCP 开关,以及正在连接和历史对话的数量。客户端和关联会话详情、打开会话及断开操作位于“连接”标签。预设、上下文、删除保护、连接分别配置;预设配置页直接展示表单。MCP 默认关闭,在“连接”标签中勾选允许的工作目录、调整本机端口和最大连接数;修改会自动保存,无需确认按钮。服务只监听 `127.0.0.1`,地址以页面显示为准;端口冲突会显示错误。
|
|
272
|
+
|
|
273
|
+
Settings → Super Code opens **Home**, with preset status and versions, protection level, the MCP switch, and counts of connected and past conversations. Client and linked-session details, opening conversations and disconnect actions are in **Connection**. Preset, context, deletion protection and connection settings have separate tabs. Preset configuration shows its form directly. MCP is disabled by default. In **Connection**, select allowed working directories and adjust the local port and maximum connections. Changes save automatically without a confirmation button. The service listens on `127.0.0.1` only; use the displayed URL. Port conflicts are reported explicitly.
|
|
274
|
+
|
|
275
|
+
工作目录以勾选列表展示,每次进入连接页会重新读取 DSH 工作区。首次配置时预选已有有效工作区,修改后自动保存并保留用户选择;后来新增的工作区不会静默获得访问权限。可以通过目录选择器添加目录,取消勾选会撤销该目录的入口授权,取消最后一个允许目录时会同时关闭 MCP。手动添加但未勾选的目录仍保留在列表中。允许目录包含其子目录。
|
|
276
|
+
|
|
277
|
+
Directories appear as a checkbox list refreshed from DSH workspaces when opening Connection. Existing valid workspaces are initially selected in the first configuration draft; edits save automatically and later workspaces are never silently granted access. Add directories with the directory picker. Unchecking revokes that directory's admission grant; removing the last grant also turns MCP off. Unchecked manually added directories remain listed. Each grant includes descendants.
|
|
278
|
+
|
|
279
|
+
最大连接数限制真实 MCP 协议会话(默认 3,上限 32),并同时作为任务执行并发上限。在连接页可以断开客户端,空闲 10 分钟也会释放连接;断开不会取消已接收任务。正在连接的对话按其关联 MCP 连接是否在线统计,断开后计入历史;与任务是否执行完成无关。连接凭证默认展开,离开连接页后隐藏,再次进入时重新读取。
|
|
280
|
+
|
|
281
|
+
Maximum connections counts MCP protocol sessions (default 3, maximum 32) and is also the task execution concurrency limit. Disconnect clients from Connection; idle connections also expire after 10 minutes. Disconnecting does not cancel accepted tasks. Conversations count as connected while their linked MCP connection is online, regardless of task completion; after disconnect they count as past conversations. The token is expanded by default in Connection, cleared when leaving the tab and reloaded on return.
|
|
282
|
+
|
|
283
|
+
### 连接 Prompt · Connection Prompt
|
|
284
|
+
|
|
285
|
+
1. 在连接页复制“连接 Prompt”,交给支持 Streamable HTTP MCP 的客户端配置连接。提示词包含页面当前地址、认证方式、六项工具与任务状态约定,不包含真实凭证,也不绑定特定客户端。连接后先调用 `dsh_sessions` 按工作目录查看最近对话、状态和连接额度,再由调用方选择传 `taskId` 复用历史或传 `newConversation: true` 新建;不会默认复用最新对话。
|
|
286
|
+
2. 单独复制连接凭证,在客户端安全保存并配置为 `Authorization: Bearer <连接凭证>`。不要把实际凭证写进仓库或共享提示词。
|
|
287
|
+
3. 保持提供连接的 DSH Web 服务或桌面应用运行。更换凭证后同步更新客户端;旧凭证立即失效。客户端是否允许由提示词自动配置 MCP,取决于客户端自身能力;也可以使用页面地址和认证方式手动配置。
|
|
288
|
+
|
|
289
|
+
Copy **Connection Prompt** from the Connection tab and give it to a client that supports Streamable HTTP MCP. It contains the current URL, authentication method, six tools and task-state conventions, without an actual token or client-specific command. After connecting, call `dsh_sessions` for the working directory to see recent conversations, statuses and connection capacity. Let the caller choose whether to pass `taskId` to reuse history or `newConversation: true` to create a new root; `dsh_run` never defaults to the latest conversation. Copy the token separately and securely configure `Authorization: Bearer <connection token>` in the client. Keep the serving DSH process running, and update the client after token rotation. Whether a prompt can configure MCP automatically depends on the client; manual setup using the shown URL and authentication is also supported. Never put actual credentials in repository files or shared prompts.
|
|
290
|
+
|
|
291
|
+
| 工具 / Tool | 用途 / Behavior |
|
|
292
|
+
|---|---|
|
|
293
|
+
| `dsh_sessions` | 连接后按允许的工作目录返回最近对话、状态、可复用标记、每条对话的连接数,以及当前/最大/剩余连接数和任务并发占用。调用方据此选择复用或新建。 / After connecting, list recent conversations for an allowed working directory with status, reuse availability, per-conversation connection count, current/maximum/available connections, and active task capacity. Use it to choose reuse or a new root. |
|
|
294
|
+
| `dsh_run` | 传 `taskId` 精确复用历史根会话;传 `newConversation: true` 明确新建,未传时为兼容旧客户端也新建。相同 `requestId` 与相同输入不会重复提交,输入不同会报冲突。 / Pass `taskId` to reuse an exact history entry; pass `newConversation: true` to make a new root explicit. Omitting both also creates a new root for backward compatibility. Retrying identical input with the same request ID does not dispatch again; conflicting input is rejected. |
|
|
295
|
+
| `dsh_wait` | 提供任务 ID 时读取状态、输出、工作区观察及游标后的事件,最长等待 30 秒;省略任务 ID 时分页列出本服务持有的任务。 / Read task state, output, workspace observations and events after a cursor, with waits bounded to 30 seconds; omit the task ID to list owned tasks. |
|
|
296
|
+
| `dsh_send` | 在同一根会话补充要求或明确继续,使用新的请求 ID;不会代替用户批准宿主权限。 / Queue a follow-up or explicitly continue the same root session with a new request ID. Does not approve host permissions. |
|
|
297
|
+
| `dsh_request_directory` | 申请新增工作目录,由 DSH 用户明确批准;重复请求查询审批状态。 / Request additional directory access with explicit consent in DSH; repeat to poll the decision. |
|
|
298
|
+
| `dsh_cancel` | 请求取消根会话及受管理后代;需继续观察真实状态,不能把取消请求当成全部停止。 / Request cancellation of the root and managed descendants; observe the resulting state to confirm execution stopped. |
|
|
299
|
+
|
|
300
|
+
### 新增目录申请 · Additional Directory Requests
|
|
301
|
+
|
|
302
|
+
外部会话可调用 `dsh_request_directory`,提交稳定的 `requestId`、已存在的绝对 `path` 和 `reason`。DSH 会在全局弹出确认对话框,显示客户端名称、实际目录和申请理由,不需要先打开设置。只有用户点击“允许访问”,才会将该目录加入列表并勾选;审批沿用最新配置,不覆盖同时发生的其他设置修改,也不会断开已有 MCP 连接。申请不会触发模型调用,且不能由模型的自动审批策略代为同意。
|
|
303
|
+
|
|
304
|
+
重复相同输入可查询 `pending` / `approved` / `rejected` / `expired` 状态;相同 ID 改变输入会报冲突。批准前不能在该目录委派任务。待审批请求最多 8 条,5 分钟过期;拒绝、关闭服务或重启均不自动授权。请求历史为有界的进程内记录(最多 100 条),已批准的目录配置会保存。客户端名称和理由来自客户端,仅供辨认。
|
|
305
|
+
|
|
306
|
+
External sessions call `dsh_request_directory` with a stable `requestId`, an existing absolute `path` and a `reason`. A global DSH dialog shows the client name, canonical directory and reason even when settings is closed. Only the user's **Allow access** action adds and selects the directory. Approval merges into the latest configuration without overwriting concurrent changes or disconnecting clients. It does not invoke a model and cannot be approved by a model's automatic permission policy.
|
|
307
|
+
|
|
308
|
+
Repeat identical input to read `pending`, `approved`, `rejected` or `expired`; changing input under the same ID conflicts. Delegation is blocked until access is approved. At most eight pending requests are allowed, expiring after five minutes. Rejection, service shutdown and restart never grant access. Request history is in memory and bounded to 100 entries; approved directory settings persist. Client names and reasons are supplied by the caller for identification.
|
|
309
|
+
|
|
310
|
+
### 状态、权限与恢复 · State, Permissions and Recovery
|
|
311
|
+
|
|
312
|
+
任务沿用当前宿主的默认模型、Super Code 预设和权限;不修改普通会话的提示词或执行策略,也不会自动放行权限。调用方的沙箱不会自动传播到 DSH。允许目录限制用于任务入口,不构成文件系统沙箱;实际工具权限由 DSH 管理。同一工作区不会并行委派,可由调用方自行准备独立 worktree;插件不创建、删除或合并 worktree。
|
|
313
|
+
|
|
314
|
+
Tasks use the host’s default model, Super Code preset and permissions without changing ordinary conversation prompts or execution strategy. Caller sandbox restrictions do not automatically propagate to DSH. Allowed directories govern task admission, not filesystem isolation; DSH controls tool permissions. Delegations in the same workspace do not run concurrently. Callers may supply separate worktrees; the plugin does not create, delete or merge them.
|
|
315
|
+
|
|
316
|
+
`waiting_confirmation` 表示需要在 DSH 处理权限确认或受阻的回合。`finished` 仅表示根会话和已观测的受管理后代执行结束,返回的 `acceptance` 始终为 `not-verified`,需要调用方验证结果。文件信息来自执行前基线与当前 Git 工作区的有界观察,会保留原有脏文件列表,不能证明全部变化均由本任务产生;非 Git 目录、超出观察上限或读取失败时会标记不可用。
|
|
317
|
+
|
|
318
|
+
`waiting_confirmation` requires action in DSH. `finished` means the root and observed managed descendants have settled; it does not certify acceptance. Results carry `acceptance: not-verified`. File information is a bounded Git workspace observation relative to the starting baseline, including pre-existing dirty files, and does not establish exclusive attribution. Non-Git directories, exceeded observation limits and read failures are reported as unavailable.
|
|
319
|
+
|
|
320
|
+
等待超时或客户端断线不会取消执行。关闭连接停止接收请求,已接收任务继续由 DSH 管理。重启或热重载后不自动重发 prompt;可通过 `dsh_sessions` 或任务列表找回 ID,先观察会话,再明确继续。无法确认状态时保留 `interrupted` 或 `unavailable`,避免误报完成;未确认停止的任务会继续占用并发额度。
|
|
321
|
+
|
|
322
|
+
Wait timeouts and client disconnections do not cancel execution. Disabling the connection stops accepting requests while DSH continues managing accepted work. Restart and hot reload never automatically replay prompts. Recover task IDs through `dsh_sessions` or the task listing, inspect the session, then explicitly continue. Unconfirmed tasks remain interrupted or unavailable and retain their concurrency reservation.
|
|
323
|
+
|
|
324
|
+
任务记录、配置和凭证保存在当前 profile 的 `super-code-connection` 目录中,目录权限为 0700,文件为 0600;同一配置目录只允许一个服务实例持有。当前上限为 200 个任务记录、每任务 128 个补充操作和最近 200 条状态事件,输出保留最后 12,000 个字符。达到记录上限会明确拒绝新任务,不会悄悄丢弃幂等记录并重跑。
|
|
325
|
+
|
|
326
|
+
State, configuration and credentials are stored in the profile’s `super-code-connection` directory, with directory mode 0700 and file mode 0600. A profile has one service owner. Limits are 200 task records, 128 follow-up operations per task, the latest 200 state events, and the last 12,000 output characters. Reaching the history limit explicitly rejects new tasks rather than silently discarding idempotency records and redispatching work.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface DirectoryApplication {
|
|
2
|
+
requestId: string;
|
|
3
|
+
path: string;
|
|
4
|
+
reason: string;
|
|
5
|
+
}
|
|
6
|
+
export interface DirectoryRequest {
|
|
7
|
+
id: string;
|
|
8
|
+
requestId: string;
|
|
9
|
+
path: string;
|
|
10
|
+
reason: string;
|
|
11
|
+
client: string;
|
|
12
|
+
createdAt: number;
|
|
13
|
+
status: 'pending' | 'approved' | 'rejected' | 'expired';
|
|
14
|
+
}
|
|
15
|
+
/** Pending consent is deliberately ephemeral; only an approved allowlist is persisted. */
|
|
16
|
+
export declare class DirectoryRequests {
|
|
17
|
+
private readonly allowed;
|
|
18
|
+
private readonly now;
|
|
19
|
+
private readonly requests;
|
|
20
|
+
private readonly sources;
|
|
21
|
+
constructor(allowed: () => string[], now?: () => number);
|
|
22
|
+
private expire;
|
|
23
|
+
request(input: DirectoryApplication, client: string): Promise<DirectoryRequest>;
|
|
24
|
+
pending(): DirectoryRequest[];
|
|
25
|
+
resolve(id: string, decision: 'approved' | 'rejected', grant: (path: string) => Promise<void>): Promise<{
|
|
26
|
+
status: DirectoryRequest['status'];
|
|
27
|
+
}>;
|
|
28
|
+
rejectPending(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=directories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directories.d.ts","sourceRoot":"","sources":["../../src/connection/directories.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACzF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAC/F,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;CACzD;AACD,0FAA0F;AAC1F,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAkB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAF1E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;gBACvB,OAAO,EAAE,MAAM,MAAM,EAAE,EAAmB,GAAG,GAAE,MAAM,MAAiB;IACnG,OAAO,CAAC,MAAM;IAKR,OAAO,CAAC,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAsBrF,OAAO,IAAI,gBAAgB,EAAE;IACvB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;IAarJ,aAAa,IAAI,IAAI;CACtB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute } from 'node:path';
|
|
4
|
+
import { ConnectionError } from './types.js';
|
|
5
|
+
import { withinDirectory } from './tasks.js';
|
|
6
|
+
/** Pending consent is deliberately ephemeral; only an approved allowlist is persisted. */
|
|
7
|
+
export class DirectoryRequests {
|
|
8
|
+
allowed;
|
|
9
|
+
now;
|
|
10
|
+
requests = new Map();
|
|
11
|
+
sources = new Map();
|
|
12
|
+
constructor(allowed, now = Date.now) {
|
|
13
|
+
this.allowed = allowed;
|
|
14
|
+
this.now = now;
|
|
15
|
+
}
|
|
16
|
+
expire() {
|
|
17
|
+
for (const row of this.requests.values()) {
|
|
18
|
+
if (row.status === 'pending' && this.now() - row.createdAt >= 5 * 60 * 1000)
|
|
19
|
+
row.status = 'expired';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async request(input, client) {
|
|
23
|
+
this.expire();
|
|
24
|
+
const existing = this.requests.get(input.requestId);
|
|
25
|
+
if (existing) {
|
|
26
|
+
if (this.sources.get(input.requestId) !== input.path || existing.reason !== input.reason)
|
|
27
|
+
throw new ConnectionError('request-conflict');
|
|
28
|
+
return { ...existing };
|
|
29
|
+
}
|
|
30
|
+
if (!isAbsolute(input.path))
|
|
31
|
+
throw new ConnectionError('absolute-directory-required');
|
|
32
|
+
let path;
|
|
33
|
+
try {
|
|
34
|
+
path = await realpath(input.path);
|
|
35
|
+
if (!(await stat(path)).isDirectory())
|
|
36
|
+
throw new Error();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new ConnectionError('directory-unavailable');
|
|
40
|
+
}
|
|
41
|
+
if (this.pending().length >= 8)
|
|
42
|
+
throw new ConnectionError('directory-request-limit');
|
|
43
|
+
if (this.requests.size >= 100) {
|
|
44
|
+
const oldest = [...this.requests.entries()].find(([, row]) => row.status !== 'pending');
|
|
45
|
+
if (oldest) {
|
|
46
|
+
this.requests.delete(oldest[0]);
|
|
47
|
+
this.sources.delete(oldest[0]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const row = { id: randomUUID(), ...input, path, client: client.slice(0, 80), createdAt: this.now(),
|
|
51
|
+
status: this.allowed().some(parent => withinDirectory(parent, path)) ? 'approved' : 'pending' };
|
|
52
|
+
this.requests.set(input.requestId, row);
|
|
53
|
+
this.sources.set(input.requestId, input.path);
|
|
54
|
+
return { ...row };
|
|
55
|
+
}
|
|
56
|
+
pending() { this.expire(); return [...this.requests.values()].filter(row => row.status === 'pending').map(row => ({ ...row })); }
|
|
57
|
+
async resolve(id, decision, grant) {
|
|
58
|
+
this.expire();
|
|
59
|
+
const row = [...this.requests.values()].find(row => row.id === id);
|
|
60
|
+
if (!row)
|
|
61
|
+
throw new ConnectionError('directory-request-not-found');
|
|
62
|
+
if (row.status !== 'pending')
|
|
63
|
+
return { status: row.status };
|
|
64
|
+
if (decision === 'approved') {
|
|
65
|
+
try {
|
|
66
|
+
if (await realpath(row.path) !== row.path || !(await stat(row.path)).isDirectory())
|
|
67
|
+
throw new Error();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
row.status = 'rejected';
|
|
71
|
+
throw new ConnectionError('directory-changed');
|
|
72
|
+
}
|
|
73
|
+
await grant(row.path);
|
|
74
|
+
}
|
|
75
|
+
row.status = decision;
|
|
76
|
+
return { status: row.status };
|
|
77
|
+
}
|
|
78
|
+
rejectPending() { for (const row of this.requests.values())
|
|
79
|
+
if (row.status === 'pending')
|
|
80
|
+
row.status = 'rejected'; }
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=directories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directories.js","sourceRoot":"","sources":["../../src/connection/directories.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { GitSnapshot, WorkspaceChanges } from './types.js';
|
|
2
|
+
export declare function gitWorktreeRoot(cwd: string): Promise<string | false>;
|
|
3
|
+
export declare function gitSnapshot(cwd: string): Promise<GitSnapshot>;
|
|
4
|
+
export declare function workspaceChanges(cwd: string, baseline: GitSnapshot): Promise<WorkspaceChanges>;
|
|
5
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/connection/git.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAkC/D,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,CAE1E;AACD,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAcnE;AACD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQpG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { constants } from 'node:fs';
|
|
5
|
+
import { lstat, open, readlink, realpath } from 'node:fs/promises';
|
|
6
|
+
import { resolve, relative, sep, isAbsolute } from 'node:path';
|
|
7
|
+
const exec = promisify(execFile);
|
|
8
|
+
async function git(cwd, args) {
|
|
9
|
+
const result = await exec('git', ['--no-optional-locks', '-C', cwd, ...args], {
|
|
10
|
+
timeout: 5000, maxBuffer: 1024 * 1024, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
11
|
+
});
|
|
12
|
+
return result.stdout;
|
|
13
|
+
}
|
|
14
|
+
/** Bound untracked observations and never follow symlinks into another workspace. */
|
|
15
|
+
async function untrackedFingerprint(cwd, root) {
|
|
16
|
+
const paths = (await git(cwd, ['ls-files', '--others', '--exclude-standard', '-z', '--', '.'])).split('\0').filter(Boolean);
|
|
17
|
+
if (paths.length > 160)
|
|
18
|
+
throw new Error('Untracked observation limit');
|
|
19
|
+
const hash = createHash('sha256');
|
|
20
|
+
let bytes = 0;
|
|
21
|
+
for (const path of paths) {
|
|
22
|
+
const absolute = resolve(cwd, path), fromRoot = relative(root, absolute);
|
|
23
|
+
if (fromRoot === '..' || fromRoot.startsWith(`..${sep}`) || isAbsolute(fromRoot))
|
|
24
|
+
throw new Error('Outside worktree');
|
|
25
|
+
const info = await lstat(absolute);
|
|
26
|
+
hash.update(path);
|
|
27
|
+
if (info.isSymbolicLink()) {
|
|
28
|
+
hash.update(await readlink(absolute));
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
bytes += info.size;
|
|
32
|
+
if (!info.isFile() || bytes > 1024 * 1024)
|
|
33
|
+
throw new Error('Untracked observation limit');
|
|
34
|
+
const file = await open(absolute, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
35
|
+
try {
|
|
36
|
+
const opened = await file.stat();
|
|
37
|
+
if (opened.ino !== info.ino || opened.dev !== info.dev || opened.size !== info.size)
|
|
38
|
+
throw new Error('File changed during observation');
|
|
39
|
+
const buffer = Buffer.alloc(info.size + 1);
|
|
40
|
+
const read = await file.read(buffer, 0, buffer.length, 0);
|
|
41
|
+
if (read.bytesRead !== info.size)
|
|
42
|
+
throw new Error('File changed during observation');
|
|
43
|
+
hash.update(buffer.subarray(0, read.bytesRead));
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
await file.close();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return hash.digest('hex');
|
|
50
|
+
}
|
|
51
|
+
export async function gitWorktreeRoot(cwd) {
|
|
52
|
+
try {
|
|
53
|
+
return (await git(cwd, ['rev-parse', '--show-toplevel'])).trim();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function gitSnapshot(cwd) {
|
|
60
|
+
try {
|
|
61
|
+
cwd = await realpath(cwd);
|
|
62
|
+
const root = (await git(cwd, ['rev-parse', '--show-toplevel'])).trim();
|
|
63
|
+
const head = await git(cwd, ['rev-parse', '--verify', 'HEAD']).catch(() => 'unborn');
|
|
64
|
+
const status = await git(cwd, ['status', '--porcelain=v1', '-z', '--untracked-files=all', '--', '.']);
|
|
65
|
+
const args = ['--no-ext-diff', '--no-textconv'];
|
|
66
|
+
const diff = head === 'unborn'
|
|
67
|
+
? await git(cwd, ['diff', ...args, '--', '.']) + await git(cwd, ['diff', ...args, '--cached', '--', '.'])
|
|
68
|
+
: await git(cwd, ['diff', ...args, 'HEAD', '--', '.']);
|
|
69
|
+
const untracked = await untrackedFingerprint(cwd, root);
|
|
70
|
+
return { available: true, root, head, fingerprint: createHash('sha256').update(head).update(status).update(diff).update(untracked).digest('hex'),
|
|
71
|
+
dirty: status.split('\0').filter(Boolean).slice(0, 160).map(row => row.slice(0, 1024)) };
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return { available: false, root: '', head: '', fingerprint: '', dirty: [] };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function workspaceChanges(cwd, baseline) {
|
|
78
|
+
const current = await gitSnapshot(cwd);
|
|
79
|
+
const args = ['diff', '--no-ext-diff', '--no-textconv', '--stat', ...(current.head === 'unborn' ? [] : ['HEAD']), '--', '.'];
|
|
80
|
+
const stat = current.available ? await git(cwd, args).catch(() => '') : '';
|
|
81
|
+
const available = baseline.available && current.available;
|
|
82
|
+
return { available, baselineDirty: baseline.dirty, currentDirty: current.dirty,
|
|
83
|
+
changedSinceStart: available && baseline.fingerprint !== current.fingerprint, headChanged: available && baseline.head !== current.head,
|
|
84
|
+
diffStat: stat.slice(0, 8000), truncated: !available || stat.length > 8000 || current.dirty.length >= 160, attribution: 'workspace-observation' };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/connection/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { DelegatedTasks } from './tasks.js';
|
|
3
|
+
import type { DirectoryApplication, DirectoryRequest } from './directories.js';
|
|
4
|
+
type RequestDirectory = (input: DirectoryApplication, client: string) => Promise<DirectoryRequest>;
|
|
5
|
+
type ClientName = () => string;
|
|
6
|
+
type ConnectionStatus = () => {
|
|
7
|
+
connections: number;
|
|
8
|
+
maxConnections: number;
|
|
9
|
+
ids: readonly string[];
|
|
10
|
+
};
|
|
11
|
+
export declare function delegationMcpServer(tasks: DelegatedTasks, signal: (id: string | number) => AbortSignal, connectionId?: string, requestDirectory?: (input: DirectoryApplication) => Promise<DirectoryRequest>, clientName?: ClientName, connectionStatus?: ConnectionStatus): McpServer;
|
|
12
|
+
export interface ConnectedClient {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
connectedAt: number;
|
|
17
|
+
lastSeen: number;
|
|
18
|
+
}
|
|
19
|
+
/** MCP sessions, rather than TCP sockets or individual HTTP requests, define a connection. */
|
|
20
|
+
export declare class ConnectionHttp {
|
|
21
|
+
private readonly tasks;
|
|
22
|
+
private readonly requestDirectory;
|
|
23
|
+
private server;
|
|
24
|
+
private requests;
|
|
25
|
+
private readonly clients;
|
|
26
|
+
private readonly pending;
|
|
27
|
+
private timer;
|
|
28
|
+
constructor(tasks: DelegatedTasks, requestDirectory?: RequestDirectory | undefined);
|
|
29
|
+
connections(): ConnectedClient[];
|
|
30
|
+
disconnect(id: string): Promise<void>;
|
|
31
|
+
private prune;
|
|
32
|
+
start(port: number, token: string, maxConnections?: number): Promise<void>;
|
|
33
|
+
private admit;
|
|
34
|
+
private handle;
|
|
35
|
+
close(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/connection/http.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAM9E,KAAK,gBAAgB,GAAG,CAAC,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;AAClG,KAAK,UAAU,GAAG,MAAM,MAAM,CAAA;AAC9B,KAAK,gBAAgB,GAAG,MAAM;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AACrG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,KAAK,WAAW,EAAE,YAAY,SAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,gBAAgB,CAAC,EAAE,UAAU,GAAE,UAAwB,EAAE,gBAAgB,GAAE,gBAA4H,GAAG,SAAS,CAqC1Y;AAQD,MAAM,WAAW,eAAe;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE;AAKrH,8FAA8F;AAC9F,qBAAa,cAAc;IAMb,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAkB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IALrF,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,KAAK,CAAgD;gBAChC,KAAK,EAAE,cAAc,EAAmB,gBAAgB,GAAE,gBAAgB,GAAG,SAAqB;IAC/H,WAAW,IAAI,eAAe,EAAE;IAG1B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAO7B,KAAK;IAIb,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAY7D,KAAK;YAoBL,MAAM;IAoDd,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAS7B"}
|