feat: 新增技能编排引擎和工作流构建器组件
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

refactor: 统一Hands系统常量到单个源文件
refactor: 更新Hands中文名称和描述

fix: 修复技能市场在连接状态变化时重新加载
fix: 修复身份变更提案的错误处理逻辑

docs: 更新多个功能文档的验证状态和实现位置
docs: 更新Hands系统文档

test: 添加测试文件验证工作区路径
This commit is contained in:
iven
2026-03-25 08:27:25 +08:00
parent 9c781f5f2a
commit aa6a9cbd84
110 changed files with 12384 additions and 1337 deletions

View File

@@ -87,6 +87,12 @@ export interface StreamEventToolEnd {
output: unknown;
}
export interface StreamEventIterationStart {
type: 'iteration_start';
iteration: number;
maxIterations: number;
}
export interface StreamEventComplete {
type: 'complete';
inputTokens: number;
@@ -102,6 +108,7 @@ export type StreamChatEvent =
| StreamEventDelta
| StreamEventToolStart
| StreamEventToolEnd
| StreamEventIterationStart
| StreamEventComplete
| StreamEventError;
@@ -424,6 +431,7 @@ export class KernelClient {
break;
case 'tool_start':
console.log('[KernelClient] Tool started:', streamEvent.name, streamEvent.input);
if (callbacks.onTool) {
callbacks.onTool(
streamEvent.name,
@@ -434,6 +442,7 @@ export class KernelClient {
break;
case 'tool_end':
console.log('[KernelClient] Tool ended:', streamEvent.name, streamEvent.output);
if (callbacks.onTool) {
callbacks.onTool(
streamEvent.name,
@@ -443,7 +452,13 @@ export class KernelClient {
}
break;
case 'iteration_start':
console.log('[KernelClient] Iteration started:', streamEvent.iteration, '/', streamEvent.maxIterations);
// Don't need to notify user about iterations
break;
case 'complete':
console.log('[KernelClient] Stream complete:', streamEvent.inputTokens, streamEvent.outputTokens);
callbacks.onComplete(streamEvent.inputTokens, streamEvent.outputTokens);
// Clean up listener
if (unlisten) {
@@ -453,6 +468,7 @@ export class KernelClient {
break;
case 'error':
console.error('[KernelClient] Stream error:', streamEvent.message);
callbacks.onError(streamEvent.message);
// Clean up listener
if (unlisten) {
@@ -539,6 +555,236 @@ export class KernelClient {
};
}
// === Hands API ===
/**
* List all available hands
*/
async listHands(): Promise<{
hands: {
id?: string;
name: string;
description?: string;
status?: string;
requirements_met?: boolean;
category?: string;
icon?: string;
tool_count?: number;
tools?: string[];
metric_count?: number;
metrics?: string[];
}[]
}> {
const hands = await invoke<Array<{
id?: string;
name: string;
description?: string;
status?: string;
requirements_met?: boolean;
category?: string;
icon?: string;
tool_count?: number;
tools?: string[];
metric_count?: number;
metrics?: string[];
}>>('hand_list');
return { hands: hands || [] };
}
/**
* Get hand details
*/
async getHand(name: string): Promise<{
id?: string;
name?: string;
description?: string;
status?: string;
requirements_met?: boolean;
category?: string;
icon?: string;
provider?: string;
model?: string;
requirements?: { description?: string; name?: string; met?: boolean; satisfied?: boolean; details?: string; hint?: string }[];
tools?: string[];
metrics?: string[];
config?: Record<string, unknown>;
tool_count?: number;
metric_count?: number;
}> {
return invoke('hand_get', { name });
}
/**
* Trigger/execute a hand
*/
async triggerHand(name: string, params?: Record<string, unknown>): Promise<{ runId: string; status: string }> {
const result = await invoke<{ instance_id: string; status: string }>('hand_execute', {
id: name,
input: params || {},
});
return { runId: result.instance_id, status: result.status };
}
/**
* Get hand run status
*/
async getHandStatus(name: string, runId: string): Promise<{ status: string; result?: unknown }> {
return invoke('hand_run_status', { handName: name, runId });
}
/**
* Approve a hand execution
*/
async approveHand(name: string, runId: string, approved: boolean, reason?: string): Promise<{ status: string }> {
return invoke('hand_approve', { handName: name, runId, approved, reason });
}
/**
* Cancel a hand execution
*/
async cancelHand(name: string, runId: string): Promise<{ status: string }> {
return invoke('hand_cancel', { handName: name, runId });
}
/**
* List hand runs (execution history)
*/
async listHandRuns(name: string, opts?: { limit?: number; offset?: number }): Promise<{
runs: {
runId?: string;
run_id?: string;
id?: string;
status?: string;
startedAt?: string;
started_at?: string;
completedAt?: string;
completed_at?: string;
result?: unknown;
error?: string;
}[]
}> {
// Hand run history API may not exist yet, return empty array
try {
return await invoke('hand_run_list', { handName: name, ...opts });
} catch {
return { runs: [] };
}
}
// === Skills API ===
/**
* List all discovered skills
*/
async listSkills(): Promise<{
skills: {
id: string;
name: string;
description: string;
version: string;
capabilities: string[];
tags: string[];
mode: string;
enabled: boolean;
triggers: string[];
category?: string;
}[]
}> {
const skills = await invoke<Array<{
id: string;
name: string;
description: string;
version: string;
capabilities: string[];
tags: string[];
mode: string;
enabled: boolean;
triggers: string[];
category?: string;
}>>('skill_list');
return { skills: skills || [] };
}
/**
* Refresh skills from directory
*/
async refreshSkills(skillDir?: string): Promise<{
skills: {
id: string;
name: string;
description: string;
version: string;
capabilities: string[];
tags: string[];
mode: string;
enabled: boolean;
triggers: string[];
category?: string;
}[]
}> {
const skills = await invoke<Array<{
id: string;
name: string;
description: string;
version: string;
capabilities: string[];
tags: string[];
mode: string;
enabled: boolean;
triggers: string[];
category?: string;
}>>('skill_refresh', { skillDir: skillDir || null });
return { skills: skills || [] };
}
/**
* Execute a skill
*/
async executeSkill(id: string, input?: Record<string, unknown>): Promise<{
success: boolean;
output?: unknown;
error?: string;
durationMs?: number;
}> {
return invoke('skill_execute', {
id,
context: {},
input: input || {},
});
}
// === Triggers API (stubs for compatibility) ===
async listTriggers(): Promise<{ triggers?: { id: string; type: string; enabled: boolean }[] }> {
return { triggers: [] };
}
async getTrigger(_id: string): Promise<{ id: string; type: string; enabled: boolean } | null> {
return null;
}
async createTrigger(_trigger: { type: string; name?: string; enabled?: boolean; config?: Record<string, unknown>; handName?: string; workflowId?: string }): Promise<{ id?: string } | null> {
return null;
}
async updateTrigger(_id: string, _updates: { name?: string; enabled?: boolean; config?: Record<string, unknown>; handName?: string; workflowId?: string }): Promise<{ id: string }> {
throw new Error('Triggers not implemented');
}
async deleteTrigger(_id: string): Promise<{ status: string }> {
throw new Error('Triggers not implemented');
}
// === Approvals API (stubs for compatibility) ===
async listApprovals(_status?: string): Promise<{ approvals?: unknown[] }> {
return { approvals: [] };
}
async respondToApproval(_approvalId: string, _approved: boolean, _reason?: string): Promise<{ status: string }> {
throw new Error('Approvals not implemented');
}
/**
* REST API compatibility methods
*/