@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.
- package/dist-renderer/assets/ProjectEditorOverlay-DsQt4FHy.js +52 -0
- package/dist-renderer/assets/{TeamGraphOverlay-Ba5njic5.js → TeamGraphOverlay-BjZC53xf.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-BvnK-OC1.js → _basePickBy-CrWocIjq.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-DmFYXx9G.js → _baseUniq-B6d8ysWi.js} +1 -1
- package/dist-renderer/assets/{arc-DX4ZQFY4.js → arc-DAIYCFP8.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DfYr3vEN.js → architectureDiagram-VXUJARFQ-B3UudXJh.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-DuXdVeWn.js → blockDiagram-VD42YOAC-DbptKQ4W.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-Bw2nixXe.js → c4Diagram-YG6GDRKO-C4WQuZpV.js} +1 -1
- package/dist-renderer/assets/channel-DbjZvWii.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-DLiNGQoE.js → chunk-4BX2VUAB-Dp7fVpI_.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-B1L_8VIF.js → chunk-55IACEB6-B8KGfbAy.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-DaZMWKGk.js → chunk-B4BG7PRW-BG1oJrjA.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-ku-dflJG.js → chunk-DI55MBZ5-DRmxNjht.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-DV-mF1dP.js → chunk-FMBD7UC4-D6VLvy16.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-ByGcDFQ0.js → chunk-QN33PNHL-DZou1667.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-7dv-Min8.js → chunk-QZHKN3VN-CghmasSh.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-WdXL5fTu.js → chunk-TZMSLE5B-B7apcMPK.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-D_FGxxsl.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-D_FGxxsl.js +1 -0
- package/dist-renderer/assets/clone-CJ1kxO2J.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-CNcsvqPl.js → cose-bilkent-S5V4N54A-05e5uQDp.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-DBNx4qqx.js → dagre-6UL2VRFP-B06bRykF.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-BfVlT6sT.js → diagram-PSM6KHXK-CY7VYQ7c.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-HvVjs0K6.js → diagram-QEK2KX5R-BjKEH7dD.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-DYb_KnWS.js → diagram-S2PKOQOG-Bf4ELS1_.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-Ba-IgI5G.js → erDiagram-Q2GNP2WA-DJ753_L9.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-2iDN8Kpj.js → flowDiagram-NV44I4VS-B71S-lC-.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-Byjf8Fa3.js → ganttDiagram-JELNMOA3-C_U42mSZ.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-DbKvfZ_j.js → gitGraphDiagram-V2S2FVAM-DKUJU4Ns.js} +1 -1
- package/dist-renderer/assets/{graph-Enirf-f8.js → graph-DY3qbzqj.js} +1 -1
- package/dist-renderer/assets/{index-DY1zqsb6.js → index-BlOrAXp3.js} +551 -537
- package/dist-renderer/assets/{index-AjxP_rE_.js → index-Bs27J5gB.js} +1 -1
- package/dist-renderer/assets/{index-CtlzGepK.js → index-C8B_nKOF.js} +1 -1
- package/dist-renderer/assets/index-CmZPUEhS.css +1 -0
- package/dist-renderer/assets/{index-COZPUWJW.js → index-DLKyDr4T.js} +1 -1
- package/dist-renderer/assets/{index-DdhqolqE.js → index-Dhsk3_DD.js} +1 -1
- package/dist-renderer/assets/{index-ChR1D6ZF.js → index-GpUvV2xs.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D6uicwz1.js → infoDiagram-HS3SLOUP-BNs0y3IG.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-DqwZsXlQ.js → journeyDiagram-XKPGCS4Q-CqPnw4UV.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-fCDVhVUm.js → kanban-definition-3W4ZIXB7-SLlzcUJ2.js} +1 -1
- package/dist-renderer/assets/{layout-CPFgj98r.js → layout-BZLlNmbr.js} +1 -1
- package/dist-renderer/assets/{linear-CYiQ7Y3M.js → linear-qz6v45xy.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-D31dS2KE.js → mindmap-definition-VGOIOE7T-B1-kmEWV.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-BOsCJfds.js → pieDiagram-ADFJNKIX-B8a02iNx.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-CYTVQCfr.js → quadrantDiagram-AYHSOK5B-BKv1Xfou.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-CODCFpkt.js → requirementDiagram-UZGBJVZJ-B3DUpZi2.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-Z4ce9ZtZ.js → sankeyDiagram-TZEHDZUN-DmPzuTsy.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-CmS9TxhW.js → sequenceDiagram-WL72ISMW-Bo7RelRb.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-o9k-ns3q.js → stateDiagram-FKZM4ZOC-1epX98gV.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-v2-4FDKWEC3-CxHMyEt1.js → stateDiagram-v2-4FDKWEC3-03Ym9PTr.js} +1 -1
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-B6T3zrde.js → timeline-definition-IT6M3QCI-r6isC62H.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-CVd5GNDw.js → treemap-GDKQZRPO-CGKpOUF2.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-CleBrdqc.js → xychartDiagram-PRI3JC2R-t4-rwdAw.js} +1 -1
- package/dist-renderer/index.html +2 -2
- package/package.json +4 -1
- package/src/main/ipc/extensions.ts +353 -0
- package/src/main/server.ts +907 -184
- package/src/main/services/extensions/ExtensionFacadeService.ts +135 -0
- package/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts +190 -0
- package/src/main/services/extensions/catalog/McpCatalogAggregator.ts +150 -0
- package/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts +381 -0
- package/src/main/services/extensions/catalog/PluginCatalogService.ts +392 -0
- package/src/main/services/extensions/credentials/CredentialService.ts +343 -0
- package/src/main/services/extensions/install/McpInstallService.ts +407 -0
- package/src/main/services/extensions/install/PluginInstallService.ts +198 -0
- package/src/main/services/extensions/runtime/ClaudeCodeAdapter.ts +199 -0
- package/src/main/services/extensions/runtime/CodexAdapter.ts +100 -0
- package/src/main/services/extensions/runtime/CursorAdapter.ts +154 -0
- package/src/main/services/extensions/runtime/ExtensionsRuntimeAdapter.ts +172 -0
- package/src/main/services/extensions/runtime/GeminiAdapter.ts +91 -0
- package/src/main/services/extensions/runtime/HarnessInstallAdapter.ts +49 -0
- package/src/main/services/extensions/runtime/McpConfigStateReader.ts +209 -0
- package/src/main/services/extensions/runtime/OpenCodeAdapter.ts +91 -0
- package/src/main/services/extensions/runtime/adapterRegistry.ts +54 -0
- package/src/main/services/extensions/runtime/mcpDiagnosticsParser.ts +214 -0
- package/src/main/services/extensions/runtime/mcpRuntimeJson.ts +45 -0
- package/src/main/services/extensions/skills/SkillImportService.ts +155 -0
- package/src/main/services/extensions/skills/SkillMetadataParser.ts +323 -0
- package/src/main/services/extensions/skills/SkillPlanService.ts +411 -0
- package/src/main/services/extensions/skills/SkillReviewService.ts +73 -0
- package/src/main/services/extensions/skills/SkillRootsResolver.ts +49 -0
- package/src/main/services/extensions/skills/SkillScaffoldService.ts +89 -0
- package/src/main/services/extensions/skills/SkillScanner.ts +117 -0
- package/src/main/services/extensions/skills/SkillValidator.ts +69 -0
- package/src/main/services/extensions/skills/SkillsCatalogService.ts +92 -0
- package/src/main/services/extensions/skills/SkillsMutationService.ts +146 -0
- package/src/main/services/extensions/skills/SkillsWatcherService.ts +134 -0
- package/src/main/services/extensions/state/McpInstallationStateService.ts +42 -0
- package/src/main/services/extensions/state/PluginInstallationStateService.ts +281 -0
- package/src/main/services/identity/AgentTeamsIdentityStore.ts +218 -0
- package/src/main/services/runtime/providerAwareCliEnv.ts +60 -0
- package/src/main/services/session-intelligence/UsageTelemetryService.ts +33 -18
- package/src/main/services/team/ClaudeBinaryResolver.ts +469 -0
- package/src/main/services/team/ClaudeDoctorProbe.ts +0 -0
- package/src/main/services/team/cliFlavor.ts +54 -0
- package/src/main/services/teams-mvp/CollaborationBoardService.ts +310 -0
- package/src/main/services/teams-mvp/TaskDispatchService.ts +883 -95
- package/src/main/services/teams-mvp/TeamProvisioningService.ts +58 -19
- package/src/main/services/teams-mvp/TeamWorkspaceService.ts +25 -2
- package/src/main/services/teams-mvp/index.ts +3 -0
- package/src/main/utils/atomicWrite.ts +72 -0
- package/src/main/utils/childProcess.ts +554 -0
- package/src/main/utils/cliEnv.ts +54 -0
- package/src/main/utils/cliPathMerge.ts +97 -0
- package/src/main/utils/pathDecoder.ts +664 -0
- package/src/main/utils/pathValidation.ts +432 -0
- package/src/main/utils/shellEnv.ts +331 -0
- package/src/renderer/App.tsx +5 -0
- package/src/renderer/api/httpClient.ts +128 -0
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +59 -34
- package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
- package/src/renderer/components/extensions/common/ExtensionToast.tsx +141 -0
- package/src/renderer/components/extensions/common/HarnessSelector.tsx +71 -0
- package/src/renderer/components/extensions/env/EnvVarPanel.tsx +335 -0
- package/src/renderer/components/extensions/env/ProjectEnvPanel.tsx +239 -0
- package/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx +14 -223
- package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +11 -0
- package/src/renderer/components/extensions/mcp/McpServersPanel.tsx +51 -1
- package/src/renderer/components/extensions/skills/SkillsPanel.tsx +1 -126
- package/src/renderer/components/layout/PaneContent.tsx +2 -0
- package/src/renderer/components/layout/SortableTab.tsx +1 -0
- package/src/renderer/components/layout/TabBarActions.tsx +12 -12
- package/src/renderer/components/schedules/SchedulesView.tsx +54 -22
- package/src/renderer/components/settings/sections/AdvancedSection.tsx +1 -1
- package/src/renderer/components/settings/sections/HarnessSection.tsx +2 -6
- package/src/renderer/components/settings/sections/TaskBusSection.tsx +144 -84
- package/src/renderer/components/sidebar/SidebarSessions.tsx +23 -0
- package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +1 -7
- package/src/renderer/components/tasks/TasksView.tsx +343 -0
- package/src/renderer/components/team/HarnessSelect.tsx +71 -0
- package/src/renderer/components/team/TeamDetailView.tsx +55 -98
- package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +21 -12
- package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +8 -13
- package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +1 -1
- package/src/renderer/components/team/editor/EditorContextMenu.tsx +8 -23
- package/src/renderer/components/team/editor/EditorFileTree.tsx +0 -4
- package/src/renderer/components/team/editor/EditorSelectionMenu.tsx +1 -8
- package/src/renderer/components/team/editor/ProjectEditorOverlay.tsx +0 -10
- package/src/renderer/components/team/kanban/KanbanBoard.tsx +31 -65
- package/src/renderer/components/team/members/MemberDetailDialog.tsx +8 -33
- package/src/renderer/components/team/messages/MessageComposer.tsx +39 -3
- package/src/renderer/components/team/messages/MessagesPanel.tsx +100 -26
- package/src/renderer/components/team/messages/StatusBlock.tsx +2 -24
- package/src/renderer/components/team/schedule/ScheduleEmptyState.tsx +1 -1
- package/src/renderer/components/terminal/TerminalPanel.tsx +156 -0
- package/src/renderer/components/ui/MentionableTextarea.tsx +0 -1
- package/src/renderer/hooks/useExtensionsTabState.ts +2 -2
- package/src/renderer/store/slices/extensionsSlice.ts +42 -107
- package/src/renderer/store/slices/scheduleSlice.ts +21 -0
- package/src/renderer/store/slices/teamSlice.ts +67 -25
- package/src/renderer/types/tabs.ts +1 -0
- package/src/shared/types/api.ts +58 -0
- package/src/shared/types/extensions/index.ts +1 -0
- package/src/shared/types/extensions/mcp.ts +2 -0
- package/src/shared/types/extensions/plugin.ts +2 -1
- package/src/shared/types/extensions/skill.ts +7 -0
- package/src/shared/types/team.ts +104 -1
- package/src/shared/utils/providerExtensionCapabilities.ts +1 -1
- package/dist-renderer/assets/ProjectEditorOverlay-A4DZTvSy.js +0 -57
- package/dist-renderer/assets/channel-Pre42N5O.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-CdJsTJsj.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CdJsTJsj.js +0 -1
- package/dist-renderer/assets/clone-BjQBiNfj.js +0 -1
- package/dist-renderer/assets/index-BIOJremZ.css +0 -1
- package/src/features/recent-projects/main/adapters/input/http/registerRecentProjectsHttp.ts +0 -30
- package/src/features/recent-projects/main/adapters/output/presenters/DashboardRecentProjectsPresenter.ts +0 -27
- package/src/features/recent-projects/main/adapters/output/sources/ClaudeRecentProjectsSourceAdapter.ts +0 -91
- package/src/features/recent-projects/main/adapters/output/sources/CodexRecentProjectsSourceAdapter.ts +0 -326
- package/src/features/recent-projects/main/composition/createRecentProjectsFeature.ts +0 -43
- package/src/features/recent-projects/main/index.ts +0 -3
- package/src/features/recent-projects/main/infrastructure/cache/InMemoryRecentProjectsCache.ts +0 -34
- package/src/features/recent-projects/main/infrastructure/codex/CodexAppServerClient.ts +0 -116
- package/src/features/recent-projects/main/infrastructure/identity/RecentProjectIdentityResolver.ts +0 -20
- package/src/features/recent-projects/main/infrastructure/identity/normalizeIdentityPath.ts +0 -10
- package/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx +0 -143
- package/src/renderer/components/extensions/apikeys/ApiKeyFormDialog.tsx +0 -282
- package/src/renderer/components/extensions/apikeys/ApiKeysPanel.tsx +0 -280
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
Info,
|
|
24
24
|
Plus,
|
|
25
25
|
Search,
|
|
26
|
-
Trash2,
|
|
27
26
|
} from 'lucide-react';
|
|
28
27
|
import { useShallow } from 'zustand/react/shallow';
|
|
29
28
|
|
|
@@ -35,12 +34,7 @@ import { SkillImportDialog } from './SkillImportDialog';
|
|
|
35
34
|
import { resolveSkillProjectPath } from './skillProjectUtils';
|
|
36
35
|
|
|
37
36
|
import type { SkillsSortState } from '@renderer/hooks/useExtensionsTabState';
|
|
38
|
-
import type {
|
|
39
|
-
SkillCatalogItem,
|
|
40
|
-
SkillDetail,
|
|
41
|
-
SkillSource,
|
|
42
|
-
SkillValidationIssue,
|
|
43
|
-
} from '@shared/types/extensions';
|
|
37
|
+
import type { SkillCatalogItem, SkillDetail, SkillValidationIssue } from '@shared/types/extensions';
|
|
44
38
|
|
|
45
39
|
const SUCCESS_BANNER_MS = 2500;
|
|
46
40
|
const NEW_SKILL_HIGHLIGHT_MS = 4000;
|
|
@@ -141,10 +135,6 @@ export const SkillsPanel = ({
|
|
|
141
135
|
const [quickFilter, setQuickFilter] = useState<SkillsQuickFilter>('all');
|
|
142
136
|
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
|
143
137
|
const [highlightedSkillId, setHighlightedSkillId] = useState<string | null>(null);
|
|
144
|
-
const [skillSources, setSkillSources] = useState<SkillSource[]>([]);
|
|
145
|
-
const [newSkillSourceUrl, setNewSkillSourceUrl] = useState('');
|
|
146
|
-
const [skillSourceLoading, setSkillSourceLoading] = useState(false);
|
|
147
|
-
const [skillSourceError, setSkillSourceError] = useState<string | null>(null);
|
|
148
138
|
const selectedSkillIdRef = useRef<string | null>(selectedSkillId);
|
|
149
139
|
const selectedSkillItemRef = useRef<SkillCatalogItem | null>(null);
|
|
150
140
|
selectedSkillIdRef.current = selectedSkillId;
|
|
@@ -221,55 +211,6 @@ export const SkillsPanel = ({
|
|
|
221
211
|
};
|
|
222
212
|
}, [fetchSkillDetail, fetchSkillsCatalog, projectPath]);
|
|
223
213
|
|
|
224
|
-
useEffect(() => {
|
|
225
|
-
if (!api.skills) return;
|
|
226
|
-
void api.skills
|
|
227
|
-
.listSources()
|
|
228
|
-
.then((snapshot) => setSkillSources(snapshot.sources))
|
|
229
|
-
.catch(() => undefined);
|
|
230
|
-
}, []);
|
|
231
|
-
|
|
232
|
-
const saveAndRefreshSkillSources = async (sources: SkillSource[]): Promise<void> => {
|
|
233
|
-
if (!api.skills) return;
|
|
234
|
-
setSkillSourceLoading(true);
|
|
235
|
-
setSkillSourceError(null);
|
|
236
|
-
try {
|
|
237
|
-
const saved = await api.skills.saveSources(sources);
|
|
238
|
-
setSkillSources(saved.sources);
|
|
239
|
-
const refreshed = await api.skills.refreshSources();
|
|
240
|
-
setSkillSources(refreshed.sources);
|
|
241
|
-
await fetchSkillsCatalog(projectPath ?? undefined);
|
|
242
|
-
setSuccessMessage('Skills 源已同步到 ~/.hermit/skills');
|
|
243
|
-
} catch (error) {
|
|
244
|
-
setSkillSourceError(error instanceof Error ? error.message : '同步 Skills 源失败');
|
|
245
|
-
} finally {
|
|
246
|
-
setSkillSourceLoading(false);
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
const handleAddSkillSource = async (): Promise<void> => {
|
|
251
|
-
const url = newSkillSourceUrl.trim();
|
|
252
|
-
if (!url) return;
|
|
253
|
-
const id =
|
|
254
|
-
url
|
|
255
|
-
.replace(/\.git$/, '')
|
|
256
|
-
.split(/[/:]/)
|
|
257
|
-
.filter(Boolean)
|
|
258
|
-
.slice(-2)
|
|
259
|
-
.join('-')
|
|
260
|
-
.toLowerCase()
|
|
261
|
-
.replace(/[^a-z0-9._-]+/g, '-') || `source-${Date.now().toString(36)}`;
|
|
262
|
-
await saveAndRefreshSkillSources([
|
|
263
|
-
...skillSources,
|
|
264
|
-
{ id, name: id, url, enabled: true, branch: 'main' },
|
|
265
|
-
]);
|
|
266
|
-
setNewSkillSourceUrl('');
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
const handleRemoveSkillSource = async (sourceId: string): Promise<void> => {
|
|
270
|
-
await saveAndRefreshSkillSources(skillSources.filter((source) => source.id !== sourceId));
|
|
271
|
-
};
|
|
272
|
-
|
|
273
214
|
const visibleSkills = useMemo(() => {
|
|
274
215
|
const q = skillsSearchQuery.trim().toLowerCase();
|
|
275
216
|
const filteredByQuery = q
|
|
@@ -307,71 +248,6 @@ export const SkillsPanel = ({
|
|
|
307
248
|
|
|
308
249
|
return (
|
|
309
250
|
<div className="flex flex-col gap-4">
|
|
310
|
-
<div className="rounded-md border border-blue-500/30 bg-blue-500/5 px-4 py-3 text-sm text-blue-300">
|
|
311
|
-
全局技能由 `~/.hermit/skills` 管理,并在团队启动前投影到各 runtime 的全局 skills
|
|
312
|
-
目录。项目技能直接安装到你选择的项目 runtime 目录。
|
|
313
|
-
</div>
|
|
314
|
-
<div className="bg-surface-raised/20 rounded-xl border border-border p-4">
|
|
315
|
-
<div className="flex flex-col gap-3 lg:flex-row lg:items-end">
|
|
316
|
-
<div className="min-w-0 flex-1 space-y-1">
|
|
317
|
-
<h3 className="text-sm font-semibold text-text">全局 Skills 源</h3>
|
|
318
|
-
<p className="text-xs text-text-muted">
|
|
319
|
-
Git 源会同步到 `~/.hermit/skills`,随后由 Hermit 投影给 Claude、Cursor、Codex
|
|
320
|
-
等运行时。
|
|
321
|
-
</p>
|
|
322
|
-
<p className="text-xs text-text-muted">
|
|
323
|
-
打开面板只读取本地缓存;只有点击“添加并同步”或“刷新源”才会访问 GitHub 更新。
|
|
324
|
-
</p>
|
|
325
|
-
<input
|
|
326
|
-
value={newSkillSourceUrl}
|
|
327
|
-
onChange={(event) => setNewSkillSourceUrl(event.target.value)}
|
|
328
|
-
placeholder="https://github.com/yancyuu/HermitSkills"
|
|
329
|
-
className="mt-2 h-8 w-full rounded-md border border-border bg-surface px-2 text-xs text-text"
|
|
330
|
-
/>
|
|
331
|
-
</div>
|
|
332
|
-
<Button
|
|
333
|
-
variant="outline"
|
|
334
|
-
size="sm"
|
|
335
|
-
disabled={skillSourceLoading || !newSkillSourceUrl.trim()}
|
|
336
|
-
onClick={() => void handleAddSkillSource()}
|
|
337
|
-
>
|
|
338
|
-
{skillSourceLoading ? '同步中...' : '添加并同步'}
|
|
339
|
-
</Button>
|
|
340
|
-
<Button
|
|
341
|
-
variant="outline"
|
|
342
|
-
size="sm"
|
|
343
|
-
disabled={skillSourceLoading || skillSources.length === 0}
|
|
344
|
-
onClick={() => void saveAndRefreshSkillSources(skillSources)}
|
|
345
|
-
>
|
|
346
|
-
刷新源
|
|
347
|
-
</Button>
|
|
348
|
-
</div>
|
|
349
|
-
{skillSourceError ? <p className="mt-2 text-xs text-red-400">{skillSourceError}</p> : null}
|
|
350
|
-
{skillSources.length > 0 ? (
|
|
351
|
-
<div className="mt-3 flex flex-wrap gap-1.5">
|
|
352
|
-
{skillSources.map((source) => (
|
|
353
|
-
<span
|
|
354
|
-
key={source.id}
|
|
355
|
-
className="inline-flex max-w-full items-center gap-1 rounded bg-surface-raised px-1.5 py-0.5 text-[10px] text-text-muted"
|
|
356
|
-
title={source.url}
|
|
357
|
-
>
|
|
358
|
-
<span className="max-w-44 truncate">
|
|
359
|
-
{source.name}
|
|
360
|
-
{source.lastError ? ' · 同步失败' : ''}
|
|
361
|
-
</span>
|
|
362
|
-
<button
|
|
363
|
-
type="button"
|
|
364
|
-
className="-mr-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded hover:bg-red-500/10 hover:text-red-300"
|
|
365
|
-
onClick={() => void handleRemoveSkillSource(source.id)}
|
|
366
|
-
aria-label={`删除 Skills 源 ${source.name}`}
|
|
367
|
-
>
|
|
368
|
-
<Trash2 size={10} />
|
|
369
|
-
</button>
|
|
370
|
-
</span>
|
|
371
|
-
))}
|
|
372
|
-
</div>
|
|
373
|
-
) : null}
|
|
374
|
-
</div>
|
|
375
251
|
<div className="bg-surface-raised/20 rounded-xl border border-border p-4">
|
|
376
252
|
<div className="flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
|
|
377
253
|
<div className="min-w-0 flex-1 space-y-1 xl:max-w-2xl">
|
|
@@ -387,7 +263,6 @@ export const SkillsPanel = ({
|
|
|
387
263
|
</p>
|
|
388
264
|
<p className="max-w-2xl text-xs leading-5 text-text-muted">
|
|
389
265
|
需要到处生效的习惯请使用个人技能;只对当前代码库有意义的流程请使用项目技能。
|
|
390
|
-
全局技能从 Hermit 源统一投影;项目技能直接写入所选项目 runtime 目录。
|
|
391
266
|
</p>
|
|
392
267
|
</div>
|
|
393
268
|
|
|
@@ -12,6 +12,7 @@ import { NotificationsView } from '../notifications/NotificationsView';
|
|
|
12
12
|
import { SessionReportTab } from '../report/SessionReportTab';
|
|
13
13
|
import { SchedulesView } from '../schedules/SchedulesView';
|
|
14
14
|
import { SettingsView } from '../settings/SettingsView';
|
|
15
|
+
import { TasksView } from '../tasks/TasksView';
|
|
15
16
|
import { TeamDetailView } from '../team/TeamDetailView';
|
|
16
17
|
import { TeamListView } from '../team/TeamListView';
|
|
17
18
|
|
|
@@ -67,6 +68,7 @@ export const PaneContent = ({ pane, isPaneFocused }: PaneContentProps): React.JS
|
|
|
67
68
|
</TabUIProvider>
|
|
68
69
|
)}
|
|
69
70
|
{tab.type === 'schedules' && <SchedulesView />}
|
|
71
|
+
{tab.type === 'tasks' && <TasksView />}
|
|
70
72
|
{tab.type === 'graph' && (
|
|
71
73
|
<TabUIProvider tabId={tab.id}>
|
|
72
74
|
<TeamGraphTab
|
|
@@ -9,7 +9,7 @@ import { useMemo, useState } from 'react';
|
|
|
9
9
|
import { api } from '@renderer/api';
|
|
10
10
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
|
|
11
11
|
import { useStore } from '@renderer/store';
|
|
12
|
-
import {
|
|
12
|
+
import { ListTodo, PanelRight, Puzzle, Users } from 'lucide-react';
|
|
13
13
|
import { useShallow } from 'zustand/react/shallow';
|
|
14
14
|
|
|
15
15
|
import { MoreMenu } from './MoreMenu';
|
|
@@ -18,7 +18,7 @@ export const TabBarActions = (): React.JSX.Element => {
|
|
|
18
18
|
const {
|
|
19
19
|
unreadCount,
|
|
20
20
|
openExtensionsTab,
|
|
21
|
-
|
|
21
|
+
openTasksTab,
|
|
22
22
|
openTeamsTab,
|
|
23
23
|
activeTabId,
|
|
24
24
|
openTabs,
|
|
@@ -29,7 +29,7 @@ export const TabBarActions = (): React.JSX.Element => {
|
|
|
29
29
|
useShallow((s) => ({
|
|
30
30
|
unreadCount: s.unreadCount,
|
|
31
31
|
openExtensionsTab: s.openExtensionsTab,
|
|
32
|
-
|
|
32
|
+
openTasksTab: s.openTasksTab,
|
|
33
33
|
openTeamsTab: s.openTeamsTab,
|
|
34
34
|
activeTabId: s.activeTabId,
|
|
35
35
|
openTabs: s.openTabs,
|
|
@@ -42,7 +42,7 @@ export const TabBarActions = (): React.JSX.Element => {
|
|
|
42
42
|
// Hover states for buttons
|
|
43
43
|
const [teamsHover, setTeamsHover] = useState(false);
|
|
44
44
|
const [extensionsHover, setExtensionsHover] = useState(false);
|
|
45
|
-
const [
|
|
45
|
+
const [tasksHover, setTasksHover] = useState(false);
|
|
46
46
|
const [githubHover, setGithubHover] = useState(false);
|
|
47
47
|
const [expandHover, setExpandHover] = useState(false);
|
|
48
48
|
|
|
@@ -102,20 +102,20 @@ export const TabBarActions = (): React.JSX.Element => {
|
|
|
102
102
|
<Tooltip>
|
|
103
103
|
<TooltipTrigger asChild>
|
|
104
104
|
<button
|
|
105
|
-
onClick={
|
|
106
|
-
onMouseEnter={() =>
|
|
107
|
-
onMouseLeave={() =>
|
|
105
|
+
onClick={openTasksTab}
|
|
106
|
+
onMouseEnter={() => setTasksHover(true)}
|
|
107
|
+
onMouseLeave={() => setTasksHover(false)}
|
|
108
108
|
className="rounded-md p-2 transition-colors"
|
|
109
109
|
style={{
|
|
110
|
-
color:
|
|
111
|
-
backgroundColor:
|
|
110
|
+
color: tasksHover ? 'var(--color-text)' : 'var(--color-text-muted)',
|
|
111
|
+
backgroundColor: tasksHover ? 'var(--color-surface-raised)' : 'transparent',
|
|
112
112
|
}}
|
|
113
|
-
aria-label="
|
|
113
|
+
aria-label="任务"
|
|
114
114
|
>
|
|
115
|
-
<
|
|
115
|
+
<ListTodo className="size-4" />
|
|
116
116
|
</button>
|
|
117
117
|
</TooltipTrigger>
|
|
118
|
-
<TooltipContent side="bottom"
|
|
118
|
+
<TooltipContent side="bottom">任务</TooltipContent>
|
|
119
119
|
</Tooltip>
|
|
120
120
|
|
|
121
121
|
{/* GitHub link */}
|
|
@@ -74,9 +74,9 @@ const ScheduleListItem = ({
|
|
|
74
74
|
}, [expanded, runs.length, runsLoading, fetchRunHistory, schedule.id]);
|
|
75
75
|
|
|
76
76
|
return (
|
|
77
|
-
<div className="rounded-
|
|
77
|
+
<div className="rounded-xl border border-[var(--color-border-subtle)] bg-white/[0.025] font-sans shadow-[0_14px_32px_rgba(0,0,0,0.14)] transition-colors hover:border-[var(--color-border-emphasis)] hover:bg-white/[0.04]">
|
|
78
78
|
{/* Main row */}
|
|
79
|
-
<div className="flex items-center gap-3 px-4 py-3">
|
|
79
|
+
<div className="flex items-center gap-3 px-4 py-3.5">
|
|
80
80
|
{/* Expand toggle */}
|
|
81
81
|
<button
|
|
82
82
|
type="button"
|
|
@@ -106,7 +106,7 @@ const ScheduleListItem = ({
|
|
|
106
106
|
{/* Team badge */}
|
|
107
107
|
<button
|
|
108
108
|
type="button"
|
|
109
|
-
className="flex shrink-0 items-center gap-1.5 rounded-
|
|
109
|
+
className="flex shrink-0 items-center gap-1.5 rounded-full border border-white/10 bg-white/[0.04] px-2.5 py-1 text-xs text-[var(--color-text-secondary)] transition-colors hover:border-[var(--color-border-emphasis)] hover:text-[var(--color-text)]"
|
|
110
110
|
onClick={() => onTeamClick(schedule.teamName)}
|
|
111
111
|
>
|
|
112
112
|
<span className="size-2 shrink-0 rounded-full" style={{ backgroundColor: teamColor }} />
|
|
@@ -116,7 +116,7 @@ const ScheduleListItem = ({
|
|
|
116
116
|
{/* Next run */}
|
|
117
117
|
<Tooltip>
|
|
118
118
|
<TooltipTrigger asChild>
|
|
119
|
-
<span className="shrink-0 text-xs text-[var(--color-text-muted)]">
|
|
119
|
+
<span className="shrink-0 rounded-full bg-white/[0.035] px-2 py-1 text-xs text-[var(--color-text-muted)]">
|
|
120
120
|
下次:{formatNextRun(schedule.nextRunAt)}
|
|
121
121
|
</span>
|
|
122
122
|
</TooltipTrigger>
|
|
@@ -194,7 +194,7 @@ const ScheduleListItem = ({
|
|
|
194
194
|
|
|
195
195
|
{/* Expanded: Run history */}
|
|
196
196
|
{expanded ? (
|
|
197
|
-
<div className="border-t border-[
|
|
197
|
+
<div className="border-t border-white/[0.06] bg-black/10">
|
|
198
198
|
{runsLoading ? (
|
|
199
199
|
<div className="flex items-center justify-center py-4 text-xs text-[var(--color-text-muted)]">
|
|
200
200
|
正在加载运行历史...
|
|
@@ -328,6 +328,16 @@ export const SchedulesView = (): React.JSX.Element => {
|
|
|
328
328
|
});
|
|
329
329
|
}, [getTeamDisplayName, schedules, teamFilter, searchQuery]);
|
|
330
330
|
|
|
331
|
+
const scheduleStats = useMemo(
|
|
332
|
+
() => ({
|
|
333
|
+
total: schedules.length,
|
|
334
|
+
active: schedules.filter((schedule) => schedule.status === 'active').length,
|
|
335
|
+
paused: schedules.filter((schedule) => schedule.status === 'paused').length,
|
|
336
|
+
teams: new Set(schedules.map((schedule) => schedule.teamName)).size,
|
|
337
|
+
}),
|
|
338
|
+
[schedules]
|
|
339
|
+
);
|
|
340
|
+
|
|
331
341
|
const handleEdit = useCallback((schedule: Schedule) => {
|
|
332
342
|
setEditingSchedule(schedule);
|
|
333
343
|
setDialogOpen(true);
|
|
@@ -367,18 +377,38 @@ export const SchedulesView = (): React.JSX.Element => {
|
|
|
367
377
|
|
|
368
378
|
return (
|
|
369
379
|
<div className="h-full overflow-y-auto bg-[var(--color-surface)]">
|
|
370
|
-
<div className="mx-auto w-full max-w-
|
|
380
|
+
<div className="mx-auto w-full max-w-6xl px-6 py-8">
|
|
371
381
|
{/* Header */}
|
|
372
|
-
<div className="mb-4">
|
|
373
|
-
<div className="flex items-
|
|
374
|
-
<div
|
|
375
|
-
<
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
<span className="rounded-full bg-[var(--color-surface-raised)] px-2 py-0.5 text-xs text-[var(--color-text-muted)]">
|
|
379
|
-
{schedules.length}
|
|
382
|
+
<div className="mb-5 rounded-2xl border border-[var(--color-border-subtle)] bg-white/[0.025] p-4 shadow-[0_18px_42px_rgba(0,0,0,0.12)]">
|
|
383
|
+
<div className="flex flex-wrap items-start justify-between gap-4">
|
|
384
|
+
<div>
|
|
385
|
+
<div className="flex items-center gap-3">
|
|
386
|
+
<span className="flex size-9 items-center justify-center rounded-xl bg-blue-500/10 text-blue-400">
|
|
387
|
+
<Calendar className="size-4" />
|
|
380
388
|
</span>
|
|
381
|
-
|
|
389
|
+
<div>
|
|
390
|
+
<h1 className="text-lg font-semibold text-[var(--color-text)]">定时任务</h1>
|
|
391
|
+
<p className="mt-0.5 text-xs text-[var(--color-text-muted)]">
|
|
392
|
+
集中管理所有团队的 Cron 计划、运行状态和历史记录。
|
|
393
|
+
</p>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
{schedules.length > 0 ? (
|
|
397
|
+
<div className="mt-4 flex flex-wrap gap-2">
|
|
398
|
+
<span className="rounded-full border border-white/10 bg-white/[0.04] px-2.5 py-1 text-xs text-[var(--color-text-secondary)]">
|
|
399
|
+
全部 {scheduleStats.total}
|
|
400
|
+
</span>
|
|
401
|
+
<span className="rounded-full border border-emerald-400/15 bg-emerald-400/10 px-2.5 py-1 text-xs text-emerald-400">
|
|
402
|
+
运行中 {scheduleStats.active}
|
|
403
|
+
</span>
|
|
404
|
+
<span className="rounded-full border border-yellow-400/15 bg-yellow-400/10 px-2.5 py-1 text-xs text-yellow-400">
|
|
405
|
+
已暂停 {scheduleStats.paused}
|
|
406
|
+
</span>
|
|
407
|
+
<span className="rounded-full border border-white/10 bg-white/[0.04] px-2.5 py-1 text-xs text-[var(--color-text-secondary)]">
|
|
408
|
+
团队 {scheduleStats.teams}
|
|
409
|
+
</span>
|
|
410
|
+
</div>
|
|
411
|
+
) : null}
|
|
382
412
|
</div>
|
|
383
413
|
<Button size="sm" className="gap-1.5" onClick={handleCreate}>
|
|
384
414
|
<Plus className="size-3.5" />
|
|
@@ -388,9 +418,9 @@ export const SchedulesView = (): React.JSX.Element => {
|
|
|
388
418
|
|
|
389
419
|
{/* Filters row */}
|
|
390
420
|
{schedules.length > 0 && (
|
|
391
|
-
<div className="mt-
|
|
421
|
+
<div className="mt-4 flex flex-wrap items-center gap-3 rounded-xl border border-white/[0.06] bg-black/10 p-2">
|
|
392
422
|
{/* Search */}
|
|
393
|
-
<div className="relative
|
|
423
|
+
<div className="relative min-w-[220px] flex-1">
|
|
394
424
|
<Search className="absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-[var(--color-text-muted)]" />
|
|
395
425
|
<Input
|
|
396
426
|
placeholder="搜索计划..."
|
|
@@ -470,12 +500,14 @@ export const SchedulesView = (): React.JSX.Element => {
|
|
|
470
500
|
</div>
|
|
471
501
|
) : schedules.length === 0 ? (
|
|
472
502
|
/* Global empty state */
|
|
473
|
-
<div className="flex flex-col items-center justify-center gap-3 py-16 text-center">
|
|
474
|
-
<
|
|
503
|
+
<div className="flex flex-col items-center justify-center gap-3 rounded-2xl border border-dashed border-[var(--color-border)] bg-white/[0.02] py-16 text-center">
|
|
504
|
+
<div className="flex size-14 items-center justify-center rounded-2xl bg-blue-500/10 text-blue-400">
|
|
505
|
+
<Calendar className="size-7" />
|
|
506
|
+
</div>
|
|
475
507
|
<div className="space-y-1.5">
|
|
476
|
-
<p className="text-sm font-medium text-[var(--color-text-secondary)]"
|
|
508
|
+
<p className="text-sm font-medium text-[var(--color-text-secondary)]">暂无定时任务</p>
|
|
477
509
|
<p className="max-w-sm text-xs text-[var(--color-text-muted)]">
|
|
478
|
-
在任意团队中创建计划,即可使用 Cron
|
|
510
|
+
在任意团队中创建计划,即可使用 Cron 表达式自动运行团队。
|
|
479
511
|
所有团队的计划都会显示在这里。
|
|
480
512
|
</p>
|
|
481
513
|
</div>
|
|
@@ -486,7 +518,7 @@ export const SchedulesView = (): React.JSX.Element => {
|
|
|
486
518
|
</div>
|
|
487
519
|
) : filteredSchedules.length === 0 ? (
|
|
488
520
|
/* No results for current filters */
|
|
489
|
-
<div className="flex flex-col items-center justify-center gap-2 py-12 text-center">
|
|
521
|
+
<div className="flex flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-[var(--color-border)] bg-white/[0.02] py-12 text-center">
|
|
490
522
|
<Search className="size-8 text-[var(--color-text-muted)]" />
|
|
491
523
|
<p className="text-sm text-[var(--color-text-muted)]">没有符合当前筛选条件的计划</p>
|
|
492
524
|
<button
|
|
@@ -240,7 +240,7 @@ export const AdvancedSection = ({}: AdvancedSectionProps): React.JSX.Element =>
|
|
|
240
240
|
Version {version || '...'}
|
|
241
241
|
</p>
|
|
242
242
|
<p className="mt-2 text-xs leading-relaxed" style={{ color: 'var(--color-text-muted)' }}>
|
|
243
|
-
|
|
243
|
+
渠道与模型供应商由后端服务统一管理;团队内部任务由 harness 自主管理。
|
|
244
244
|
</p>
|
|
245
245
|
</div>
|
|
246
246
|
</div>
|
|
@@ -10,6 +10,7 @@ import { useCallback, useEffect, useState } from 'react';
|
|
|
10
10
|
import { providersApi } from '@renderer/api/providers';
|
|
11
11
|
import { ALL_AGENT_TYPES, AGENT_TYPE_LABELS } from '@renderer/components/team/HarnessCards';
|
|
12
12
|
import type { CcAgentType } from '@renderer/components/team/HarnessCards';
|
|
13
|
+
import { HarnessIcon } from '@renderer/components/team/HarnessSelect';
|
|
13
14
|
import { cn } from '@renderer/lib/utils';
|
|
14
15
|
import { OPEN_HERMIT_EVENTS } from '@renderer/utils/openHermitEvents';
|
|
15
16
|
import { CheckCircle2 } from 'lucide-react';
|
|
@@ -115,12 +116,7 @@ export const HarnessSection = (): React.JSX.Element => {
|
|
|
115
116
|
background: 'var(--color-surface-raised)',
|
|
116
117
|
}}
|
|
117
118
|
>
|
|
118
|
-
<
|
|
119
|
-
className={cn(
|
|
120
|
-
'h-2 w-2 shrink-0 rounded-full',
|
|
121
|
-
covered ? 'bg-green-500' : 'bg-gray-500'
|
|
122
|
-
)}
|
|
123
|
-
/>
|
|
119
|
+
<HarnessIcon type={type} className="size-5 shrink-0" />
|
|
124
120
|
<div className="min-w-0 flex-1">
|
|
125
121
|
<p
|
|
126
122
|
className="truncate text-xs font-medium"
|