@geminilight/mindos 0.6.29 → 0.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/README.md +10 -4
- package/app/app/api/acp/config/route.ts +82 -0
- package/app/app/api/acp/detect/route.ts +71 -48
- package/app/app/api/acp/install/route.ts +51 -0
- package/app/app/api/acp/session/route.ts +141 -11
- package/app/app/api/ask/route.ts +116 -13
- package/app/app/api/workflows/route.ts +156 -0
- package/app/app/page.tsx +7 -2
- package/app/components/ActivityBar.tsx +12 -4
- package/app/components/AskModal.tsx +4 -1
- package/app/components/FileTree.tsx +21 -10
- package/app/components/HomeContent.tsx +1 -0
- package/app/components/Panel.tsx +1 -0
- package/app/components/RightAskPanel.tsx +5 -1
- package/app/components/SidebarLayout.tsx +6 -0
- package/app/components/agents/AgentDetailContent.tsx +263 -47
- package/app/components/agents/AgentsContentPage.tsx +11 -0
- package/app/components/agents/AgentsPanelA2aTab.tsx +285 -46
- package/app/components/agents/AgentsPanelSessionsTab.tsx +166 -0
- package/app/components/agents/agents-content-model.ts +2 -2
- package/app/components/ask/AgentSelectorCapsule.tsx +218 -0
- package/app/components/ask/AskContent.tsx +197 -239
- package/app/components/ask/FileChip.tsx +82 -17
- package/app/components/ask/MentionPopover.tsx +21 -3
- package/app/components/ask/MessageList.tsx +30 -9
- package/app/components/ask/SlashCommandPopover.tsx +21 -3
- package/app/components/panels/AgentsPanel.tsx +1 -0
- package/app/components/panels/AgentsPanelHubNav.tsx +9 -2
- package/app/components/panels/WorkflowsPanel.tsx +206 -0
- package/app/components/renderers/workflow-yaml/StepEditor.tsx +157 -0
- package/app/components/renderers/workflow-yaml/WorkflowEditor.tsx +201 -0
- package/app/components/renderers/workflow-yaml/WorkflowRunner.tsx +226 -0
- package/app/components/renderers/workflow-yaml/WorkflowYamlRenderer.tsx +126 -0
- package/app/components/renderers/workflow-yaml/execution.ts +177 -0
- package/app/components/renderers/workflow-yaml/index.ts +6 -0
- package/app/components/renderers/workflow-yaml/manifest.ts +21 -0
- package/app/components/renderers/workflow-yaml/parser.ts +172 -0
- package/app/components/renderers/workflow-yaml/selectors.tsx +522 -0
- package/app/components/renderers/workflow-yaml/serializer.ts +56 -0
- package/app/components/renderers/workflow-yaml/types.ts +46 -0
- package/app/hooks/useAcpConfig.ts +96 -0
- package/app/hooks/useAcpDetection.ts +69 -14
- package/app/hooks/useAcpRegistry.ts +46 -11
- package/app/hooks/useAskModal.ts +12 -5
- package/app/hooks/useAskPanel.ts +8 -5
- package/app/hooks/useAskSession.ts +19 -2
- package/app/hooks/useImageUpload.ts +152 -0
- package/app/lib/acp/acp-tools.ts +3 -1
- package/app/lib/acp/agent-descriptors.ts +274 -0
- package/app/lib/acp/bridge.ts +6 -0
- package/app/lib/acp/index.ts +20 -4
- package/app/lib/acp/registry.ts +74 -7
- package/app/lib/acp/session.ts +481 -28
- package/app/lib/acp/subprocess.ts +307 -21
- package/app/lib/acp/types.ts +158 -20
- package/app/lib/agent/model.ts +18 -3
- package/app/lib/agent/to-agent-messages.ts +25 -2
- package/app/lib/i18n/modules/knowledge.ts +4 -0
- package/app/lib/i18n/modules/navigation.ts +2 -0
- package/app/lib/i18n/modules/panels.ts +146 -2
- package/app/lib/pi-integration/skills.ts +21 -6
- package/app/lib/renderers/index.ts +2 -2
- package/app/lib/settings.ts +10 -0
- package/app/lib/types.ts +12 -1
- package/app/next-env.d.ts +1 -1
- package/app/package.json +3 -1
- package/package.json +1 -1
- package/templates/en/.mindos/workflows/Sprint Release.flow.yaml +130 -0
- package/templates/zh/.mindos/workflows//345/221/250/350/277/255/344/273/243/346/243/200/346/237/245.flow.yaml +84 -0
- package/app/components/renderers/workflow/WorkflowRenderer.tsx +0 -409
- package/app/components/renderers/workflow/manifest.ts +0 -14
|
@@ -13,13 +13,36 @@
|
|
|
13
13
|
* - Orphaned tool calls (running/pending from interrupted streams): supply empty result
|
|
14
14
|
* - Reasoning parts: filtered out (display-only, not sent back to LLM)
|
|
15
15
|
*/
|
|
16
|
-
import type { Message as FrontendMessage, ToolCallPart as FrontendToolCallPart } from '@/lib/types';
|
|
16
|
+
import type { Message as FrontendMessage, ToolCallPart as FrontendToolCallPart, ImagePart } from '@/lib/types';
|
|
17
17
|
import type { AgentMessage } from '@mariozechner/pi-agent-core';
|
|
18
18
|
import type { UserMessage, AssistantMessage, ToolResultMessage } from '@mariozechner/pi-ai';
|
|
19
19
|
|
|
20
20
|
// Re-export for convenience
|
|
21
21
|
export type { AgentMessage } from '@mariozechner/pi-agent-core';
|
|
22
22
|
|
|
23
|
+
/** Build multimodal content array for user messages with images */
|
|
24
|
+
function buildUserContent(text: string, images?: ImagePart[]): string | any[] {
|
|
25
|
+
// Filter out stripped images (empty data from persisted sessions)
|
|
26
|
+
const validImages = images?.filter(img => img.data);
|
|
27
|
+
if (!validImages || validImages.length === 0) return text;
|
|
28
|
+
|
|
29
|
+
// Multimodal content: images first, then text
|
|
30
|
+
// Use pi-ai ImageContent format: { type: 'image', data: base64, mimeType }
|
|
31
|
+
// The SDK converts this to the provider-specific format (Anthropic/OpenAI) internally
|
|
32
|
+
const parts: any[] = [];
|
|
33
|
+
for (const img of validImages) {
|
|
34
|
+
parts.push({
|
|
35
|
+
type: 'image',
|
|
36
|
+
data: img.data,
|
|
37
|
+
mimeType: img.mimeType,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (text) {
|
|
41
|
+
parts.push({ type: 'text', text });
|
|
42
|
+
}
|
|
43
|
+
return parts;
|
|
44
|
+
}
|
|
45
|
+
|
|
23
46
|
export function toAgentMessages(messages: FrontendMessage[]): AgentMessage[] {
|
|
24
47
|
const result: AgentMessage[] = [];
|
|
25
48
|
|
|
@@ -29,7 +52,7 @@ export function toAgentMessages(messages: FrontendMessage[]): AgentMessage[] {
|
|
|
29
52
|
if (msg.role === 'user') {
|
|
30
53
|
result.push({
|
|
31
54
|
role: 'user',
|
|
32
|
-
content: msg.content,
|
|
55
|
+
content: buildUserContent(msg.content, msg.images),
|
|
33
56
|
timestamp,
|
|
34
57
|
} satisfies UserMessage as AgentMessage);
|
|
35
58
|
continue;
|
|
@@ -39,11 +39,13 @@ export const knowledgeEn = {
|
|
|
39
39
|
'agent-inspector': 'Agent Inspector',
|
|
40
40
|
'config-panel': 'Config Panel',
|
|
41
41
|
'todo': 'TODO Board',
|
|
42
|
+
'workflow-yaml': 'Workflows',
|
|
42
43
|
} as Record<string, string>,
|
|
43
44
|
toolDesc: {
|
|
44
45
|
'agent-inspector': 'View agent tool-call logs and audit trail',
|
|
45
46
|
'config-panel': 'Edit and manage global configuration',
|
|
46
47
|
'todo': 'Manage tasks as an interactive kanban board',
|
|
48
|
+
'workflow-yaml': 'Execute step-by-step workflows with AI assistance',
|
|
47
49
|
} as Record<string, string>,
|
|
48
50
|
plugins: 'Extensions',
|
|
49
51
|
changeHistory: 'Change History',
|
|
@@ -251,11 +253,13 @@ export const knowledgeZh = {
|
|
|
251
253
|
'agent-inspector': '审计面板',
|
|
252
254
|
'config-panel': '配置面板',
|
|
253
255
|
'todo': '待办面板',
|
|
256
|
+
'workflow-yaml': '工作流',
|
|
254
257
|
} as Record<string, string>,
|
|
255
258
|
toolDesc: {
|
|
256
259
|
'agent-inspector': '查看 Agent 操作日志与调用轨迹',
|
|
257
260
|
'config-panel': '编辑和管理全局配置项',
|
|
258
261
|
'todo': '以看板形式管理待办事项',
|
|
262
|
+
'workflow-yaml': '执行多步骤工作流,AI 辅助执行',
|
|
259
263
|
} as Record<string, string>,
|
|
260
264
|
plugins: '扩展',
|
|
261
265
|
changeHistory: '变更历史',
|
|
@@ -11,6 +11,7 @@ export const navigationEn = {
|
|
|
11
11
|
agents: 'Agents',
|
|
12
12
|
echo: 'Echo',
|
|
13
13
|
discover: 'Discover',
|
|
14
|
+
workflows: 'Flows',
|
|
14
15
|
history: 'History',
|
|
15
16
|
help: 'Help',
|
|
16
17
|
syncLabel: 'Sync',
|
|
@@ -86,6 +87,7 @@ export const navigationZh = {
|
|
|
86
87
|
agents: '智能体',
|
|
87
88
|
echo: '回响',
|
|
88
89
|
discover: '探索',
|
|
90
|
+
workflows: '流程',
|
|
89
91
|
history: '历史',
|
|
90
92
|
help: '帮助',
|
|
91
93
|
syncLabel: '同步',
|
|
@@ -40,6 +40,7 @@ export const panelsEn = {
|
|
|
40
40
|
navMcp: 'MCP',
|
|
41
41
|
navSkills: 'Skills',
|
|
42
42
|
navNetwork: 'Network',
|
|
43
|
+
navSessions: 'Sessions',
|
|
43
44
|
// A2A tab
|
|
44
45
|
a2aTabTitle: 'Remote Agents',
|
|
45
46
|
a2aTabEmpty: 'No remote agents',
|
|
@@ -90,11 +91,33 @@ export const panelsEn = {
|
|
|
90
91
|
acpComingSoon: 'Coming soon \u2014 use Ask AI to invoke',
|
|
91
92
|
acpReady: 'Ready',
|
|
92
93
|
acpNotInstalled: 'Not Installed',
|
|
93
|
-
acpScan: '
|
|
94
|
+
acpScan: 'Re-scan',
|
|
94
95
|
acpInstallHint: (cmd: string) => `Install with: ${cmd}`,
|
|
96
|
+
acpInstall: 'Install',
|
|
97
|
+
acpInstalling: 'Installing…',
|
|
95
98
|
acpLoading: 'Loading ACP registry\u2026',
|
|
96
99
|
acpLoadFailed: 'Failed to load ACP registry.',
|
|
97
100
|
acpRetry: 'Retry',
|
|
101
|
+
acpQuickReview: 'Review code',
|
|
102
|
+
acpQuickFix: 'Fix bugs',
|
|
103
|
+
acpQuickExplain: 'Explain repo',
|
|
104
|
+
acpUseWith: (name: string) => `Use ${name} to `,
|
|
105
|
+
acpDefaultAgent: 'MindOS Agent',
|
|
106
|
+
acpSelectAgent: 'Select Agent',
|
|
107
|
+
acpChangeAgent: 'Change agent',
|
|
108
|
+
acpConfigToggle: 'Configure',
|
|
109
|
+
acpConfigCommand: 'Command',
|
|
110
|
+
acpConfigArgs: 'Args',
|
|
111
|
+
acpConfigEnv: 'Env',
|
|
112
|
+
acpConfigEnvAdd: 'Add env var',
|
|
113
|
+
acpConfigSource: 'Source',
|
|
114
|
+
acpConfigSourceBuiltin: 'built-in',
|
|
115
|
+
acpConfigSourceRegistry: 'registry',
|
|
116
|
+
acpConfigSourceUser: 'custom',
|
|
117
|
+
acpConfigReset: 'Reset',
|
|
118
|
+
acpConfigSave: 'Save',
|
|
119
|
+
acpConfigSaved: 'Saved',
|
|
120
|
+
acpConfigPath: 'Path',
|
|
98
121
|
networkEmptyTitle: 'Connect to the agent ecosystem',
|
|
99
122
|
networkEmptyDesc: 'Discover remote agents or browse coding agents from the ACP registry.',
|
|
100
123
|
networkDiscoverBtn: 'Discover Agent',
|
|
@@ -139,6 +162,22 @@ export const panelsEn = {
|
|
|
139
162
|
viewAll: 'View all use cases',
|
|
140
163
|
tryIt: 'Try',
|
|
141
164
|
},
|
|
165
|
+
workflows: {
|
|
166
|
+
title: 'Flows',
|
|
167
|
+
empty: 'No flows yet',
|
|
168
|
+
emptyDesc: 'Create your first flow to automate multi-step tasks with AI.',
|
|
169
|
+
newWorkflow: 'New Flow',
|
|
170
|
+
nSteps: (n: number) => `${n} step${n === 1 ? '' : 's'}`,
|
|
171
|
+
parseError: 'Parse error',
|
|
172
|
+
name: 'Name',
|
|
173
|
+
namePlaceholder: 'My Flow',
|
|
174
|
+
template: 'Template',
|
|
175
|
+
templateBlank: 'Blank',
|
|
176
|
+
create: 'Create',
|
|
177
|
+
cancel: 'Cancel',
|
|
178
|
+
creating: 'Creating...',
|
|
179
|
+
exists: 'A workflow with this name already exists',
|
|
180
|
+
},
|
|
142
181
|
},
|
|
143
182
|
echoPages: {
|
|
144
183
|
parent: 'Echo',
|
|
@@ -211,6 +250,7 @@ export const panelsEn = {
|
|
|
211
250
|
navMcp: 'MCP',
|
|
212
251
|
navSkills: 'Skills',
|
|
213
252
|
navNetwork: 'Network',
|
|
253
|
+
navSessions: 'Sessions',
|
|
214
254
|
a2aTabTitle: 'Remote Agents',
|
|
215
255
|
a2aTabEmptyHint: 'Discover agents to enable cross-agent delegation.',
|
|
216
256
|
backToOverview: 'Back to Agents',
|
|
@@ -518,6 +558,38 @@ export const panelsEn = {
|
|
|
518
558
|
mcpReconnectAll: 'Reconnect all',
|
|
519
559
|
mcpReconnectAllRunning: 'Reconnecting...',
|
|
520
560
|
mcpReconnectAllDone: (ok: number, failed: number) => `Reconnected ${ok}${failed > 0 ? `, failed ${failed}` : ''}.`,
|
|
561
|
+
// ─── Runtime & Diagnostics ───
|
|
562
|
+
runtimeDiagTitle: 'Runtime & Diagnostics',
|
|
563
|
+
runtimePing: 'Ping',
|
|
564
|
+
runtimePinging: 'Pinging...',
|
|
565
|
+
runtimePingOk: (ms: number) => `Reachable (${ms}ms)`,
|
|
566
|
+
runtimePingFail: 'Unreachable',
|
|
567
|
+
runtimeUptime: 'Uptime',
|
|
568
|
+
runtimePid: 'Process',
|
|
569
|
+
runtimeMemory: 'Memory',
|
|
570
|
+
runtimeVersion: 'Version',
|
|
571
|
+
runtimeStartedAt: 'Started',
|
|
572
|
+
runtimeNoData: 'No runtime data available.',
|
|
573
|
+
// ─── Environment & Permissions ───
|
|
574
|
+
envPermTitle: 'Environment & Permissions',
|
|
575
|
+
envVars: 'Environment variables',
|
|
576
|
+
envVarsCount: (n: number) => `${n} configured`,
|
|
577
|
+
envVarsEmpty: 'No custom environment variables.',
|
|
578
|
+
envScope: 'Scope',
|
|
579
|
+
envReadOnly: 'Read-only access',
|
|
580
|
+
envWriteAccess: 'Write access',
|
|
581
|
+
envFileAccess: 'File access',
|
|
582
|
+
envNetworkAccess: 'Network access',
|
|
583
|
+
envAllowed: 'Allowed',
|
|
584
|
+
envRestricted: 'Restricted',
|
|
585
|
+
// ─── Activity & Usage ───
|
|
586
|
+
activityTitle: 'Activity & Usage',
|
|
587
|
+
activityTotal: 'Total invocations',
|
|
588
|
+
activityLast7d: 'Last 7 days',
|
|
589
|
+
activityLastInvocation: 'Last invocation',
|
|
590
|
+
activityTokensUsed: 'Tokens used',
|
|
591
|
+
activityAvgLatency: 'Avg latency',
|
|
592
|
+
activityNoData: 'No activity recorded yet.',
|
|
521
593
|
},
|
|
522
594
|
detailSubtitle: '',
|
|
523
595
|
detailNotFound: 'Agent not found — it may have been removed or renamed.',
|
|
@@ -565,6 +637,7 @@ export const panelsZh = {
|
|
|
565
637
|
navMcp: 'MCP',
|
|
566
638
|
navSkills: '技能',
|
|
567
639
|
navNetwork: '网络',
|
|
640
|
+
navSessions: '会话',
|
|
568
641
|
// A2A tab
|
|
569
642
|
a2aTabTitle: '远程 Agent',
|
|
570
643
|
a2aTabEmpty: '无远程 Agent',
|
|
@@ -615,11 +688,33 @@ export const panelsZh = {
|
|
|
615
688
|
acpComingSoon: '即将上线 — 当前可通过 Ask AI 调用',
|
|
616
689
|
acpReady: '就绪',
|
|
617
690
|
acpNotInstalled: '未安装',
|
|
618
|
-
acpScan: '
|
|
691
|
+
acpScan: '重新扫描',
|
|
619
692
|
acpInstallHint: (cmd: string) => `安装命令: ${cmd}`,
|
|
693
|
+
acpInstall: '安装',
|
|
694
|
+
acpInstalling: '安装中…',
|
|
620
695
|
acpLoading: '加载 ACP 注册表中…',
|
|
621
696
|
acpLoadFailed: '加载 ACP 注册表失败。',
|
|
622
697
|
acpRetry: '重试',
|
|
698
|
+
acpQuickReview: '代码审查',
|
|
699
|
+
acpQuickFix: '修复Bug',
|
|
700
|
+
acpQuickExplain: '解释项目',
|
|
701
|
+
acpUseWith: (name: string) => `使用 ${name} `,
|
|
702
|
+
acpDefaultAgent: 'MindOS Agent',
|
|
703
|
+
acpSelectAgent: '选择 Agent',
|
|
704
|
+
acpChangeAgent: '切换 Agent',
|
|
705
|
+
acpConfigToggle: '配置',
|
|
706
|
+
acpConfigCommand: '命令',
|
|
707
|
+
acpConfigArgs: '参数',
|
|
708
|
+
acpConfigEnv: '环境变量',
|
|
709
|
+
acpConfigEnvAdd: '添加环境变量',
|
|
710
|
+
acpConfigSource: '来源',
|
|
711
|
+
acpConfigSourceBuiltin: '内置',
|
|
712
|
+
acpConfigSourceRegistry: '注册表',
|
|
713
|
+
acpConfigSourceUser: '自定义',
|
|
714
|
+
acpConfigReset: '重置',
|
|
715
|
+
acpConfigSave: '保存',
|
|
716
|
+
acpConfigSaved: '已保存',
|
|
717
|
+
acpConfigPath: '路径',
|
|
623
718
|
networkEmptyTitle: '连接智能体生态',
|
|
624
719
|
networkEmptyDesc: '发现远程 Agent 或浏览 ACP 注册表中的编程智能体。',
|
|
625
720
|
networkDiscoverBtn: '发现 Agent',
|
|
@@ -664,6 +759,22 @@ export const panelsZh = {
|
|
|
664
759
|
viewAll: '查看所有使用案例',
|
|
665
760
|
tryIt: '试试',
|
|
666
761
|
},
|
|
762
|
+
workflows: {
|
|
763
|
+
title: '流程',
|
|
764
|
+
empty: '还没有流程',
|
|
765
|
+
emptyDesc: '创建第一个流程,用 AI 自动化多步骤任务。',
|
|
766
|
+
newWorkflow: '新建流程',
|
|
767
|
+
nSteps: (n: number) => `${n} 个步骤`,
|
|
768
|
+
parseError: '解析错误',
|
|
769
|
+
name: '名称',
|
|
770
|
+
namePlaceholder: '我的流程',
|
|
771
|
+
template: '模板',
|
|
772
|
+
templateBlank: '空白',
|
|
773
|
+
create: '创建',
|
|
774
|
+
cancel: '取消',
|
|
775
|
+
creating: '创建中...',
|
|
776
|
+
exists: '已存在同名流程',
|
|
777
|
+
},
|
|
667
778
|
},
|
|
668
779
|
echoPages: {
|
|
669
780
|
parent: '回响',
|
|
@@ -736,6 +847,7 @@ export const panelsZh = {
|
|
|
736
847
|
navMcp: 'MCP',
|
|
737
848
|
navSkills: 'Skills',
|
|
738
849
|
navNetwork: '网络',
|
|
850
|
+
navSessions: '会话',
|
|
739
851
|
a2aTabTitle: '远程 Agent',
|
|
740
852
|
a2aTabEmptyHint: '发现远程 Agent 以启用跨 Agent 委派。',
|
|
741
853
|
backToOverview: '返回 Agents',
|
|
@@ -1043,6 +1155,38 @@ export const panelsZh = {
|
|
|
1043
1155
|
mcpReconnectAll: '全部重连',
|
|
1044
1156
|
mcpReconnectAllRunning: '正在重连...',
|
|
1045
1157
|
mcpReconnectAllDone: (ok: number, failed: number) => `已重连 ${ok}${failed > 0 ? `,失败 ${failed}` : ''}。`,
|
|
1158
|
+
// ─── 运行与诊断 ───
|
|
1159
|
+
runtimeDiagTitle: '运行与诊断',
|
|
1160
|
+
runtimePing: '连通测试',
|
|
1161
|
+
runtimePinging: '测试中...',
|
|
1162
|
+
runtimePingOk: (ms: number) => `可达 (${ms}ms)`,
|
|
1163
|
+
runtimePingFail: '不可达',
|
|
1164
|
+
runtimeUptime: '运行时长',
|
|
1165
|
+
runtimePid: '进程',
|
|
1166
|
+
runtimeMemory: '内存',
|
|
1167
|
+
runtimeVersion: '版本',
|
|
1168
|
+
runtimeStartedAt: '启动于',
|
|
1169
|
+
runtimeNoData: '暂无运行数据。',
|
|
1170
|
+
// ─── 环境与权限 ───
|
|
1171
|
+
envPermTitle: '环境与权限',
|
|
1172
|
+
envVars: '环境变量',
|
|
1173
|
+
envVarsCount: (n: number) => `已配置 ${n} 个`,
|
|
1174
|
+
envVarsEmpty: '暂无自定义环境变量。',
|
|
1175
|
+
envScope: '作用域',
|
|
1176
|
+
envReadOnly: '只读访问',
|
|
1177
|
+
envWriteAccess: '写入访问',
|
|
1178
|
+
envFileAccess: '文件访问',
|
|
1179
|
+
envNetworkAccess: '网络访问',
|
|
1180
|
+
envAllowed: '允许',
|
|
1181
|
+
envRestricted: '受限',
|
|
1182
|
+
// ─── 活动与用量 ───
|
|
1183
|
+
activityTitle: '活动与用量',
|
|
1184
|
+
activityTotal: '总调用次数',
|
|
1185
|
+
activityLast7d: '近 7 天',
|
|
1186
|
+
activityLastInvocation: '最近调用',
|
|
1187
|
+
activityTokensUsed: '消耗 Tokens',
|
|
1188
|
+
activityAvgLatency: '平均延迟',
|
|
1189
|
+
activityNoData: '暂无活动记录。',
|
|
1046
1190
|
},
|
|
1047
1191
|
detailSubtitle: '',
|
|
1048
1192
|
detailNotFound: '未找到该 Agent,可能已移除或重命名。',
|
|
@@ -23,15 +23,30 @@ export function parseSkillMd(content: string): { name: string; description: stri
|
|
|
23
23
|
if (!match) return { name: '', description: '' };
|
|
24
24
|
const yaml = match[1];
|
|
25
25
|
const nameMatch = yaml.match(/^name:\s*(.+)/m);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
// Try to match block scalar (description: >) first
|
|
28
|
+
// Captures all indented lines until next non-indented line or EOF
|
|
28
29
|
let description = '';
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const blockMatch = yaml.match(/^description:\s*>?\s*\n((?:\s+.+\n?)*)/m);
|
|
31
|
+
if (blockMatch && blockMatch[1].trim()) {
|
|
32
|
+
// Block scalar: join indented lines, dedent, preserve structure
|
|
33
|
+
description = blockMatch[1]
|
|
34
|
+
.split('\n')
|
|
35
|
+
.map(line => line.replace(/^\s+/, '')) // Remove leading spaces
|
|
36
|
+
.filter(line => line.trim()) // Remove empty lines
|
|
37
|
+
.join(' ')
|
|
38
|
+
.slice(0, 200);
|
|
31
39
|
} else {
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
// Fallback to single-line description
|
|
41
|
+
const simpleMatch = yaml.match(/^description:\s*(.+)/m);
|
|
42
|
+
if (simpleMatch) {
|
|
43
|
+
const val = simpleMatch[1].trim();
|
|
44
|
+
// Skip the ">" character if it's there (fallback from block scalar)
|
|
45
|
+
description = val === '>' ? '' : val.slice(0, 200);
|
|
46
|
+
}
|
|
34
47
|
}
|
|
48
|
+
|
|
49
|
+
const name = nameMatch ? nameMatch[1].trim() : '';
|
|
35
50
|
return { name, description };
|
|
36
51
|
}
|
|
37
52
|
|
|
@@ -10,11 +10,11 @@ import { manifest as csv } from '@/components/renderers/csv/manifest';
|
|
|
10
10
|
import { manifest as summary } from '@/components/renderers/summary/manifest';
|
|
11
11
|
import { manifest as timeline } from '@/components/renderers/timeline/manifest';
|
|
12
12
|
import { manifest as todo } from '@/components/renderers/todo/manifest';
|
|
13
|
-
import { manifest as
|
|
13
|
+
import { manifest as workflowYaml } from '@/components/renderers/workflow-yaml/manifest';
|
|
14
14
|
import { manifest as graph } from '@/components/renderers/graph/manifest';
|
|
15
15
|
|
|
16
16
|
const manifests = [
|
|
17
|
-
agentInspector, backlinks, config, csv, summary, timeline, todo,
|
|
17
|
+
agentInspector, backlinks, config, csv, summary, timeline, todo, workflowYaml, graph,
|
|
18
18
|
];
|
|
19
19
|
|
|
20
20
|
for (const m of manifests) {
|
package/app/lib/settings.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
|
+
import { parseAcpAgentOverrides } from './acp/agent-descriptors';
|
|
4
5
|
|
|
5
6
|
const SETTINGS_PATH = path.join(os.homedir(), '.mindos', 'config.json');
|
|
6
7
|
|
|
@@ -49,6 +50,8 @@ export interface ServerSettings {
|
|
|
49
50
|
setupPending?: boolean; // true → / redirects to /setup
|
|
50
51
|
disabledSkills?: string[];
|
|
51
52
|
guideState?: GuideState;
|
|
53
|
+
/** Per-agent ACP overrides (command, args, env, enabled). Keyed by agent ID. */
|
|
54
|
+
acpAgents?: Record<string, import('./acp/agent-descriptors').AcpAgentOverride>;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
const DEFAULTS: ServerSettings = {
|
|
@@ -133,6 +136,11 @@ function parseAgent(raw: unknown): AgentConfig | undefined {
|
|
|
133
136
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
134
137
|
}
|
|
135
138
|
|
|
139
|
+
/** Parse acpAgents config field, delegates to agent-descriptors.ts */
|
|
140
|
+
function parseAcpAgentsField(raw: unknown): Record<string, import('./acp/agent-descriptors').AcpAgentOverride> | undefined {
|
|
141
|
+
return parseAcpAgentOverrides(raw);
|
|
142
|
+
}
|
|
143
|
+
|
|
136
144
|
/** Parse guideState from unknown input */
|
|
137
145
|
function parseGuideState(raw: unknown): GuideState | undefined {
|
|
138
146
|
if (!raw || typeof raw !== 'object') return undefined;
|
|
@@ -159,6 +167,7 @@ export function readSettings(): ServerSettings {
|
|
|
159
167
|
return {
|
|
160
168
|
ai: migrateAi(parsed),
|
|
161
169
|
agent: parseAgent(parsed.agent),
|
|
170
|
+
acpAgents: parseAcpAgentsField(parsed.acpAgents),
|
|
162
171
|
mindRoot: (parsed.mindRoot ?? parsed.sopRoot ?? DEFAULTS.mindRoot) as string,
|
|
163
172
|
webPassword: typeof parsed.webPassword === 'string' ? parsed.webPassword : undefined,
|
|
164
173
|
authToken: typeof parsed.authToken === 'string' ? parsed.authToken : undefined,
|
|
@@ -189,6 +198,7 @@ export function writeSettings(settings: ServerSettings): void {
|
|
|
189
198
|
if (settings.startMode !== undefined) merged.startMode = settings.startMode;
|
|
190
199
|
if (settings.disabledSkills !== undefined) merged.disabledSkills = settings.disabledSkills;
|
|
191
200
|
if (settings.guideState !== undefined) merged.guideState = settings.guideState;
|
|
201
|
+
if (settings.acpAgents !== undefined) merged.acpAgents = settings.acpAgents;
|
|
192
202
|
// setupPending: false/undefined → remove the field (cleanup); true → set it
|
|
193
203
|
if ('setupPending' in settings) {
|
|
194
204
|
if (settings.setupPending) merged.setupPending = true;
|
package/app/lib/types.ts
CHANGED
|
@@ -32,7 +32,16 @@ export interface ReasoningPart {
|
|
|
32
32
|
text: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export type
|
|
35
|
+
export type ImageMimeType = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
|
|
36
|
+
|
|
37
|
+
export interface ImagePart {
|
|
38
|
+
type: 'image';
|
|
39
|
+
/** Base64-encoded image data (no data: prefix) */
|
|
40
|
+
data: string;
|
|
41
|
+
mimeType: ImageMimeType;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type MessagePart = TextPart | ToolCallPart | ReasoningPart | ImagePart;
|
|
36
45
|
|
|
37
46
|
export interface Message {
|
|
38
47
|
role: 'user' | 'assistant';
|
|
@@ -41,6 +50,8 @@ export interface Message {
|
|
|
41
50
|
timestamp?: number;
|
|
42
51
|
/** Structured parts for assistant messages (tool calls + text segments) */
|
|
43
52
|
parts?: MessagePart[];
|
|
53
|
+
/** Images attached to this message (user messages only) */
|
|
54
|
+
images?: ImagePart[];
|
|
44
55
|
/** Skill name used for this user message (rendered as a capsule in the UI) */
|
|
45
56
|
skillName?: string;
|
|
46
57
|
}
|
package/app/next-env.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/types/routes.d.ts";
|
|
3
|
+
import "./.next/dev/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
package/app/package.json
CHANGED
|
@@ -39,9 +39,10 @@
|
|
|
39
39
|
"extend": "^3.0.2",
|
|
40
40
|
"fuse.js": "^7.1.0",
|
|
41
41
|
"github-slugger": "^2.0.0",
|
|
42
|
+
"js-yaml": "^4.1.1",
|
|
42
43
|
"lucide-react": "^0.577.0",
|
|
43
|
-
"nanoid": "^5.1.0",
|
|
44
44
|
"mcporter": "^0.7.3",
|
|
45
|
+
"nanoid": "^5.1.0",
|
|
45
46
|
"next": "16.1.6",
|
|
46
47
|
"papaparse": "^5.5.3",
|
|
47
48
|
"pdfjs-dist": "^4.10.38",
|
|
@@ -61,6 +62,7 @@
|
|
|
61
62
|
},
|
|
62
63
|
"devDependencies": {
|
|
63
64
|
"@tailwindcss/postcss": "^4",
|
|
65
|
+
"@types/js-yaml": "^4.0.9",
|
|
64
66
|
"@types/node": "^20",
|
|
65
67
|
"@types/papaparse": "^5.5.2",
|
|
66
68
|
"@types/react": "^19",
|
package/package.json
CHANGED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
title: Sprint Release Workflow
|
|
2
|
+
description: Weekly sprint release process with multi-agent collaboration and comprehensive QA
|
|
3
|
+
|
|
4
|
+
# Global configuration - skills available across all steps
|
|
5
|
+
skills:
|
|
6
|
+
- software-architecture
|
|
7
|
+
- code-review-quality
|
|
8
|
+
- document-release
|
|
9
|
+
|
|
10
|
+
# Global tools guidance (advisory - LLM auto-selects based on context)
|
|
11
|
+
tools:
|
|
12
|
+
- git
|
|
13
|
+
- npm
|
|
14
|
+
- github
|
|
15
|
+
|
|
16
|
+
# Workflow steps - executed sequentially
|
|
17
|
+
steps:
|
|
18
|
+
# Step 1: Run comprehensive test suite
|
|
19
|
+
- id: run_tests
|
|
20
|
+
name: Run tests
|
|
21
|
+
description: Execute full test suite and report results with coverage metrics
|
|
22
|
+
agent: cursor
|
|
23
|
+
prompt: |
|
|
24
|
+
Execute the full test suite for this project.
|
|
25
|
+
|
|
26
|
+
Provide:
|
|
27
|
+
1. Total tests run, passed, failed
|
|
28
|
+
2. Coverage report (lines/branches/functions)
|
|
29
|
+
3. Any critical failures with recommendations
|
|
30
|
+
4. Time taken
|
|
31
|
+
|
|
32
|
+
If failures exist, list the top 3 most critical with suggested fixes.
|
|
33
|
+
timeout: 120
|
|
34
|
+
|
|
35
|
+
# Step 2: Code review with dedicated AI agent
|
|
36
|
+
- id: code_review
|
|
37
|
+
name: Code review
|
|
38
|
+
description: Comprehensive code review using software architecture principles
|
|
39
|
+
agent: claude-code
|
|
40
|
+
skill: code-review-quality
|
|
41
|
+
prompt: |
|
|
42
|
+
Review the recent code changes using the code-review-quality standard.
|
|
43
|
+
|
|
44
|
+
Evaluate:
|
|
45
|
+
1. Correctness - error handling, edge cases
|
|
46
|
+
2. Security - authentication, input validation, secrets
|
|
47
|
+
3. Performance - N+1 queries, caching, complexity
|
|
48
|
+
4. Maintainability - naming, tests, documentation
|
|
49
|
+
5. Architecture - follows project patterns, no anti-patterns
|
|
50
|
+
|
|
51
|
+
Provide a rating (e.g., 8.5/10) and key recommendations.
|
|
52
|
+
timeout: 120
|
|
53
|
+
|
|
54
|
+
# Step 3: Automated security scan (no agent - use LLM with tools)
|
|
55
|
+
- id: security_check
|
|
56
|
+
name: Security scan
|
|
57
|
+
description: Run security analysis and dependency checks
|
|
58
|
+
tools:
|
|
59
|
+
- npm
|
|
60
|
+
- github
|
|
61
|
+
prompt: |
|
|
62
|
+
Perform security checks on this project:
|
|
63
|
+
|
|
64
|
+
1. Check for known vulnerabilities in npm dependencies
|
|
65
|
+
2. Review recent dependency changes
|
|
66
|
+
3. Check for hardcoded secrets or credentials
|
|
67
|
+
4. Evaluate access control and authentication mechanisms
|
|
68
|
+
5. Assess error handling for information leaks
|
|
69
|
+
|
|
70
|
+
Report severity and recommended fixes.
|
|
71
|
+
timeout: 60
|
|
72
|
+
|
|
73
|
+
# Step 4: Update documentation using document-release skill
|
|
74
|
+
- id: update_docs
|
|
75
|
+
name: Update documentation
|
|
76
|
+
description: Sync CHANGELOG, README, and API docs with shipped changes
|
|
77
|
+
skill: document-release
|
|
78
|
+
prompt: |
|
|
79
|
+
Update project documentation based on the shipped changes:
|
|
80
|
+
|
|
81
|
+
1. Update CHANGELOG.md following semantic versioning
|
|
82
|
+
2. Update README.md if features or APIs changed
|
|
83
|
+
3. Update API documentation if endpoints changed
|
|
84
|
+
4. Verify all documentation links are valid
|
|
85
|
+
5. Check code examples match current implementation
|
|
86
|
+
|
|
87
|
+
Provide a summary of all documentation updates made.
|
|
88
|
+
timeout: 60
|
|
89
|
+
|
|
90
|
+
# Step 5: Final checklist before release
|
|
91
|
+
- id: pre_release_check
|
|
92
|
+
name: Pre-release verification
|
|
93
|
+
description: Final comprehensive verification before shipping
|
|
94
|
+
agent: mindos
|
|
95
|
+
prompt: |
|
|
96
|
+
Perform final pre-release verification:
|
|
97
|
+
|
|
98
|
+
Checklist:
|
|
99
|
+
☐ All tests passing
|
|
100
|
+
☐ Code review completed and issues resolved
|
|
101
|
+
☐ Security scan passed or risks accepted
|
|
102
|
+
☐ Documentation updated and links valid
|
|
103
|
+
☐ Version bumped correctly (semver)
|
|
104
|
+
☐ Git tags and commits clean
|
|
105
|
+
☐ No uncommitted changes
|
|
106
|
+
☐ Changelog entry present
|
|
107
|
+
☐ Dependencies updated and locked
|
|
108
|
+
☐ Performance benchmarks acceptable
|
|
109
|
+
|
|
110
|
+
Confirm release readiness or list any blockers.
|
|
111
|
+
timeout: 60
|
|
112
|
+
|
|
113
|
+
# Step 6: Create release tag and prepare release notes
|
|
114
|
+
- id: create_release
|
|
115
|
+
name: Create release
|
|
116
|
+
description: Tag release and prepare release notes for publishing
|
|
117
|
+
tools:
|
|
118
|
+
- git
|
|
119
|
+
- npm
|
|
120
|
+
prompt: |
|
|
121
|
+
Prepare the project for release:
|
|
122
|
+
|
|
123
|
+
1. Confirm version in package.json matches intended release
|
|
124
|
+
2. Create git tag for this version (vX.Y.Z)
|
|
125
|
+
3. Generate release notes from CHANGELOG.md
|
|
126
|
+
4. Prepare npm release command (do not execute yet)
|
|
127
|
+
5. List all deliverables included in this release
|
|
128
|
+
|
|
129
|
+
Provide step-by-step commands for final publishing.
|
|
130
|
+
timeout: 60
|