@yancyyu/openhermit 1.6.28 → 1.6.30

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.
Files changed (177) hide show
  1. package/dist-renderer/assets/ProjectEditorOverlay-DsQt4FHy.js +52 -0
  2. package/dist-renderer/assets/{TeamGraphOverlay-Ba5njic5.js → TeamGraphOverlay-BjZC53xf.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-BvnK-OC1.js → _basePickBy-CrWocIjq.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-DmFYXx9G.js → _baseUniq-B6d8ysWi.js} +1 -1
  5. package/dist-renderer/assets/{arc-DX4ZQFY4.js → arc-DAIYCFP8.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DfYr3vEN.js → architectureDiagram-VXUJARFQ-B3UudXJh.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-DuXdVeWn.js → blockDiagram-VD42YOAC-DbptKQ4W.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-Bw2nixXe.js → c4Diagram-YG6GDRKO-C4WQuZpV.js} +1 -1
  9. package/dist-renderer/assets/channel-DbjZvWii.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-DLiNGQoE.js → chunk-4BX2VUAB-Dp7fVpI_.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-B1L_8VIF.js → chunk-55IACEB6-B8KGfbAy.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-DaZMWKGk.js → chunk-B4BG7PRW-BG1oJrjA.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-ku-dflJG.js → chunk-DI55MBZ5-DRmxNjht.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-DV-mF1dP.js → chunk-FMBD7UC4-D6VLvy16.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-ByGcDFQ0.js → chunk-QN33PNHL-DZou1667.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-7dv-Min8.js → chunk-QZHKN3VN-CghmasSh.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-WdXL5fTu.js → chunk-TZMSLE5B-B7apcMPK.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-D_FGxxsl.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-D_FGxxsl.js +1 -0
  20. package/dist-renderer/assets/clone-CJ1kxO2J.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-CNcsvqPl.js → cose-bilkent-S5V4N54A-05e5uQDp.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-DBNx4qqx.js → dagre-6UL2VRFP-B06bRykF.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-BfVlT6sT.js → diagram-PSM6KHXK-CY7VYQ7c.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-HvVjs0K6.js → diagram-QEK2KX5R-BjKEH7dD.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-DYb_KnWS.js → diagram-S2PKOQOG-Bf4ELS1_.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-Ba-IgI5G.js → erDiagram-Q2GNP2WA-DJ753_L9.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-2iDN8Kpj.js → flowDiagram-NV44I4VS-B71S-lC-.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-Byjf8Fa3.js → ganttDiagram-JELNMOA3-C_U42mSZ.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-DbKvfZ_j.js → gitGraphDiagram-V2S2FVAM-DKUJU4Ns.js} +1 -1
  30. package/dist-renderer/assets/{graph-Enirf-f8.js → graph-DY3qbzqj.js} +1 -1
  31. package/dist-renderer/assets/{index-DY1zqsb6.js → index-BlOrAXp3.js} +551 -537
  32. package/dist-renderer/assets/{index-AjxP_rE_.js → index-Bs27J5gB.js} +1 -1
  33. package/dist-renderer/assets/{index-CtlzGepK.js → index-C8B_nKOF.js} +1 -1
  34. package/dist-renderer/assets/index-CmZPUEhS.css +1 -0
  35. package/dist-renderer/assets/{index-COZPUWJW.js → index-DLKyDr4T.js} +1 -1
  36. package/dist-renderer/assets/{index-DdhqolqE.js → index-Dhsk3_DD.js} +1 -1
  37. package/dist-renderer/assets/{index-ChR1D6ZF.js → index-GpUvV2xs.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D6uicwz1.js → infoDiagram-HS3SLOUP-BNs0y3IG.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-DqwZsXlQ.js → journeyDiagram-XKPGCS4Q-CqPnw4UV.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-fCDVhVUm.js → kanban-definition-3W4ZIXB7-SLlzcUJ2.js} +1 -1
  41. package/dist-renderer/assets/{layout-CPFgj98r.js → layout-BZLlNmbr.js} +1 -1
  42. package/dist-renderer/assets/{linear-CYiQ7Y3M.js → linear-qz6v45xy.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-D31dS2KE.js → mindmap-definition-VGOIOE7T-B1-kmEWV.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-BOsCJfds.js → pieDiagram-ADFJNKIX-B8a02iNx.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-CYTVQCfr.js → quadrantDiagram-AYHSOK5B-BKv1Xfou.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-CODCFpkt.js → requirementDiagram-UZGBJVZJ-B3DUpZi2.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-Z4ce9ZtZ.js → sankeyDiagram-TZEHDZUN-DmPzuTsy.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-CmS9TxhW.js → sequenceDiagram-WL72ISMW-Bo7RelRb.js} +1 -1
  49. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-o9k-ns3q.js → stateDiagram-FKZM4ZOC-1epX98gV.js} +1 -1
  50. package/dist-renderer/assets/{stateDiagram-v2-4FDKWEC3-CxHMyEt1.js → stateDiagram-v2-4FDKWEC3-03Ym9PTr.js} +1 -1
  51. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-B6T3zrde.js → timeline-definition-IT6M3QCI-r6isC62H.js} +1 -1
  52. package/dist-renderer/assets/{treemap-GDKQZRPO-CVd5GNDw.js → treemap-GDKQZRPO-CGKpOUF2.js} +1 -1
  53. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-CleBrdqc.js → xychartDiagram-PRI3JC2R-t4-rwdAw.js} +1 -1
  54. package/dist-renderer/index.html +2 -2
  55. package/package.json +4 -1
  56. package/src/main/ipc/extensions.ts +353 -0
  57. package/src/main/server.ts +907 -184
  58. package/src/main/services/extensions/ExtensionFacadeService.ts +135 -0
  59. package/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts +190 -0
  60. package/src/main/services/extensions/catalog/McpCatalogAggregator.ts +150 -0
  61. package/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts +381 -0
  62. package/src/main/services/extensions/catalog/PluginCatalogService.ts +392 -0
  63. package/src/main/services/extensions/credentials/CredentialService.ts +343 -0
  64. package/src/main/services/extensions/install/McpInstallService.ts +407 -0
  65. package/src/main/services/extensions/install/PluginInstallService.ts +198 -0
  66. package/src/main/services/extensions/runtime/ClaudeCodeAdapter.ts +199 -0
  67. package/src/main/services/extensions/runtime/CodexAdapter.ts +100 -0
  68. package/src/main/services/extensions/runtime/CursorAdapter.ts +154 -0
  69. package/src/main/services/extensions/runtime/ExtensionsRuntimeAdapter.ts +172 -0
  70. package/src/main/services/extensions/runtime/GeminiAdapter.ts +91 -0
  71. package/src/main/services/extensions/runtime/HarnessInstallAdapter.ts +49 -0
  72. package/src/main/services/extensions/runtime/McpConfigStateReader.ts +209 -0
  73. package/src/main/services/extensions/runtime/OpenCodeAdapter.ts +91 -0
  74. package/src/main/services/extensions/runtime/adapterRegistry.ts +54 -0
  75. package/src/main/services/extensions/runtime/mcpDiagnosticsParser.ts +214 -0
  76. package/src/main/services/extensions/runtime/mcpRuntimeJson.ts +45 -0
  77. package/src/main/services/extensions/skills/SkillImportService.ts +155 -0
  78. package/src/main/services/extensions/skills/SkillMetadataParser.ts +323 -0
  79. package/src/main/services/extensions/skills/SkillPlanService.ts +411 -0
  80. package/src/main/services/extensions/skills/SkillReviewService.ts +73 -0
  81. package/src/main/services/extensions/skills/SkillRootsResolver.ts +49 -0
  82. package/src/main/services/extensions/skills/SkillScaffoldService.ts +89 -0
  83. package/src/main/services/extensions/skills/SkillScanner.ts +117 -0
  84. package/src/main/services/extensions/skills/SkillValidator.ts +69 -0
  85. package/src/main/services/extensions/skills/SkillsCatalogService.ts +92 -0
  86. package/src/main/services/extensions/skills/SkillsMutationService.ts +146 -0
  87. package/src/main/services/extensions/skills/SkillsWatcherService.ts +134 -0
  88. package/src/main/services/extensions/state/McpInstallationStateService.ts +42 -0
  89. package/src/main/services/extensions/state/PluginInstallationStateService.ts +281 -0
  90. package/src/main/services/identity/AgentTeamsIdentityStore.ts +218 -0
  91. package/src/main/services/runtime/providerAwareCliEnv.ts +60 -0
  92. package/src/main/services/session-intelligence/UsageTelemetryService.ts +33 -18
  93. package/src/main/services/team/ClaudeBinaryResolver.ts +469 -0
  94. package/src/main/services/team/ClaudeDoctorProbe.ts +0 -0
  95. package/src/main/services/team/cliFlavor.ts +54 -0
  96. package/src/main/services/teams-mvp/CollaborationBoardService.ts +310 -0
  97. package/src/main/services/teams-mvp/TaskDispatchService.ts +883 -95
  98. package/src/main/services/teams-mvp/TeamProvisioningService.ts +58 -19
  99. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +25 -2
  100. package/src/main/services/teams-mvp/index.ts +3 -0
  101. package/src/main/utils/atomicWrite.ts +72 -0
  102. package/src/main/utils/childProcess.ts +554 -0
  103. package/src/main/utils/cliEnv.ts +54 -0
  104. package/src/main/utils/cliPathMerge.ts +97 -0
  105. package/src/main/utils/pathDecoder.ts +664 -0
  106. package/src/main/utils/pathValidation.ts +432 -0
  107. package/src/main/utils/shellEnv.ts +331 -0
  108. package/src/renderer/App.tsx +5 -0
  109. package/src/renderer/api/httpClient.ts +128 -0
  110. package/src/renderer/components/extensions/ExtensionStoreView.tsx +59 -34
  111. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
  112. package/src/renderer/components/extensions/common/ExtensionToast.tsx +141 -0
  113. package/src/renderer/components/extensions/common/HarnessSelector.tsx +71 -0
  114. package/src/renderer/components/extensions/env/EnvVarPanel.tsx +335 -0
  115. package/src/renderer/components/extensions/env/ProjectEnvPanel.tsx +239 -0
  116. package/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx +14 -223
  117. package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +11 -0
  118. package/src/renderer/components/extensions/mcp/McpServersPanel.tsx +51 -1
  119. package/src/renderer/components/extensions/skills/SkillsPanel.tsx +1 -126
  120. package/src/renderer/components/layout/PaneContent.tsx +2 -0
  121. package/src/renderer/components/layout/SortableTab.tsx +1 -0
  122. package/src/renderer/components/layout/TabBarActions.tsx +12 -12
  123. package/src/renderer/components/schedules/SchedulesView.tsx +54 -22
  124. package/src/renderer/components/settings/sections/AdvancedSection.tsx +1 -1
  125. package/src/renderer/components/settings/sections/HarnessSection.tsx +2 -6
  126. package/src/renderer/components/settings/sections/TaskBusSection.tsx +144 -84
  127. package/src/renderer/components/sidebar/SidebarSessions.tsx +23 -0
  128. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +1 -7
  129. package/src/renderer/components/tasks/TasksView.tsx +343 -0
  130. package/src/renderer/components/team/HarnessSelect.tsx +71 -0
  131. package/src/renderer/components/team/TeamDetailView.tsx +55 -98
  132. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +21 -12
  133. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +8 -13
  134. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +1 -1
  135. package/src/renderer/components/team/editor/EditorContextMenu.tsx +8 -23
  136. package/src/renderer/components/team/editor/EditorFileTree.tsx +0 -4
  137. package/src/renderer/components/team/editor/EditorSelectionMenu.tsx +1 -8
  138. package/src/renderer/components/team/editor/ProjectEditorOverlay.tsx +0 -10
  139. package/src/renderer/components/team/kanban/KanbanBoard.tsx +31 -65
  140. package/src/renderer/components/team/members/MemberDetailDialog.tsx +8 -33
  141. package/src/renderer/components/team/messages/MessageComposer.tsx +39 -3
  142. package/src/renderer/components/team/messages/MessagesPanel.tsx +100 -26
  143. package/src/renderer/components/team/messages/StatusBlock.tsx +2 -24
  144. package/src/renderer/components/team/schedule/ScheduleEmptyState.tsx +1 -1
  145. package/src/renderer/components/terminal/TerminalPanel.tsx +156 -0
  146. package/src/renderer/components/ui/MentionableTextarea.tsx +0 -1
  147. package/src/renderer/hooks/useExtensionsTabState.ts +2 -2
  148. package/src/renderer/store/slices/extensionsSlice.ts +42 -107
  149. package/src/renderer/store/slices/scheduleSlice.ts +21 -0
  150. package/src/renderer/store/slices/teamSlice.ts +67 -25
  151. package/src/renderer/types/tabs.ts +1 -0
  152. package/src/shared/types/api.ts +58 -0
  153. package/src/shared/types/extensions/index.ts +1 -0
  154. package/src/shared/types/extensions/mcp.ts +2 -0
  155. package/src/shared/types/extensions/plugin.ts +2 -1
  156. package/src/shared/types/extensions/skill.ts +7 -0
  157. package/src/shared/types/team.ts +104 -1
  158. package/src/shared/utils/providerExtensionCapabilities.ts +1 -1
  159. package/dist-renderer/assets/ProjectEditorOverlay-A4DZTvSy.js +0 -57
  160. package/dist-renderer/assets/channel-Pre42N5O.js +0 -1
  161. package/dist-renderer/assets/classDiagram-2ON5EDUG-CdJsTJsj.js +0 -1
  162. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CdJsTJsj.js +0 -1
  163. package/dist-renderer/assets/clone-BjQBiNfj.js +0 -1
  164. package/dist-renderer/assets/index-BIOJremZ.css +0 -1
  165. package/src/features/recent-projects/main/adapters/input/http/registerRecentProjectsHttp.ts +0 -30
  166. package/src/features/recent-projects/main/adapters/output/presenters/DashboardRecentProjectsPresenter.ts +0 -27
  167. package/src/features/recent-projects/main/adapters/output/sources/ClaudeRecentProjectsSourceAdapter.ts +0 -91
  168. package/src/features/recent-projects/main/adapters/output/sources/CodexRecentProjectsSourceAdapter.ts +0 -326
  169. package/src/features/recent-projects/main/composition/createRecentProjectsFeature.ts +0 -43
  170. package/src/features/recent-projects/main/index.ts +0 -3
  171. package/src/features/recent-projects/main/infrastructure/cache/InMemoryRecentProjectsCache.ts +0 -34
  172. package/src/features/recent-projects/main/infrastructure/codex/CodexAppServerClient.ts +0 -116
  173. package/src/features/recent-projects/main/infrastructure/identity/RecentProjectIdentityResolver.ts +0 -20
  174. package/src/features/recent-projects/main/infrastructure/identity/normalizeIdentityPath.ts +0 -10
  175. package/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx +0 -143
  176. package/src/renderer/components/extensions/apikeys/ApiKeyFormDialog.tsx +0 -282
  177. package/src/renderer/components/extensions/apikeys/ApiKeysPanel.tsx +0 -280
@@ -44,7 +44,8 @@ import {
44
44
  X,
45
45
  } from 'lucide-react';
46
46
 
47
- import { ALL_AGENT_TYPES, AGENT_TYPE_LABELS } from '../HarnessCards';
47
+ import { AGENT_TYPE_LABELS } from '../HarnessCards';
48
+ import { HarnessSelect } from '../HarnessSelect';
48
49
  import { ProjectPathSelector } from './ProjectPathSelector';
49
50
  import { OptionalSettingsSection } from './OptionalSettingsSection';
50
51
  import { AutoResizeTextarea } from '@renderer/components/ui/auto-resize-textarea';
@@ -52,7 +53,13 @@ import { platformMeta, isQRPlatform } from './platformMeta';
52
53
  import PlatformSetupQR from './PlatformSetupQR';
53
54
  import PlatformManualForm from './PlatformManualForm';
54
55
 
55
- import type { Project, TeamCreateRequest } from '@shared/types';
56
+ import type {
57
+ EffortLevel,
58
+ Project,
59
+ TeamCreateRequest,
60
+ TeamFastMode,
61
+ TeamProviderId,
62
+ } from '@shared/types';
56
63
  import type { CcAgentType } from '@shared/types/ccConnect';
57
64
  import type { GlobalProvider } from '@shared/types/providers';
58
65
 
@@ -69,6 +76,14 @@ export interface TeamCopyData {
69
76
  teamName: string;
70
77
  description?: string;
71
78
  color?: string;
79
+ providerId?: TeamProviderId;
80
+ model?: string;
81
+ effort?: EffortLevel;
82
+ fastMode?: TeamFastMode;
83
+ limitContext?: boolean;
84
+ skipPermissions?: boolean;
85
+ templateSourceId?: string;
86
+ templateDirectoryId?: string;
72
87
  }
73
88
 
74
89
  // ---------------------------------------------------------------------------
@@ -549,18 +564,12 @@ export const CreateTeamDialog = ({
549
564
 
550
565
  <div className="space-y-1.5">
551
566
  <Label htmlFor="team-harness">Agent 类型</Label>
552
- <select
567
+ <HarnessSelect
553
568
  id="team-harness"
554
- className="flex w-full rounded-md border border-[var(--color-border)] bg-transparent px-3 py-2 text-sm"
555
569
  value={selectedHarness}
556
- onChange={(e) => setSelectedHarness(e.target.value as CcAgentType)}
557
- >
558
- {ALL_AGENT_TYPES.map((t) => (
559
- <option key={t} value={t}>
560
- {AGENT_TYPE_LABELS[t]}
561
- </option>
562
- ))}
563
- </select>
570
+ onChange={setSelectedHarness}
571
+ className="w-full"
572
+ />
564
573
  </div>
565
574
 
566
575
  <ProjectPathSelector
@@ -1,7 +1,8 @@
1
1
  import { useEffect, useState } from 'react';
2
2
 
3
3
  import { api } from '@renderer/api';
4
- import { ALL_AGENT_TYPES, AGENT_TYPE_LABELS } from '@renderer/components/team/HarnessCards';
4
+ import { AGENT_TYPE_LABELS } from '@renderer/components/team/HarnessCards';
5
+ import { HarnessSelect } from '@renderer/components/team/HarnessSelect';
5
6
  import { Button } from '@renderer/components/ui/button';
6
7
  import { Checkbox } from '@renderer/components/ui/checkbox';
7
8
  import {
@@ -259,20 +260,14 @@ export const EditTeamDialog = ({
259
260
  <label className="mb-1 block text-xs font-medium text-[var(--color-text-secondary)]">
260
261
  Agent 类型
261
262
  </label>
262
- <select
263
- value={agentType}
264
- onChange={(event) => {
263
+ <HarnessSelect
264
+ value={agentType as CcAgentType}
265
+ onChange={(v) => {
265
266
  clearError();
266
- setAgentType(event.target.value);
267
+ setAgentType(v);
267
268
  }}
268
- className="w-full rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-1.5 text-sm text-[var(--color-text)] outline-none focus:border-[var(--color-border-emphasis)]"
269
- >
270
- {ALL_AGENT_TYPES.map((type) => (
271
- <option key={type} value={type}>
272
- {AGENT_TYPE_LABELS[type]}
273
- </option>
274
- ))}
275
- </select>
269
+ className="w-full"
270
+ />
276
271
  </div>
277
272
 
278
273
  <div>
@@ -2058,7 +2058,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2058
2058
  ) : effectiveTeamName ? (
2059
2059
  `为团队“${effectiveTeamName}”创建自动运行计划`
2060
2060
  ) : (
2061
- '创建团队任务自动执行计划'
2061
+ '创建团队自动运行计划'
2062
2062
  );
2063
2063
 
2064
2064
  const submitLabel = isLaunchMode
@@ -16,7 +16,6 @@ import {
16
16
  FilePlus,
17
17
  FolderOpen,
18
18
  FolderPlus,
19
- ListTodo,
20
19
  MessageSquare,
21
20
  Pencil,
22
21
  Trash2,
@@ -39,8 +38,6 @@ interface EditorContextMenuProps {
39
38
  onNewFolder: (parentDir: string) => void;
40
39
  onDelete: (path: string) => void;
41
40
  onRename: (path: string) => void;
42
- /** Trigger "Create Task" with a file mention (files only, not directories) */
43
- onCreateTask?: (filePath: string) => void;
44
41
  /** Trigger "Write Teammate" with a file mention (files only, not directories) */
45
42
  onSendMessage?: (filePath: string) => void;
46
43
  }
@@ -56,7 +53,6 @@ export const EditorContextMenu = ({
56
53
  onNewFolder,
57
54
  onDelete,
58
55
  onRename,
59
- onCreateTask,
60
56
  onSendMessage,
61
57
  }: EditorContextMenuProps): React.ReactElement => {
62
58
  const [target, setTarget] = useState<TargetEntry | null>(null);
@@ -183,27 +179,16 @@ export const EditorContextMenu = ({
183
179
  )}
184
180
 
185
181
  {/* Team actions — file only */}
186
- {target && !target.isDir && (onCreateTask || onSendMessage) && (
182
+ {target && !target.isDir && onSendMessage && (
187
183
  <>
188
184
  <ContextMenu.Separator className="my-1 h-px bg-border" />
189
- {onSendMessage && (
190
- <ContextMenu.Item
191
- className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs text-text outline-none hover:bg-surface-raised focus:bg-surface-raised"
192
- onSelect={() => onSendMessage(target.path)}
193
- >
194
- <MessageSquare className="size-3.5 text-text-muted" />
195
- Write Teammate
196
- </ContextMenu.Item>
197
- )}
198
- {onCreateTask && (
199
- <ContextMenu.Item
200
- className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs text-text outline-none hover:bg-surface-raised focus:bg-surface-raised"
201
- onSelect={() => onCreateTask(target.path)}
202
- >
203
- <ListTodo className="size-3.5 text-text-muted" />
204
- Create Task
205
- </ContextMenu.Item>
206
- )}
185
+ <ContextMenu.Item
186
+ className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs text-text outline-none hover:bg-surface-raised focus:bg-surface-raised"
187
+ onSelect={() => onSendMessage(target.path)}
188
+ >
189
+ <MessageSquare className="size-3.5 text-text-muted" />
190
+ Write Teammate
191
+ </ContextMenu.Item>
207
192
  </>
208
193
  )}
209
194
  </ContextMenu.Content>
@@ -54,8 +54,6 @@ import type { FileTreeEntry, GitFileStatusType } from '@shared/types/editor';
54
54
  interface EditorFileTreeProps {
55
55
  selectedFilePath: string | null;
56
56
  onFileSelect: (filePath: string) => void;
57
- /** Trigger "Create Task" with a file mention from context menu */
58
- onCreateTask?: (filePath: string) => void;
59
57
  /** Trigger "Write Teammate" with a file mention from context menu */
60
58
  onSendMessage?: (filePath: string) => void;
61
59
  }
@@ -91,7 +89,6 @@ let fileTreeRenderCount = 0;
91
89
  export const EditorFileTree = ({
92
90
  selectedFilePath,
93
91
  onFileSelect,
94
- onCreateTask,
95
92
  onSendMessage,
96
93
  }: EditorFileTreeProps): React.ReactElement => {
97
94
  fileTreeRenderCount++;
@@ -452,7 +449,6 @@ export const EditorFileTree = ({
452
449
  onNewFolder={handleNewFolder}
453
450
  onDelete={handleDelete}
454
451
  onRename={handleRename}
455
- onCreateTask={onCreateTask}
456
452
  onSendMessage={onSendMessage}
457
453
  >
458
454
  <DndContext
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { Button } from '@renderer/components/ui/button';
9
9
  import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
10
- import { ListTodo, MessageSquare } from 'lucide-react';
10
+ import { MessageSquare } from 'lucide-react';
11
11
 
12
12
  import type { EditorSelectionInfo } from '@shared/types/editor';
13
13
 
@@ -20,7 +20,6 @@ interface EditorSelectionMenuProps {
20
20
  /** Bounding rect of the editor content container (for viewport → container conversion) */
21
21
  containerRect: DOMRect;
22
22
  onSendMessage: () => void;
23
- onCreateTask: () => void;
24
23
  }
25
24
 
26
25
  // =============================================================================
@@ -39,7 +38,6 @@ export const EditorSelectionMenu = ({
39
38
  info,
40
39
  containerRect,
41
40
  onSendMessage,
42
- onCreateTask,
43
41
  }: EditorSelectionMenuProps): React.ReactElement | null => {
44
42
  if (!info.text.trim()) return null;
45
43
 
@@ -71,11 +69,6 @@ export const EditorSelectionMenu = ({
71
69
  label="Write Teammate"
72
70
  onClick={onSendMessage}
73
71
  />
74
- <MenuButton
75
- icon={<ListTodo className="size-3.5" />}
76
- label="Create Task"
77
- onClick={onCreateTask}
78
- />
79
72
  </div>
80
73
  );
81
74
  };
@@ -628,12 +628,6 @@ export const ProjectEditorOverlay = ({
628
628
  <EditorFileTree
629
629
  selectedFilePath={activeTabId}
630
630
  onFileSelect={handleFileSelect}
631
- onCreateTask={
632
- onEditorAction
633
- ? (filePath: string) =>
634
- onEditorAction(buildFileAction('createTask', filePath, projectPath))
635
- : undefined
636
- }
637
631
  onSendMessage={
638
632
  onEditorAction
639
633
  ? (filePath: string) =>
@@ -829,10 +823,6 @@ export const ProjectEditorOverlay = ({
829
823
  onEditorAction(buildSelectionAction('sendMessage', selectionInfo));
830
824
  setSelectionInfo(null);
831
825
  }}
832
- onCreateTask={() => {
833
- onEditorAction(buildSelectionAction('createTask', selectionInfo));
834
- setSelectionInfo(null);
835
- }}
836
826
  />
837
827
  )}
838
828
  </div>
@@ -274,7 +274,11 @@ export const KanbanBoard = ({
274
274
  }: KanbanBoardProps): React.JSX.Element => {
275
275
  const boardRef = useRef<HTMLDivElement>(null);
276
276
  const scrollRestoreTimeoutsRef = useRef<number[]>([]);
277
- const [viewMode, setViewMode] = useState<KanbanViewMode>('grid');
277
+ const [viewMode, setViewMode] = useState<KanbanViewMode>('columns');
278
+
279
+ useEffect(() => {
280
+ setViewMode('columns');
281
+ }, []);
278
282
  const enableTaskSorting =
279
283
  viewMode === 'columns' && !!onColumnOrderChange && sort.field === 'manual';
280
284
 
@@ -357,49 +361,26 @@ export const KanbanBoard = ({
357
361
  columnTasks: TeamTask[],
358
362
  compact?: boolean
359
363
  ): React.JSX.Element => {
360
- const addHandler =
361
- onAddTask && columnId === 'todo'
362
- ? () => onAddTask(false)
363
- : onAddTask && columnId === 'in_progress'
364
- ? () => onAddTask(true)
365
- : undefined;
366
-
367
- const addButton = addHandler ? (
368
- <button
369
- type="button"
370
- onClick={addHandler}
371
- className="flex w-full items-center justify-center gap-1.5 rounded-md border border-dashed border-[var(--color-border)] p-3 text-xs text-[var(--color-text-muted)] transition-colors hover:border-[var(--color-border-emphasis)] hover:text-[var(--color-text-secondary)]"
372
- >
373
- <Plus size={13} />
374
- Add task
375
- </button>
376
- ) : null;
377
-
378
364
  if (columnTasks.length === 0) {
379
365
  return (
380
- addButton ?? (
381
- <div className="rounded-md border border-dashed border-[var(--color-border)] p-3 text-xs text-[var(--color-text-muted)]">
382
- No tasks
383
- </div>
384
- )
366
+ <div className="rounded-md border border-dashed border-[var(--color-border)] p-3 text-xs text-[var(--color-text-muted)]">
367
+ No tasks
368
+ </div>
385
369
  );
386
370
  }
387
371
  if (enableTaskSorting) {
388
372
  const itemIds = columnTasks.map((t) => t.id);
389
373
  return (
390
- <>
391
- <SortableContext items={itemIds} strategy={verticalListSortingStrategy}>
392
- {columnTasks.map((task) => (
393
- <SortableKanbanTaskCard
394
- key={task.id}
395
- task={task}
396
- columnId={columnId}
397
- memberColorMap={memberColorMap}
398
- />
399
- ))}
400
- </SortableContext>
401
- {addButton}
402
- </>
374
+ <SortableContext items={itemIds} strategy={verticalListSortingStrategy}>
375
+ {columnTasks.map((task) => (
376
+ <SortableKanbanTaskCard
377
+ key={task.id}
378
+ task={task}
379
+ columnId={columnId}
380
+ memberColorMap={memberColorMap}
381
+ />
382
+ ))}
383
+ </SortableContext>
403
384
  );
404
385
  }
405
386
  return (
@@ -428,7 +409,6 @@ export const KanbanBoard = ({
428
409
  onDeleteTask={onDeleteTask}
429
410
  />
430
411
  ))}
431
- {addButton}
432
412
  </>
433
413
  );
434
414
  };
@@ -610,36 +590,22 @@ export const KanbanBoard = ({
610
590
  </div>
611
591
  ) : (
612
592
  <div className="w-full min-w-0 max-w-full overflow-x-auto overflow-y-hidden px-1 pb-6 pr-4 pt-2">
613
- <div className="flex min-w-max items-start pr-1">
614
- {visibleColumns.map((column, index) => {
593
+ <div className="flex w-full items-start gap-3">
594
+ {visibleColumns.map((column) => {
615
595
  const columnTasks = groupedOrdered.get(column.id) ?? [];
616
596
  const accent = COLUMN_ACCENTS[column.id as 'todo' | 'in_progress' | 'done'];
617
- const width = columnWidths.get(column.id) ?? 256;
618
- const handleProps = getHandleProps(column.id);
619
597
  return (
620
- <div key={column.id} className="flex shrink-0">
621
- <div style={{ width }}>
622
- <KanbanColumn
623
- title={column.title}
624
- count={columnTasks.length}
625
- icon={accent.icon}
626
- headerBg={accent.headerBg}
627
- bodyBg={accent.bodyBg}
628
- bodyClassName="max-h-none overflow-visible"
629
- >
630
- {renderCards(column.id, columnTasks, true)}
631
- </KanbanColumn>
632
- </div>
633
- {index < visibleColumns.length - 1 ? (
634
- <div
635
- className="group relative mx-0.5 flex items-center justify-center"
636
- onPointerDown={handleProps.onPointerDown}
637
- style={handleProps.style}
638
- aria-label={handleProps['aria-label']}
639
- >
640
- <div className="h-full w-px bg-[var(--color-border)] transition-colors group-hover:bg-blue-500/50 group-active:bg-blue-500" />
641
- </div>
642
- ) : null}
598
+ <div key={column.id} className="min-w-0 flex-1">
599
+ <KanbanColumn
600
+ title={column.title}
601
+ count={columnTasks.length}
602
+ icon={accent.icon}
603
+ headerBg={accent.headerBg}
604
+ bodyBg={accent.bodyBg}
605
+ bodyClassName="max-h-none overflow-visible"
606
+ >
607
+ {renderCards(column.id, columnTasks, true)}
608
+ </KanbanColumn>
643
609
  </div>
644
610
  );
645
611
  })}
@@ -26,7 +26,6 @@ import { type MemberActivityFilter, type MemberDetailTab } from './memberDetailT
26
26
  import { MemberLaunchDiagnosticsButton } from './MemberLaunchDiagnosticsButton';
27
27
  import { MemberMessagesTab } from './MemberMessagesTab';
28
28
  import { MemberStatsTab } from './MemberStatsTab';
29
- import { MemberTasksTab } from './MemberTasksTab';
30
29
  import { MemberWorkspaceTab } from './MemberWorkspaceTab';
31
30
 
32
31
  import type { TeamLaunchParams } from '@renderer/store/slices/teamSlice';
@@ -56,8 +55,10 @@ interface MemberDetailDialogProps {
56
55
  launchParams?: TeamLaunchParams;
57
56
  onClose: () => void;
58
57
  onSendMessage: () => void;
59
- onAssignTask: () => void;
60
- onTaskClick: (task: TeamTaskWithKanban) => void;
58
+ /** Deprecated: team tasks UI has been removed, kept for compatibility with older callers/tests. */
59
+ onAssignTask?: () => void;
60
+ /** Deprecated: team tasks UI has been removed, kept for compatibility with older callers/tests. */
61
+ onTaskClick?: (task: TeamTaskWithKanban) => void;
61
62
  onRemoveMember?: () => void;
62
63
  onRestartMember?: (memberName: string) => Promise<void> | void;
63
64
  onUpdateRole?: (memberName: string, role: string | undefined) => Promise<void> | void;
@@ -83,18 +84,12 @@ export const MemberDetailDialog = ({
83
84
  launchParams,
84
85
  onClose,
85
86
  onSendMessage,
86
- onAssignTask,
87
- onTaskClick,
88
87
  onRemoveMember,
89
88
  onRestartMember,
90
89
  onUpdateRole,
91
90
  updatingRole,
92
91
  onViewMemberChanges,
93
92
  }: MemberDetailDialogProps): React.JSX.Element | null => {
94
- const memberTasks = useMemo(
95
- () => (member ? tasks.filter((t) => t.owner === member.name) : []),
96
- [tasks, member]
97
- );
98
93
  const memberMessages = useStore((state) =>
99
94
  selectMemberMessagesForTeamMember(state, teamName, member?.name ?? null)
100
95
  );
@@ -111,17 +106,9 @@ export const MemberDetailDialog = ({
111
106
  }).length;
112
107
  }, [member, memberMessages, members, tasks, teamName]);
113
108
 
114
- const inProgressTasks = useMemo(
115
- () => memberTasks.filter((t) => t.status === 'in_progress').length,
116
- [memberTasks]
117
- );
118
-
119
- const completedTasks = useMemo(
120
- () => memberTasks.filter((t) => t.status === 'completed').length,
121
- [memberTasks]
109
+ const [activeTab, setActiveTab] = useState<MemberDetailTab>(
110
+ initialTab === 'tasks' ? 'workspace' : initialTab
122
111
  );
123
-
124
- const [activeTab, setActiveTab] = useState<MemberDetailTab>(initialTab);
125
112
  const [restarting, setRestarting] = useState(false);
126
113
  const [restartError, setRestartError] = useState<string | null>(null);
127
114
 
@@ -202,8 +189,8 @@ export const MemberDetailDialog = ({
202
189
  </DialogHeader>
203
190
 
204
191
  <MemberDetailStats
205
- totalTasks={memberTasks.length}
206
- inProgressTasks={inProgressTasks}
192
+ totalTasks={0}
193
+ inProgressTasks={0}
207
194
  totalTokens={totalTokens}
208
195
  statsLoading={statsLoading}
209
196
  statsComputedAt={memberStats?.computedAt}
@@ -217,14 +204,6 @@ export const MemberDetailDialog = ({
217
204
  className="min-w-0 overflow-hidden"
218
205
  >
219
206
  <TabsList className="w-full">
220
- <TabsTrigger value="tasks" className="flex-1 gap-1.5">
221
- Tasks
222
- {memberTasks.length > 0 && (
223
- <span className="rounded-full bg-[var(--color-surface)] px-1.5 text-[10px]">
224
- {memberTasks.length}
225
- </span>
226
- )}
227
- </TabsTrigger>
228
207
  <TabsTrigger value="workspace" className="flex-1 gap-1.5">
229
208
  <FolderOpen size={12} />
230
209
  Workspace
@@ -242,9 +221,6 @@ export const MemberDetailDialog = ({
242
221
  Stats
243
222
  </TabsTrigger>
244
223
  </TabsList>
245
- <TabsContent value="tasks">
246
- <MemberTasksTab tasks={memberTasks} onTaskClick={onTaskClick} />
247
- </TabsContent>
248
224
  <TabsContent value="workspace">
249
225
  <MemberWorkspaceTab
250
226
  teamName={teamName}
@@ -260,7 +236,6 @@ export const MemberDetailDialog = ({
260
236
  members={members}
261
237
  tasks={tasks}
262
238
  initialFilter={initialActivityFilter}
263
- onTaskClick={onTaskClick}
264
239
  />
265
240
  </TabsContent>
266
241
  <TabsContent value="stats">
@@ -69,6 +69,11 @@ interface MessageComposerProps {
69
69
  actionMode?: AgentActionMode,
70
70
  taskRefs?: TaskRef[]
71
71
  ) => void;
72
+ onDispatchTask?: (
73
+ toTeam: string,
74
+ subject: string,
75
+ description: string
76
+ ) => Promise<boolean | void> | boolean | void;
72
77
  }
73
78
 
74
79
  export const MessageComposer = ({
@@ -86,6 +91,7 @@ export const MessageComposer = ({
86
91
  onSessionChange,
87
92
  textareaRef: externalTextareaRef,
88
93
  onSend,
94
+ onDispatchTask,
89
95
  }: MessageComposerProps): React.JSX.Element => {
90
96
  const internalTextareaRef = useRef<HTMLTextAreaElement>(null);
91
97
  const textareaRef = useMemo(() => {
@@ -223,7 +229,26 @@ export const MessageComposer = ({
223
229
  ? '斜杠命令需要团队负责人在线'
224
230
  : null
225
231
  : null;
226
- const canSend =
232
+ const teamDispatch = useMemo(() => {
233
+ const match = trimmed.match(/^@([^\s]+)\s+([\s\S]+)$/);
234
+ if (!match || !onDispatchTask) return null;
235
+ const mentioned = match[1];
236
+ const subject = match[2]?.trim();
237
+ if (!mentioned || !subject) return null;
238
+ const targetTeam = teamMentionSuggestions.find((team) => {
239
+ const slug = team.id.startsWith('team:') ? team.id.slice('team:'.length) : team.id;
240
+ return slug === mentioned || team.name === mentioned;
241
+ });
242
+ const slug = targetTeam
243
+ ? targetTeam.id.startsWith('team:')
244
+ ? targetTeam.id.slice('team:'.length)
245
+ : targetTeam.id
246
+ : mentioned;
247
+ return { slug, subject };
248
+ }, [onDispatchTask, teamMentionSuggestions, trimmed]);
249
+ const canDispatchToTeam =
250
+ teamDispatch !== null && trimmed.length > 0 && trimmed.length <= MAX_TEXT_LENGTH && !sending;
251
+ const canSendRegularMessage =
227
252
  recipient.length > 0 &&
228
253
  trimmed.length > 0 &&
229
254
  trimmed.length <= MAX_TEXT_LENGTH &&
@@ -231,6 +256,7 @@ export const MessageComposer = ({
231
256
  !isProvisioning &&
232
257
  !attachmentsBlocked &&
233
258
  !slashCommandRestrictionReason;
259
+ const canSend = canDispatchToTeam || canSendRegularMessage;
234
260
 
235
261
  // Track whether we initiated a send — clear draft only on confirmed success
236
262
  const pendingSendRef = useRef(false);
@@ -238,9 +264,19 @@ export const MessageComposer = ({
238
264
  const handleSend = useCallback(() => {
239
265
  if (!canSend) return;
240
266
  dismissMentionsRef.current?.();
241
- pendingSendRef.current = true;
242
267
  const taskRefs = extractTaskRefsFromText(draft.text, taskSuggestions);
243
268
  const serialized = serializeChipsWithText(trimmed, draft.chips);
269
+
270
+ if (teamDispatch && onDispatchTask) {
271
+ void Promise.resolve(
272
+ onDispatchTask(teamDispatch.slug, teamDispatch.subject, serialized)
273
+ ).then((dispatched) => {
274
+ if (dispatched !== false) draft.clearDraft();
275
+ });
276
+ return;
277
+ }
278
+
279
+ pendingSendRef.current = true;
244
280
  onSend(
245
281
  recipient,
246
282
  serialized,
@@ -249,7 +285,7 @@ export const MessageComposer = ({
249
285
  undefined,
250
286
  taskRefs
251
287
  );
252
- }, [canSend, recipient, trimmed, onSend, draft.attachments, draft.chips, taskSuggestions]);
288
+ }, [canSend, recipient, trimmed, onSend, draft, taskSuggestions, teamDispatch, onDispatchTask]);
253
289
 
254
290
  // Clear draft only after send completes successfully (sending: true → false, no error)
255
291
  useEffect(() => {