@octo-cyber/ai 0.5.0 → 0.5.2
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/ai.module.d.ts +2 -1
- package/dist/ai.module.d.ts.map +1 -1
- package/dist/ai.module.js +22 -3
- package/dist/ai.module.js.map +1 -1
- package/dist/cli/cli-executor.service.js +1 -1
- package/dist/cli/cli-executor.service.js.map +1 -1
- package/dist/cli/cli-registry.service.js +1 -1
- package/dist/cli/cli-registry.service.js.map +1 -1
- package/dist/cli/controllers/ai-cli.controller.d.ts +1 -1
- package/dist/cli/controllers/ai-cli.controller.d.ts.map +1 -1
- package/dist/cli/controllers/ai-cli.controller.js +1 -1
- package/dist/cli/controllers/ai-cli.controller.js.map +1 -1
- package/dist/cli/workspace.service.js +1 -1
- package/dist/cli/workspace.service.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/skill/controllers/skill.controller.d.ts +33 -0
- package/dist/skill/controllers/skill.controller.d.ts.map +1 -0
- package/dist/skill/controllers/skill.controller.js +264 -0
- package/dist/skill/controllers/skill.controller.js.map +1 -0
- package/dist/skill/entities/octo-skill.entity.d.ts +22 -0
- package/dist/skill/entities/octo-skill.entity.d.ts.map +1 -0
- package/dist/skill/entities/octo-skill.entity.js +91 -0
- package/dist/skill/entities/octo-skill.entity.js.map +1 -0
- package/dist/skill/index.d.ts +7 -0
- package/dist/skill/index.d.ts.map +1 -0
- package/dist/skill/index.js +17 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/skill/services/skill-generator.service.d.ts +47 -0
- package/dist/skill/services/skill-generator.service.d.ts.map +1 -0
- package/dist/skill/services/skill-generator.service.js +232 -0
- package/dist/skill/services/skill-generator.service.js.map +1 -0
- package/dist/skill/services/skill-installer.service.d.ts +38 -0
- package/dist/skill/services/skill-installer.service.d.ts.map +1 -0
- package/dist/skill/services/skill-installer.service.js +150 -0
- package/dist/skill/services/skill-installer.service.js.map +1 -0
- package/dist/skill/services/skill-registry.service.d.ts +60 -0
- package/dist/skill/services/skill-registry.service.d.ts.map +1 -0
- package/dist/skill/services/skill-registry.service.js +147 -0
- package/dist/skill/services/skill-registry.service.js.map +1 -0
- package/dist/skill/types.d.ts +45 -0
- package/dist/skill/types.d.ts.map +1 -0
- package/dist/skill/types.js +6 -0
- package/dist/skill/types.js.map +1 -0
- package/package.json +4 -4
- package/web/components/SkillCard.tsx +139 -0
- package/web/components/SkillEditorDialog.tsx +77 -0
- package/web/components/SkillInstallDialog.tsx +134 -0
- package/web/index.ts +2 -0
- package/web/manifest.ts +1 -0
- package/web/messages/en-US.json +53 -0
- package/web/messages/zh-CN.json +53 -0
- package/web/pages/SkillsPage.tsx +206 -0
- package/web/services/skill-service.ts +89 -0
- package/dist/controllers/agent.controller.d.ts +0 -13
- package/dist/controllers/agent.controller.d.ts.map +0 -1
- package/dist/controllers/agent.controller.js +0 -117
- package/dist/controllers/agent.controller.js.map +0 -1
- package/dist/controllers/capability.controller.d.ts +0 -16
- package/dist/controllers/capability.controller.d.ts.map +0 -1
- package/dist/controllers/capability.controller.js +0 -108
- package/dist/controllers/capability.controller.js.map +0 -1
- package/dist/controllers/client.controller.d.ts +0 -10
- package/dist/controllers/client.controller.d.ts.map +0 -1
- package/dist/controllers/client.controller.js +0 -79
- package/dist/controllers/client.controller.js.map +0 -1
- package/dist/controllers/execution.controller.d.ts +0 -11
- package/dist/controllers/execution.controller.d.ts.map +0 -1
- package/dist/controllers/execution.controller.js +0 -50
- package/dist/controllers/execution.controller.js.map +0 -1
- package/dist/controllers/index.d.ts +0 -5
- package/dist/controllers/index.d.ts.map +0 -1
- package/dist/controllers/index.js +0 -12
- package/dist/controllers/index.js.map +0 -1
- package/dist/entities/agent-binding.entity.d.ts +0 -17
- package/dist/entities/agent-binding.entity.d.ts.map +0 -1
- package/dist/entities/agent-binding.entity.js +0 -64
- package/dist/entities/agent-binding.entity.js.map +0 -1
- package/dist/entities/agent-definition.entity.d.ts +0 -17
- package/dist/entities/agent-definition.entity.d.ts.map +0 -1
- package/dist/entities/agent-definition.entity.js +0 -70
- package/dist/entities/agent-definition.entity.js.map +0 -1
- package/dist/entities/agent-execution.entity.d.ts +0 -23
- package/dist/entities/agent-execution.entity.d.ts.map +0 -1
- package/dist/entities/agent-execution.entity.js +0 -93
- package/dist/entities/agent-execution.entity.js.map +0 -1
- package/dist/entities/agent-instance.entity.d.ts +0 -19
- package/dist/entities/agent-instance.entity.d.ts.map +0 -1
- package/dist/entities/agent-instance.entity.js +0 -76
- package/dist/entities/agent-instance.entity.js.map +0 -1
- package/dist/entities/capability-definition.entity.d.ts +0 -20
- package/dist/entities/capability-definition.entity.d.ts.map +0 -1
- package/dist/entities/capability-definition.entity.js +0 -77
- package/dist/entities/capability-definition.entity.js.map +0 -1
- package/dist/entities/client-registration.entity.d.ts +0 -19
- package/dist/entities/client-registration.entity.d.ts.map +0 -1
- package/dist/entities/client-registration.entity.js +0 -79
- package/dist/entities/client-registration.entity.js.map +0 -1
- package/dist/entities/index.d.ts +0 -7
- package/dist/entities/index.d.ts.map +0 -1
- package/dist/entities/index.js +0 -16
- package/dist/entities/index.js.map +0 -1
- package/dist/services/agent.service.d.ts +0 -23
- package/dist/services/agent.service.d.ts.map +0 -1
- package/dist/services/agent.service.js +0 -76
- package/dist/services/agent.service.js.map +0 -1
- package/dist/services/capability-router.service.d.ts +0 -45
- package/dist/services/capability-router.service.d.ts.map +0 -1
- package/dist/services/capability-router.service.js +0 -120
- package/dist/services/capability-router.service.js.map +0 -1
- package/dist/services/client-registration.service.d.ts +0 -27
- package/dist/services/client-registration.service.d.ts.map +0 -1
- package/dist/services/client-registration.service.js +0 -83
- package/dist/services/client-registration.service.js.map +0 -1
- package/dist/services/index.d.ts +0 -5
- package/dist/services/index.d.ts.map +0 -1
- package/dist/services/index.js +0 -12
- package/dist/services/index.js.map +0 -1
- package/dist/services/sync-bridge.service.d.ts +0 -41
- package/dist/services/sync-bridge.service.d.ts.map +0 -1
- package/dist/services/sync-bridge.service.js +0 -118
- package/dist/services/sync-bridge.service.js.map +0 -1
package/web/messages/en-US.json
CHANGED
|
@@ -77,5 +77,58 @@
|
|
|
77
77
|
"pullFailed": "Pull failed"
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
+
},
|
|
81
|
+
"aiSkills": {
|
|
82
|
+
"title": "AI Skills",
|
|
83
|
+
"description": "Manage SKILL.md files generated from system APIs, install to Claude Code, Cursor, and more",
|
|
84
|
+
"empty": "No skills yet. Click the button below to generate.",
|
|
85
|
+
"tabs": {
|
|
86
|
+
"all": "All",
|
|
87
|
+
"enabled": "Enabled",
|
|
88
|
+
"installed": "Installed"
|
|
89
|
+
},
|
|
90
|
+
"status": {
|
|
91
|
+
"enabled": "Enabled",
|
|
92
|
+
"disabled": "Disabled"
|
|
93
|
+
},
|
|
94
|
+
"meta": {
|
|
95
|
+
"source": "Source",
|
|
96
|
+
"edited": "Edited"
|
|
97
|
+
},
|
|
98
|
+
"actions": {
|
|
99
|
+
"generate": "Generate Skills",
|
|
100
|
+
"install": "Install",
|
|
101
|
+
"edit": "Edit",
|
|
102
|
+
"enable": "Enable",
|
|
103
|
+
"disable": "Disable",
|
|
104
|
+
"delete": "Delete"
|
|
105
|
+
},
|
|
106
|
+
"installDialog": {
|
|
107
|
+
"title": "Install Skill",
|
|
108
|
+
"description": "Select AI tools to install {name}",
|
|
109
|
+
"noTargets": "No installed AI tools detected",
|
|
110
|
+
"apiKeyNote": "An API Key will be auto-created and embedded in the Skill file. AI tools can call the API directly."
|
|
111
|
+
},
|
|
112
|
+
"editor": {
|
|
113
|
+
"title": "Edit {name}",
|
|
114
|
+
"description": "Modify SKILL.md content. Saving marks it as 'Edited' to prevent auto-regeneration overwrite."
|
|
115
|
+
},
|
|
116
|
+
"toast": {
|
|
117
|
+
"loadFailed": "Failed to load skills",
|
|
118
|
+
"generateDone": "Generation complete: {created} created, {updated} updated",
|
|
119
|
+
"generateFailed": "Generation failed",
|
|
120
|
+
"installed": "Installed to {targets}",
|
|
121
|
+
"installFailed": "Installation failed",
|
|
122
|
+
"installPartial": "Partial installation failure: {failed}",
|
|
123
|
+
"apiKeyCreated": "API Key auto-created",
|
|
124
|
+
"saved": "Saved",
|
|
125
|
+
"saveFailed": "Save failed",
|
|
126
|
+
"toggleFailed": "Operation failed",
|
|
127
|
+
"deleted": "Deleted",
|
|
128
|
+
"deleteFailed": "Delete failed"
|
|
129
|
+
},
|
|
130
|
+
"pages": {
|
|
131
|
+
"skills": "AI Skills"
|
|
132
|
+
}
|
|
80
133
|
}
|
|
81
134
|
}
|
package/web/messages/zh-CN.json
CHANGED
|
@@ -77,5 +77,58 @@
|
|
|
77
77
|
"pullFailed": "拉取失败"
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
+
},
|
|
81
|
+
"aiSkills": {
|
|
82
|
+
"title": "AI Skills",
|
|
83
|
+
"description": "管理系统 API 生成的 Skill 文件,安装到 Claude Code、Cursor 等 AI 工具",
|
|
84
|
+
"empty": "暂无 Skill,点击下方按钮生成",
|
|
85
|
+
"tabs": {
|
|
86
|
+
"all": "全部",
|
|
87
|
+
"enabled": "已启用",
|
|
88
|
+
"installed": "已安装"
|
|
89
|
+
},
|
|
90
|
+
"status": {
|
|
91
|
+
"enabled": "已启用",
|
|
92
|
+
"disabled": "已禁用"
|
|
93
|
+
},
|
|
94
|
+
"meta": {
|
|
95
|
+
"source": "来源",
|
|
96
|
+
"edited": "已编辑"
|
|
97
|
+
},
|
|
98
|
+
"actions": {
|
|
99
|
+
"generate": "生成 Skills",
|
|
100
|
+
"install": "安装",
|
|
101
|
+
"edit": "编辑",
|
|
102
|
+
"enable": "启用",
|
|
103
|
+
"disable": "禁用",
|
|
104
|
+
"delete": "删除"
|
|
105
|
+
},
|
|
106
|
+
"installDialog": {
|
|
107
|
+
"title": "安装 Skill",
|
|
108
|
+
"description": "选择要安装 {name} 的 AI 工具",
|
|
109
|
+
"noTargets": "未检测到已安装的 AI 工具",
|
|
110
|
+
"apiKeyNote": "安装时会自动创建 API Key 并写入 Skill 文件,AI 工具可直接调用 API。"
|
|
111
|
+
},
|
|
112
|
+
"editor": {
|
|
113
|
+
"title": "编辑 {name}",
|
|
114
|
+
"description": "修改 SKILL.md 内容。保存后将标记为「已编辑」,自动生成不会覆盖。"
|
|
115
|
+
},
|
|
116
|
+
"toast": {
|
|
117
|
+
"loadFailed": "加载 Skill 列表失败",
|
|
118
|
+
"generateDone": "生成完成:{created} 个新建,{updated} 个更新",
|
|
119
|
+
"generateFailed": "生成失败",
|
|
120
|
+
"installed": "已安装到 {targets}",
|
|
121
|
+
"installFailed": "安装失败",
|
|
122
|
+
"installPartial": "部分安装失败:{failed}",
|
|
123
|
+
"apiKeyCreated": "已自动创建 API Key",
|
|
124
|
+
"saved": "已保存",
|
|
125
|
+
"saveFailed": "保存失败",
|
|
126
|
+
"toggleFailed": "操作失败",
|
|
127
|
+
"deleted": "已删除",
|
|
128
|
+
"deleteFailed": "删除失败"
|
|
129
|
+
},
|
|
130
|
+
"pages": {
|
|
131
|
+
"skills": "AI Skills"
|
|
132
|
+
}
|
|
80
133
|
}
|
|
81
134
|
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect, useCallback } from 'react'
|
|
4
|
+
import { useTranslations } from 'next-intl'
|
|
5
|
+
import { toast } from 'sonner'
|
|
6
|
+
import {
|
|
7
|
+
RefreshCw,
|
|
8
|
+
Plus,
|
|
9
|
+
Loader2,
|
|
10
|
+
Sparkles,
|
|
11
|
+
} from 'lucide-react'
|
|
12
|
+
|
|
13
|
+
import { PageHeader } from '@octo-cyber/ui/components/shared/page-header'
|
|
14
|
+
import { Button } from '@octo-cyber/ui/components/ui/button'
|
|
15
|
+
import { Tabs, TabsList, TabsTrigger } from '@octo-cyber/ui/components/ui/tabs'
|
|
16
|
+
|
|
17
|
+
import { skillService } from '../services/skill-service'
|
|
18
|
+
import type { SkillInfo, SkillTargetInfo } from '../services/skill-service'
|
|
19
|
+
import SkillCard from '../components/SkillCard'
|
|
20
|
+
import SkillInstallDialog from '../components/SkillInstallDialog'
|
|
21
|
+
import SkillEditorDialog from '../components/SkillEditorDialog'
|
|
22
|
+
|
|
23
|
+
type TabFilter = 'all' | 'enabled' | 'installed'
|
|
24
|
+
|
|
25
|
+
export default function SkillsPage() {
|
|
26
|
+
const t = useTranslations('aiSkills')
|
|
27
|
+
const tc = useTranslations('common')
|
|
28
|
+
|
|
29
|
+
const [skills, setSkills] = useState<SkillInfo[]>([])
|
|
30
|
+
const [targets, setTargets] = useState<SkillTargetInfo[]>([])
|
|
31
|
+
const [loading, setLoading] = useState(true)
|
|
32
|
+
const [generating, setGenerating] = useState(false)
|
|
33
|
+
const [tab, setTab] = useState<TabFilter>('all')
|
|
34
|
+
|
|
35
|
+
// Dialog states
|
|
36
|
+
const [installSkill, setInstallSkill] = useState<SkillInfo | null>(null)
|
|
37
|
+
const [editSkill, setEditSkill] = useState<SkillInfo | null>(null)
|
|
38
|
+
|
|
39
|
+
const loadData = useCallback(async () => {
|
|
40
|
+
setLoading(true)
|
|
41
|
+
try {
|
|
42
|
+
const [skillList, targetList] = await Promise.all([
|
|
43
|
+
skillService.list(),
|
|
44
|
+
skillService.getTargets(),
|
|
45
|
+
])
|
|
46
|
+
setSkills(skillList)
|
|
47
|
+
setTargets(targetList)
|
|
48
|
+
} catch {
|
|
49
|
+
toast.error(t('toast.loadFailed'))
|
|
50
|
+
} finally {
|
|
51
|
+
setLoading(false)
|
|
52
|
+
}
|
|
53
|
+
}, [t])
|
|
54
|
+
|
|
55
|
+
useEffect(() => { loadData() }, [loadData])
|
|
56
|
+
|
|
57
|
+
const handleGenerate = useCallback(async () => {
|
|
58
|
+
setGenerating(true)
|
|
59
|
+
try {
|
|
60
|
+
const result = await skillService.generate()
|
|
61
|
+
toast.success(t('toast.generateDone', {
|
|
62
|
+
created: result.created.length,
|
|
63
|
+
updated: result.updated.length,
|
|
64
|
+
}))
|
|
65
|
+
await loadData()
|
|
66
|
+
} catch {
|
|
67
|
+
toast.error(t('toast.generateFailed'))
|
|
68
|
+
} finally {
|
|
69
|
+
setGenerating(false)
|
|
70
|
+
}
|
|
71
|
+
}, [t, loadData])
|
|
72
|
+
|
|
73
|
+
const handleToggle = useCallback(async (id: string) => {
|
|
74
|
+
try {
|
|
75
|
+
await skillService.toggle(id)
|
|
76
|
+
await loadData()
|
|
77
|
+
} catch {
|
|
78
|
+
toast.error(t('toast.toggleFailed'))
|
|
79
|
+
}
|
|
80
|
+
}, [t, loadData])
|
|
81
|
+
|
|
82
|
+
const handleDelete = useCallback(async (id: string) => {
|
|
83
|
+
try {
|
|
84
|
+
await skillService.deleteSkill(id)
|
|
85
|
+
toast.success(t('toast.deleted'))
|
|
86
|
+
await loadData()
|
|
87
|
+
} catch {
|
|
88
|
+
toast.error(t('toast.deleteFailed'))
|
|
89
|
+
}
|
|
90
|
+
}, [t, loadData])
|
|
91
|
+
|
|
92
|
+
const handleInstallDone = useCallback(() => {
|
|
93
|
+
setInstallSkill(null)
|
|
94
|
+
loadData()
|
|
95
|
+
}, [loadData])
|
|
96
|
+
|
|
97
|
+
const handleEditSave = useCallback(async (id: string, content: string) => {
|
|
98
|
+
try {
|
|
99
|
+
await skillService.update(id, { content })
|
|
100
|
+
toast.success(t('toast.saved'))
|
|
101
|
+
setEditSkill(null)
|
|
102
|
+
await loadData()
|
|
103
|
+
} catch {
|
|
104
|
+
toast.error(t('toast.saveFailed'))
|
|
105
|
+
}
|
|
106
|
+
}, [t, loadData])
|
|
107
|
+
|
|
108
|
+
// Filter skills by tab
|
|
109
|
+
const filtered = skills.filter((s) => {
|
|
110
|
+
if (tab === 'enabled') return s.isEnabled
|
|
111
|
+
if (tab === 'installed') return s.installedTargets.length > 0
|
|
112
|
+
return true
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<div className="space-y-6">
|
|
117
|
+
<PageHeader title={t('title')} description={t('description')}>
|
|
118
|
+
<Button
|
|
119
|
+
variant="outline"
|
|
120
|
+
size="sm"
|
|
121
|
+
onClick={handleGenerate}
|
|
122
|
+
disabled={generating}
|
|
123
|
+
>
|
|
124
|
+
{generating ? (
|
|
125
|
+
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
126
|
+
) : (
|
|
127
|
+
<Sparkles className="mr-2 h-4 w-4" />
|
|
128
|
+
)}
|
|
129
|
+
{t('actions.generate')}
|
|
130
|
+
</Button>
|
|
131
|
+
<Button
|
|
132
|
+
variant="outline"
|
|
133
|
+
size="sm"
|
|
134
|
+
onClick={loadData}
|
|
135
|
+
disabled={loading}
|
|
136
|
+
>
|
|
137
|
+
<RefreshCw className="mr-2 h-4 w-4" />
|
|
138
|
+
{tc('refresh')}
|
|
139
|
+
</Button>
|
|
140
|
+
</PageHeader>
|
|
141
|
+
|
|
142
|
+
<Tabs value={tab} onValueChange={(v) => setTab(v as TabFilter)}>
|
|
143
|
+
<TabsList>
|
|
144
|
+
<TabsTrigger value="all">{t('tabs.all')}</TabsTrigger>
|
|
145
|
+
<TabsTrigger value="enabled">{t('tabs.enabled')}</TabsTrigger>
|
|
146
|
+
<TabsTrigger value="installed">{t('tabs.installed')}</TabsTrigger>
|
|
147
|
+
</TabsList>
|
|
148
|
+
</Tabs>
|
|
149
|
+
|
|
150
|
+
{loading ? (
|
|
151
|
+
<div className="flex items-center justify-center py-12">
|
|
152
|
+
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
|
|
153
|
+
</div>
|
|
154
|
+
) : filtered.length === 0 ? (
|
|
155
|
+
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
|
|
156
|
+
<Sparkles className="mb-2 h-8 w-8" />
|
|
157
|
+
<p>{t('empty')}</p>
|
|
158
|
+
<Button
|
|
159
|
+
variant="outline"
|
|
160
|
+
size="sm"
|
|
161
|
+
className="mt-4"
|
|
162
|
+
onClick={handleGenerate}
|
|
163
|
+
>
|
|
164
|
+
<Plus className="mr-2 h-4 w-4" />
|
|
165
|
+
{t('actions.generate')}
|
|
166
|
+
</Button>
|
|
167
|
+
</div>
|
|
168
|
+
) : (
|
|
169
|
+
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
170
|
+
{filtered.map((skill) => (
|
|
171
|
+
<SkillCard
|
|
172
|
+
key={skill.id}
|
|
173
|
+
skill={skill}
|
|
174
|
+
targets={targets}
|
|
175
|
+
onInstall={() => setInstallSkill(skill)}
|
|
176
|
+
onEdit={() => setEditSkill(skill)}
|
|
177
|
+
onToggle={() => handleToggle(skill.id)}
|
|
178
|
+
onDelete={() => handleDelete(skill.id)}
|
|
179
|
+
/>
|
|
180
|
+
))}
|
|
181
|
+
</div>
|
|
182
|
+
)}
|
|
183
|
+
|
|
184
|
+
{/* Install Dialog */}
|
|
185
|
+
{installSkill && (
|
|
186
|
+
<SkillInstallDialog
|
|
187
|
+
skill={installSkill}
|
|
188
|
+
targets={targets}
|
|
189
|
+
open={!!installSkill}
|
|
190
|
+
onOpenChange={(open) => { if (!open) setInstallSkill(null) }}
|
|
191
|
+
onDone={handleInstallDone}
|
|
192
|
+
/>
|
|
193
|
+
)}
|
|
194
|
+
|
|
195
|
+
{/* Editor Dialog */}
|
|
196
|
+
{editSkill && (
|
|
197
|
+
<SkillEditorDialog
|
|
198
|
+
skill={editSkill}
|
|
199
|
+
open={!!editSkill}
|
|
200
|
+
onOpenChange={(open) => { if (!open) setEditSkill(null) }}
|
|
201
|
+
onSave={handleEditSave}
|
|
202
|
+
/>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
)
|
|
206
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { api } from '@octo-cyber/ui/services/api-client'
|
|
2
|
+
import type { ApiResponse } from '@octo-cyber/ui/types/common'
|
|
3
|
+
|
|
4
|
+
export interface SkillInfo {
|
|
5
|
+
id: string
|
|
6
|
+
name: string
|
|
7
|
+
description: string
|
|
8
|
+
sourceModule: string
|
|
9
|
+
sourceType: 'module' | 'custom'
|
|
10
|
+
content: string
|
|
11
|
+
version: string
|
|
12
|
+
isEnabled: boolean
|
|
13
|
+
isEdited: boolean
|
|
14
|
+
installTargets: string | null
|
|
15
|
+
installedTargets: string[]
|
|
16
|
+
createdAt: string
|
|
17
|
+
updatedAt: string
|
|
18
|
+
lastInstalledAt: string | null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SkillTargetInfo {
|
|
22
|
+
id: string
|
|
23
|
+
name: string
|
|
24
|
+
skillsDir: string
|
|
25
|
+
detectDir: string
|
|
26
|
+
isInstalled: boolean
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface GenerateResult {
|
|
30
|
+
created: string[]
|
|
31
|
+
updated: string[]
|
|
32
|
+
skipped: string[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface InstallResult {
|
|
36
|
+
installed: string[]
|
|
37
|
+
failed: Array<{ target: string; error: string }>
|
|
38
|
+
apiKeyCreated: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const skillService = {
|
|
42
|
+
async list(): Promise<SkillInfo[]> {
|
|
43
|
+
const res = await api.get<ApiResponse<SkillInfo[]>>('/api/v1/skills')
|
|
44
|
+
return res.data
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
async getById(id: string): Promise<SkillInfo> {
|
|
48
|
+
const res = await api.get<ApiResponse<SkillInfo>>(`/api/v1/skills/${id}`)
|
|
49
|
+
return res.data
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
async getTargets(): Promise<SkillTargetInfo[]> {
|
|
53
|
+
const res = await api.get<ApiResponse<SkillTargetInfo[]>>('/api/v1/skills/targets')
|
|
54
|
+
return res.data
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
async generate(baseUrl?: string): Promise<GenerateResult> {
|
|
58
|
+
const res = await api.post<ApiResponse<GenerateResult>>('/api/v1/skills/generate', { baseUrl })
|
|
59
|
+
return res.data
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
async create(data: { name: string; description: string; content: string }): Promise<SkillInfo> {
|
|
63
|
+
const res = await api.post<ApiResponse<SkillInfo>>('/api/v1/skills', data)
|
|
64
|
+
return res.data
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
async update(id: string, data: { name?: string; description?: string; content?: string }): Promise<SkillInfo> {
|
|
68
|
+
const res = await api.put<ApiResponse<SkillInfo>>(`/api/v1/skills/${id}`, data)
|
|
69
|
+
return res.data
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
async toggle(id: string): Promise<SkillInfo> {
|
|
73
|
+
const res = await api.put<ApiResponse<SkillInfo>>(`/api/v1/skills/${id}/toggle`)
|
|
74
|
+
return res.data
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
async deleteSkill(id: string): Promise<void> {
|
|
78
|
+
await api.delete<ApiResponse<null>>(`/api/v1/skills/${id}`)
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
async install(id: string, targets: string[], baseUrl?: string): Promise<InstallResult> {
|
|
82
|
+
const res = await api.post<ApiResponse<InstallResult>>(`/api/v1/skills/${id}/install`, { targets, baseUrl })
|
|
83
|
+
return res.data
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
async uninstall(id: string, targets: string[]): Promise<void> {
|
|
87
|
+
await api.post<ApiResponse<unknown>>(`/api/v1/skills/${id}/uninstall`, { targets })
|
|
88
|
+
},
|
|
89
|
+
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Request, Response } from '@octo/core';
|
|
2
|
-
export declare class AgentController {
|
|
3
|
-
private agentService;
|
|
4
|
-
listDefinitions(_req: Request, res: Response): Promise<void>;
|
|
5
|
-
createDefinition(req: Request, res: Response): Promise<void>;
|
|
6
|
-
getDefinition(req: Request, res: Response): Promise<void>;
|
|
7
|
-
updateDefinition(req: Request, res: Response): Promise<void>;
|
|
8
|
-
deleteDefinition(req: Request, res: Response): Promise<void>;
|
|
9
|
-
listInstances(req: Request, res: Response): Promise<void>;
|
|
10
|
-
getInstance(req: Request, res: Response): Promise<void>;
|
|
11
|
-
createInstance(req: Request, res: Response): Promise<void>;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=agent.controller.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/agent.controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGpD,qBACa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAA+B;IAG7C,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzD,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5D,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5D,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzD,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvD,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAIjE"}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AgentController = void 0;
|
|
13
|
-
const core_1 = require("@octo/core");
|
|
14
|
-
const agent_service_js_1 = require("../services/agent.service.js");
|
|
15
|
-
let AgentController = class AgentController {
|
|
16
|
-
agentService = core_1.Container.get(agent_service_js_1.AgentService);
|
|
17
|
-
async listDefinitions(_req, res) {
|
|
18
|
-
const definitions = await this.agentService.findAllDefinitions();
|
|
19
|
-
res.json(core_1.ApiResponse.ok(definitions));
|
|
20
|
-
}
|
|
21
|
-
async createDefinition(req, res) {
|
|
22
|
-
const definition = await this.agentService.createDefinition(req.body);
|
|
23
|
-
res.status(201).json(core_1.ApiResponse.ok(definition, 'Agent definition created'));
|
|
24
|
-
}
|
|
25
|
-
async getDefinition(req, res) {
|
|
26
|
-
const def = await this.agentService.findDefinitionById(Number(req.params.id));
|
|
27
|
-
if (!def)
|
|
28
|
-
throw core_1.AppError.notFound('Agent definition not found');
|
|
29
|
-
res.json(core_1.ApiResponse.ok(def));
|
|
30
|
-
}
|
|
31
|
-
async updateDefinition(req, res) {
|
|
32
|
-
const def = await this.agentService.updateDefinition(Number(req.params.id), req.body);
|
|
33
|
-
if (!def)
|
|
34
|
-
throw core_1.AppError.notFound('Agent definition not found');
|
|
35
|
-
res.json(core_1.ApiResponse.ok(def));
|
|
36
|
-
}
|
|
37
|
-
async deleteDefinition(req, res) {
|
|
38
|
-
const deleted = await this.agentService.deleteDefinition(Number(req.params.id));
|
|
39
|
-
if (!deleted)
|
|
40
|
-
throw core_1.AppError.notFound('Agent definition not found');
|
|
41
|
-
res.json(core_1.ApiResponse.ok(null, 'Agent definition deleted'));
|
|
42
|
-
}
|
|
43
|
-
async listInstances(req, res) {
|
|
44
|
-
const clientId = req.query.clientId;
|
|
45
|
-
if (clientId) {
|
|
46
|
-
const instances = await this.agentService.findInstancesByClient(clientId);
|
|
47
|
-
res.json(core_1.ApiResponse.ok(instances));
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
const instances = await this.agentService.findOnlineInstances();
|
|
51
|
-
res.json(core_1.ApiResponse.ok(instances));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
async getInstance(req, res) {
|
|
55
|
-
const instance = await this.agentService.findInstanceById(Number(req.params.id));
|
|
56
|
-
if (!instance)
|
|
57
|
-
throw core_1.AppError.notFound('Agent instance not found');
|
|
58
|
-
res.json(core_1.ApiResponse.ok(instance));
|
|
59
|
-
}
|
|
60
|
-
async createInstance(req, res) {
|
|
61
|
-
const instance = await this.agentService.createInstance(req.body);
|
|
62
|
-
res.status(201).json(core_1.ApiResponse.ok(instance, 'Agent instance created'));
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
exports.AgentController = AgentController;
|
|
66
|
-
__decorate([
|
|
67
|
-
(0, core_1.Get)('/definitions'),
|
|
68
|
-
__metadata("design:type", Function),
|
|
69
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
70
|
-
__metadata("design:returntype", Promise)
|
|
71
|
-
], AgentController.prototype, "listDefinitions", null);
|
|
72
|
-
__decorate([
|
|
73
|
-
(0, core_1.Post)('/definitions'),
|
|
74
|
-
__metadata("design:type", Function),
|
|
75
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
76
|
-
__metadata("design:returntype", Promise)
|
|
77
|
-
], AgentController.prototype, "createDefinition", null);
|
|
78
|
-
__decorate([
|
|
79
|
-
(0, core_1.Get)('/definitions/:id'),
|
|
80
|
-
__metadata("design:type", Function),
|
|
81
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
82
|
-
__metadata("design:returntype", Promise)
|
|
83
|
-
], AgentController.prototype, "getDefinition", null);
|
|
84
|
-
__decorate([
|
|
85
|
-
(0, core_1.Put)('/definitions/:id'),
|
|
86
|
-
__metadata("design:type", Function),
|
|
87
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
88
|
-
__metadata("design:returntype", Promise)
|
|
89
|
-
], AgentController.prototype, "updateDefinition", null);
|
|
90
|
-
__decorate([
|
|
91
|
-
(0, core_1.Delete)('/definitions/:id'),
|
|
92
|
-
__metadata("design:type", Function),
|
|
93
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
94
|
-
__metadata("design:returntype", Promise)
|
|
95
|
-
], AgentController.prototype, "deleteDefinition", null);
|
|
96
|
-
__decorate([
|
|
97
|
-
(0, core_1.Get)('/instances'),
|
|
98
|
-
__metadata("design:type", Function),
|
|
99
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
100
|
-
__metadata("design:returntype", Promise)
|
|
101
|
-
], AgentController.prototype, "listInstances", null);
|
|
102
|
-
__decorate([
|
|
103
|
-
(0, core_1.Get)('/instances/:id'),
|
|
104
|
-
__metadata("design:type", Function),
|
|
105
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
106
|
-
__metadata("design:returntype", Promise)
|
|
107
|
-
], AgentController.prototype, "getInstance", null);
|
|
108
|
-
__decorate([
|
|
109
|
-
(0, core_1.Post)('/instances'),
|
|
110
|
-
__metadata("design:type", Function),
|
|
111
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
112
|
-
__metadata("design:returntype", Promise)
|
|
113
|
-
], AgentController.prototype, "createInstance", null);
|
|
114
|
-
exports.AgentController = AgentController = __decorate([
|
|
115
|
-
(0, core_1.Controller)('/api/agents')
|
|
116
|
-
], AgentController);
|
|
117
|
-
//# sourceMappingURL=agent.controller.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent.controller.js","sourceRoot":"","sources":["../../src/controllers/agent.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Request, Response } from '@octo/core';
|
|
2
|
-
export declare class CapabilityController {
|
|
3
|
-
private capabilityRouter;
|
|
4
|
-
private syncBridge;
|
|
5
|
-
list(_req: Request, res: Response): Promise<void>;
|
|
6
|
-
create(req: Request, res: Response): Promise<void>;
|
|
7
|
-
update(req: Request, res: Response): Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* Execute a capability — routes to an available agent instance.
|
|
10
|
-
* POST /api/capabilities/:code/execute
|
|
11
|
-
*/
|
|
12
|
-
execute(req: Request, res: Response): Promise<void>;
|
|
13
|
-
bind(req: Request, res: Response): Promise<void>;
|
|
14
|
-
unbind(req: Request, res: Response): Promise<void>;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=capability.controller.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capability.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/capability.controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAIpD,qBACa,oBAAoB;IAC/B,OAAO,CAAC,gBAAgB,CAA0C;IAClE,OAAO,CAAC,UAAU,CAAoC;IAGhD,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD;;;OAGG;IAEG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBnD,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CASzD"}
|