feat(02-03): add 7 skill IPC channels with Zod schemas and register handlers

- Add importSkill, listSkills, getSkillDetail, deleteSkill, assignSkillToAgent, removeSkillFromAgent, checkSkillUpdate IPC channels
- Add Zod validation schemas for all skill payloads in contracts.ts
- Create ipc-skill-handlers.ts with company existence checks and domain-changed events on mutations
- Add SkillRecord, SkillImportResult, SkillUpdateStatus types to shared/types.ts
- Wire registerSkillHandlers into ipc-domain-handlers.ts
- Add skillService to RegisterDomainHandlersDependencies interface
This commit is contained in:
ZacharyZhang-NY committed 2026-03-26 00:45:03 -04:00
1 parent c9111d2f6d
commit b5ad164338
5 files changed
+225 -1

No files matched your search

+51 -1
View File
@@ -1,5 +1,5 @@
import { z } from "zod";
import type { AgentMessageRecord, AgentMetrics, BrowserActionRecord, CommentRecord, CompanyMetrics, DesktopEvent, InboxItem, OnboardingBootstrapResult, ProfileSnapshot, RunLogChunk, StandupReport } from "./types";
import type { AgentMessageRecord, AgentMetrics, BrowserActionRecord, CommentRecord, CompanyMetrics, DesktopEvent, InboxItem, OnboardingBootstrapResult, ProfileSnapshot, RunLogChunk, SkillImportResult, SkillRecord, SkillUpdateStatus, StandupReport } from "./types";
export const IPC_CHANNELS = {
loadSnapshot: "agent-company:load-snapshot",
@@ -73,6 +73,13 @@ export const IPC_CHANNELS = {
runWorkflow: "agent-company:run-workflow",
autoAssignTask: "agent-company:auto-assign-task",
searchMessages: "agent-company:search-messages",
importSkill: "agent-company:import-skill",
listSkills: "agent-company:list-skills",
getSkillDetail: "agent-company:get-skill-detail",
deleteSkill: "agent-company:delete-skill",
assignSkillToAgent: "agent-company:assign-skill-to-agent",
removeSkillFromAgent: "agent-company:remove-skill-from-agent",
checkSkillUpdate: "agent-company:check-skill-update",
} as const;
const optionalId = z.preprocess(
@@ -514,6 +521,42 @@ export const autoAssignSchema = z.object({
companyId: z.string().uuid(),
});
export const importSkillSchema = z.object({
companyId: z.string().min(1),
source: z.string().min(1),
});
export const listSkillsSchema = z.object({
companyId: z.string().min(1),
});
export const getSkillDetailSchema = z.object({
companyId: z.string().min(1),
skillId: z.string().min(1),
});
export const deleteSkillSchema = z.object({
companyId: z.string().min(1),
skillId: z.string().min(1),
});
export const assignSkillToAgentSchema = z.object({
companyId: z.string().min(1),
agentId: z.string().min(1),
skillId: z.string().min(1),
});
export const removeSkillFromAgentSchema = z.object({
companyId: z.string().min(1),
agentId: z.string().min(1),
skillId: z.string().min(1),
});
export const checkSkillUpdateSchema = z.object({
companyId: z.string().min(1),
skillId: z.string().min(1),
});
export type DesktopResult<T> =
| { ok: true; data: T }
| { ok: false; error: { code: string; message: string } };
@@ -589,6 +632,13 @@ export type DesktopApi = {
runWorkflow: (input: z.infer<typeof runWorkflowSchema>) => Promise<DesktopResult<boolean>>;
autoAssignTask: (input: z.infer<typeof autoAssignSchema>) => Promise<DesktopResult<string>>;
searchMessages: (input: z.infer<typeof searchMessagesSchema>) => Promise<DesktopResult<AgentMessageRecord[]>>;
importSkill: (companyId: string, source: string) => Promise<DesktopResult<SkillImportResult[]>>;
listSkills: (companyId: string) => Promise<DesktopResult<SkillRecord[]>>;
getSkillDetail: (companyId: string, skillId: string) => Promise<DesktopResult<SkillRecord>>;
deleteSkill: (companyId: string, skillId: string) => Promise<DesktopResult<void>>;
assignSkillToAgent: (companyId: string, agentId: string, skillId: string) => Promise<DesktopResult<void>>;
removeSkillFromAgent: (companyId: string, agentId: string, skillId: string) => Promise<DesktopResult<void>>;
checkSkillUpdate: (companyId: string, skillId: string) => Promise<DesktopResult<SkillUpdateStatus>>;
recoveryRetry: (taskId: string, agentId: string, companyId: string) => Promise<DesktopResult<null>>;
recoveryDismiss: (taskId: string) => Promise<DesktopResult<null>>;
recoveryFail: (taskId: string) => Promise<DesktopResult<null>>;
+46
View File
@@ -453,6 +453,52 @@ export interface OnboardingBootstrapResult {
runId: string | null;
}
// ---------------------------------------------------------------------------
// Skill system types (mirrored from main/skill-types.ts for IPC boundary)
// ---------------------------------------------------------------------------
export type SkillSourceType = "github" | "local_path" | "url" | "skills_sh" | "managed";
export type TrustLevel = "markdown_only" | "assets" | "scripts_executables";
export interface FileInventoryEntry {
path: string;
kind: "skill" | "reference" | "script" | "asset" | "markdown" | "other";
}
export interface SkillRecord {
id: string;
companyId: string;
key: string;
slug: string;
name: string;
description: string | null;
markdown: string;
sourceType: SkillSourceType;
sourceLocator: string | null;
sourceRef: string | null;
trustLevel: TrustLevel;
compatibility: string;
fileInventory: FileInventoryEntry[];
metadata: Record<string, unknown> | null;
createdAt: string;
updatedAt: string;
}
export interface SkillImportResult {
skillId: string;
key: string;
name: string;
isUpdate: boolean;
}
export interface SkillUpdateStatus {
skillId: string;
key: string;
currentRef: string | null;
latestRef: string | null;
hasUpdate: boolean;
}
export type SocialPlatform = "twitter" | "linkedin" | "instagram" | "facebook" | "reddit" | "youtube" | "tiktok" | "bluesky" | "other";
export type SocialAccountStatus = "active" | "logged_in" | "login_required" | "suspended" | "paused";
export type BrowserActionType = "post" | "reply" | "like" | "follow" | "browse_feed" | "screenshot" | "navigate" | "search";