diff --git a/AGENTS.md b/AGENTS.md index 04f2d15..09ea735 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ Use sources in this order when changing behavior or architecture: The repository keeps durable current-state documentation, not completed design proposals, task plans, progress ledgers, dated audits, or implementation diaries. Fresh command output, CI artifacts, commits, issues, and release notes are the evidence for a particular task, commit, or build. If current-state prose disagrees with code, schemas, or tests, investigate the implementation and update the owning durable document instead of recording the discrepancy as status. -The V1 scope is intentionally narrow. Do not add public galleries, sharing/community features, Petdex import, Codex built-in pet asset export, Windows UI, cloud accounts, or a full agent mission-control platform unless the user explicitly changes scope. +The V1 scope is intentionally narrow. Do not add public galleries, sharing/community features, Petdex import, Codex built-in pet asset export, Windows UI, cloud accounts, or a full agent mission-control platform unless the user explicitly changes scope. DeepSeek Harness (dsh) was explicitly authorized and included in scope by the user on 2026-08-18. ## Architecture And Data @@ -34,6 +34,7 @@ plugins/codex/ plugins/claude-code/ plugins/pi/ plugins/opencode/ +plugins/dsh/ skills/agent-pet-studio/ skills/agent-pet-maker/ schemas/ diff --git a/README.md b/README.md index cca9303..d272e11 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Agent Pet Companion is a native macOS desktop pet for people who work with one o - **Switch windows less often** — see Agent activity on your desktop without repeatedly opening a terminal or Agent app. - **Notice tasks that need you** — get a clear visual response when an Agent needs input, finishes, or fails. -- **Follow several Agents together** — bring activity from Codex, Claude Code, Pi Coding Agent, and OpenCode into one place. +- **Follow several Agents together** — bring activity from Codex, Claude Code, Pi Coding Agent, OpenCode, and DeepSeek Harness into one place. - **Get back to work quickly** — when routing is available, open the relevant session, Agent app, or terminal from the bubble. - **Make the pet yours** — use one of three bundled pets, import a `.petpack`, or create and edit your own pet with AI Pet Maker. - **Keep data centered on your Mac** — pets, settings, limited session summaries, and diagnostics remain local. The App does not read Agent credentials, tokens, cookies, or API keys. diff --git a/README.zh-CN.md b/README.zh-CN.md index 2423582..342e282 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -20,7 +20,7 @@ Agent Pet Companion 是一款 macOS 原生桌宠 App,适合同时使用一个 - **少一些来回切换**:在桌面上直接看到 Agent 的工作状态,不必反复打开终端或 Agent App。 - **不错过需要处理的任务**:等待输入、执行完成或失败时,桌宠会给出清晰反馈。 -- **同时关注多个 Agent**:统一查看 Codex、Claude Code、Pi Coding Agent 和 OpenCode 的任务动态。 +- **同时关注多个 Agent**:统一查看 Codex、Claude Code、Pi Coding Agent、OpenCode 与 DeepSeek Harness 的任务动态。 - **快速回到工作现场**:路由可用时,从气泡打开对应会话、Agent App 或终端。 - **拥有自己的桌宠**:使用三个内置宠物,导入 `.petpack`,或通过 AI 宠物制作创建和修改专属宠物。 - **数据以本机为中心**:宠物、设置、有限的会话摘要和诊断信息保存在 Mac 上;App 不读取 Agent 的凭据、Token、Cookie 或 API Key。 diff --git a/apps/macos/Sources/AgentPetCompanion/App/AgentIconProvider.swift b/apps/macos/Sources/AgentPetCompanion/App/AgentIconProvider.swift index 622ce68..9fb0b04 100644 --- a/apps/macos/Sources/AgentPetCompanion/App/AgentIconProvider.swift +++ b/apps/macos/Sources/AgentPetCompanion/App/AgentIconProvider.swift @@ -58,6 +58,11 @@ enum AgentIconCandidates { .resource("/Applications/OpenCode.app/Contents/Resources/icon.icns"), .resource("/Applications/opencode.app/Contents/Resources/icon.icns") ] + executableCandidates(named: "opencode") + case .dsh: + candidates = discoveredAppPaths.map(AgentIconCandidate.appBundle) + [ + .appBundle("/Applications/DeepSeek.app"), + .appBundle("/Applications/DeepSeek Harness.app") + ] + executableCandidates(named: "dsh") } var seen = Set() return candidates.filter { seen.insert("\($0.kind):\($0.path)").inserted } @@ -101,6 +106,8 @@ enum AgentIconProvider { identifiers = [] case .opencode: identifiers = ["ai.opencode.desktop", "com.opencode.desktop"] + case .dsh: + identifiers = [] } return identifiers.compactMap { NSWorkspace.shared.urlForApplication(withBundleIdentifier: $0)?.path } } @@ -157,6 +164,7 @@ struct AgentIconView: View { case .claudeCode: "Cl" case .pi: "π" case .opencode: "O" + case .dsh: "DS" case .none: "A" } } @@ -167,6 +175,7 @@ struct AgentIconView: View { case .claudeCode: Color(red: 0.78, green: 0.39, blue: 0.25) case .pi: Color(red: 0.04, green: 0.04, blue: 0.05) case .opencode: Color(red: 0.12, green: 0.12, blue: 0.14) + case .dsh: Color(red: 0.30, green: 0.42, blue: 1.00) case .none: Color.secondary } } diff --git a/apps/macos/Sources/AgentPetCompanion/App/AppStore.swift b/apps/macos/Sources/AgentPetCompanion/App/AppStore.swift index e517ff4..6d57be1 100644 --- a/apps/macos/Sources/AgentPetCompanion/App/AppStore.swift +++ b/apps/macos/Sources/AgentPetCompanion/App/AppStore.swift @@ -188,7 +188,8 @@ enum AgentSessionDeepLink { // Claude Desktop's `claude://resume` imports a CLI transcript as a new // Desktop session rather than locating the existing one, so there is no // truthful exact-session link to build for Claude Code. - case .claudeCode, .pi, .opencode: + // dsh V1 has no App surface and no session deep link, like Pi. + case .claudeCode, .pi, .opencode, .dsh: return nil } } diff --git a/apps/macos/Sources/AgentPetCompanion/App/RuntimeReleaseManifest.swift b/apps/macos/Sources/AgentPetCompanion/App/RuntimeReleaseManifest.swift index 197a461..83798db 100644 --- a/apps/macos/Sources/AgentPetCompanion/App/RuntimeReleaseManifest.swift +++ b/apps/macos/Sources/AgentPetCompanion/App/RuntimeReleaseManifest.swift @@ -8,16 +8,18 @@ struct RuntimeConnectorContracts: Codable, Equatable, Sendable { let claudeCode: String let pi: String let opencode: String + let dsh: String enum CodingKeys: String, CodingKey, CaseIterable { case codex case claudeCode = "claude_code" case pi case opencode + case dsh } var allArePresent: Bool { - [codex, claudeCode, pi, opencode].allSatisfy { + [codex, claudeCode, pi, opencode, dsh].allSatisfy { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } } @@ -204,7 +206,8 @@ struct RuntimeReleaseManifest: Codable, Equatable, Sendable { codex: "codex-hooks-2026-07-17-schema-v6", claudeCode: "claude-hooks-2026-07-17-activity-v5", pi: "pi-extension-0.80.10-activity-v7", - opencode: "opencode-v1.18.0-activity-v8" + opencode: "opencode-v1.18.0-activity-v8", + dsh: "dsh-v0.1.0-rc.6-events-v1" ) private static let publishedV1ReleaseIdentities = [ diff --git a/apps/macos/Sources/AgentPetCompanionCore/Contracts/AgentModels.swift b/apps/macos/Sources/AgentPetCompanionCore/Contracts/AgentModels.swift index c14ad5a..77c3837 100644 --- a/apps/macos/Sources/AgentPetCompanionCore/Contracts/AgentModels.swift +++ b/apps/macos/Sources/AgentPetCompanionCore/Contracts/AgentModels.swift @@ -5,6 +5,7 @@ public enum AgentSource: String, CaseIterable, Identifiable, Codable, Sendable { case claudeCode = "claude_code" case pi case opencode + case dsh public var id: String { rawValue } @@ -14,6 +15,7 @@ public enum AgentSource: String, CaseIterable, Identifiable, Codable, Sendable { case .claudeCode: "Claude Code" case .pi: "Pi Coding Agent" case .opencode: "OpenCode" + case .dsh: "DeepSeek Harness" } } @@ -23,6 +25,7 @@ public enum AgentSource: String, CaseIterable, Identifiable, Codable, Sendable { case .claudeCode: "Claude" case .pi: "Pi" case .opencode: "OpenCode" + case .dsh: "dsh" } } } diff --git a/apps/macos/Tests/AgentPetCompanionTests/InitialAppearanceBootstrapTests.swift b/apps/macos/Tests/AgentPetCompanionTests/InitialAppearanceBootstrapTests.swift index a91392b..47808aa 100644 --- a/apps/macos/Tests/AgentPetCompanionTests/InitialAppearanceBootstrapTests.swift +++ b/apps/macos/Tests/AgentPetCompanionTests/InitialAppearanceBootstrapTests.swift @@ -731,7 +731,8 @@ struct InitialAppearanceBootstrapTests { codex: "codex-hooks.v1", claudeCode: "claude-hooks.v1", pi: "pi-extension.v1", - opencode: "opencode-plugin.v1" + opencode: "opencode-plugin.v1", + dsh: "dsh-plugin.v1" ) ) } diff --git a/apps/macos/Tests/AgentPetCompanionTests/PetCoreProcessManagerTests.swift b/apps/macos/Tests/AgentPetCompanionTests/PetCoreProcessManagerTests.swift index cd610d3..0c02541 100644 --- a/apps/macos/Tests/AgentPetCompanionTests/PetCoreProcessManagerTests.swift +++ b/apps/macos/Tests/AgentPetCompanionTests/PetCoreProcessManagerTests.swift @@ -2023,7 +2023,8 @@ struct PetCoreProcessManagerTests { codex: codexContract, claudeCode: "claude-hooks.v1", pi: "pi-extension.v1", - opencode: "opencode-plugin.v1" + opencode: "opencode-plugin.v1", + dsh: "dsh-plugin.v1" ) ) } @@ -2062,7 +2063,8 @@ struct PetCoreProcessManagerTests { codex: "codex-hooks-2026-07-17-schema-v6", claudeCode: "claude-hooks-2026-07-17-activity-v5", pi: "pi-extension-0.80.10-activity-v7", - opencode: "opencode-v1.18.0-activity-v8" + opencode: "opencode-v1.18.0-activity-v8", + dsh: "dsh-v0.1.0-rc.6-events-v1" ) ) } diff --git a/apps/macos/Tests/AgentPetCompanionTests/ProductConvergenceTests.swift b/apps/macos/Tests/AgentPetCompanionTests/ProductConvergenceTests.swift index 1538874..2467476 100644 --- a/apps/macos/Tests/AgentPetCompanionTests/ProductConvergenceTests.swift +++ b/apps/macos/Tests/AgentPetCompanionTests/ProductConvergenceTests.swift @@ -794,7 +794,8 @@ struct ProductConvergenceTests { codex: "codex-hooks.v1", claudeCode: "claude-hooks.v1", pi: "pi-extension.v1", - opencode: "opencode-plugin.v1" + opencode: "opencode-plugin.v1", + dsh: "dsh-plugin.v1" ) ) } diff --git a/changes/unreleased/1-dsh-source-type.json b/changes/unreleased/1-dsh-source-type.json new file mode 100644 index 0000000..bff48bb --- /dev/null +++ b/changes/unreleased/1-dsh-source-type.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "connections", + "summary_en": "Extend the Agent source vocabulary to include DeepSeek Harness (dsh) with conservative no-op behavior while connector management lands.", + "summary_zh": "Agent 来源词汇扩展纳入 DeepSeek Harness(dsh),在连接器管理落地前保持保守无行为扩展。" +} diff --git a/changes/unreleased/2-dsh-parse.json b/changes/unreleased/2-dsh-parse.json new file mode 100644 index 0000000..22d28fa --- /dev/null +++ b/changes/unreleased/2-dsh-parse.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "connections", + "summary_en": "Add DeepSeek Harness (dsh) hook event normalization covering all seven semantic states, reasoning boundaries, and background fence.", + "summary_zh": "新增 DeepSeek Harness(dsh)Hook 事件归一化,覆盖全部七种语义状态、reasoning 边界与后台工作栅栏。" +} diff --git a/changes/unreleased/3-dsh-connections.json b/changes/unreleased/3-dsh-connections.json new file mode 100644 index 0000000..11d19d3 --- /dev/null +++ b/changes/unreleased/3-dsh-connections.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "connections", + "summary_en": "Add DeepSeek Harness (dsh) connector managed lifecycle: check, repair, refresh, and uninstall targeting the web profile cordis.patch.yml.", + "summary_zh": "新增 DeepSeek Harness(dsh)连接器受管生命周期:面向 web profile cordis.patch.yml 的 check、repair、refresh 与 uninstall 操作。" +} diff --git a/changes/unreleased/4-dsh-plugin-template.json b/changes/unreleased/4-dsh-plugin-template.json new file mode 100644 index 0000000..f9c5148 --- /dev/null +++ b/changes/unreleased/4-dsh-plugin-template.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "connections", + "summary_en": "Add DeepSeek Harness (dsh) Cordis plugin template implementing single-flight delivery, reasoning block-start thinking, child session suppression, and background fence.", + "summary_zh": "新增 DeepSeek Harness(dsh)Cordis 插件模板,实现单飞队列交付、reasoning block-start 思考边界、子会话抑制与后台工作栅栏。" +} diff --git a/changes/unreleased/5-dsh-app-surface.json b/changes/unreleased/5-dsh-app-surface.json new file mode 100644 index 0000000..ec9a278 --- /dev/null +++ b/changes/unreleased/5-dsh-app-surface.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "connections", + "summary_en": "Add DeepSeek Harness (dsh) to App-side runtime manifest and Agent Connections UI surfaces.", + "summary_zh": "在 App 端运行时清单与 Agent 连接设置页面中接入 DeepSeek Harness(dsh)。" +} diff --git a/changes/unreleased/6-dsh-e2e.json b/changes/unreleased/6-dsh-e2e.json new file mode 100644 index 0000000..501e65a --- /dev/null +++ b/changes/unreleased/6-dsh-e2e.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "connections", + "summary_en": "Add end-to-end integration tests for DeepSeek Harness (dsh) verifying contract fixtures, bounds, and privacy enforcement.", + "summary_zh": "新增 DeepSeek Harness(dsh)端到端集成测试,验证契约测试用例、字段有界性与隐私约束。" +} diff --git a/changes/unreleased/7-dsh-docs.json b/changes/unreleased/7-dsh-docs.json new file mode 100644 index 0000000..5cadbc1 --- /dev/null +++ b/changes/unreleased/7-dsh-docs.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "documentation", + "summary_en": "Incorporate DeepSeek Harness (dsh) connector contract, event mapping, privacy boundaries, and managed patch architecture into durable documentation.", + "summary_zh": "将 DeepSeek Harness(dsh)连接器契约、事件映射、隐私边界与受管 patch 架构并入正式技术文档。" +} diff --git a/changes/unreleased/8-dsh-scope.json b/changes/unreleased/8-dsh-scope.json new file mode 100644 index 0000000..0c3bd0e --- /dev/null +++ b/changes/unreleased/8-dsh-scope.json @@ -0,0 +1,7 @@ +{ + "schema_version": "apc.changelog-fragment.v1", + "kind": "Added", + "scope": "documentation", + "summary_en": "Expand repository product scope from four to five supported Agents, incorporating DeepSeek Harness across AGENTS.md, README, and architecture documentation.", + "summary_zh": "扩展产品范围支持五款 Agent,在 AGENTS.md、中英文 README 与架构文档中同步纳入 DeepSeek Harness。" +} diff --git a/crates/petcore-cli/src/main.rs b/crates/petcore-cli/src/main.rs index d5716a1..7fb40f4 100644 --- a/crates/petcore-cli/src/main.rs +++ b/crates/petcore-cli/src/main.rs @@ -1804,9 +1804,11 @@ fn runtime_agent_app_surface( { Some("opencode_app") } - AgentSource::Codex | AgentSource::ClaudeCode | AgentSource::Pi | AgentSource::Opencode => { - None - } + AgentSource::Codex + | AgentSource::ClaudeCode + | AgentSource::Pi + | AgentSource::Opencode + | AgentSource::Dsh => None, } } diff --git a/crates/petcore-types/src/agent.rs b/crates/petcore-types/src/agent.rs index 719fc2b..2fe2a34 100644 --- a/crates/petcore-types/src/agent.rs +++ b/crates/petcore-types/src/agent.rs @@ -8,6 +8,7 @@ pub enum AgentSource { ClaudeCode, Pi, Opencode, + Dsh, } impl AgentSource { @@ -17,6 +18,7 @@ impl AgentSource { Self::ClaudeCode => "Claude Code", Self::Pi => "Pi Coding Agent", Self::Opencode => "OpenCode", + Self::Dsh => "DeepSeek Harness", } } } diff --git a/crates/petcore/src/adapter_contracts.rs b/crates/petcore/src/adapter_contracts.rs index 7e0cc9e..57a2b4a 100644 --- a/crates/petcore/src/adapter_contracts.rs +++ b/crates/petcore/src/adapter_contracts.rs @@ -16,6 +16,7 @@ pub const CODEX_HOOKS_CONTRACT_VERSION: &str = "codex-hooks-2026-08-01-events-v9 pub const CLAUDE_HOOKS_CONTRACT_VERSION: &str = "claude-hooks-2026-08-01-events-v9"; pub const PI_EXTENSION_CONTRACT_VERSION: &str = "pi-extension-0.80.10-events-v15"; pub const OPENCODE_CONTRACT_VERSION: &str = "opencode-v1.18.4-events-v16"; +pub const DSH_PLUGIN_CONTRACT_VERSION: &str = "dsh-v0.1.0-rc.6-events-v1"; const MAX_MESSAGE_BYTES: usize = 4_096; const MAX_IDENTITY_BYTES: usize = 256; @@ -89,6 +90,7 @@ pub fn parse_contract_event(source: AgentSource, input: &Value) -> Result