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
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:
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user