@skillshub-labs/cli 0.1.17
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/LICENSE +21 -0
- package/README.md +190 -0
- package/bin/skills-hub +1611 -0
- package/lib/core/kit-core.d.ts +56 -0
- package/lib/core/kit-core.mjs +626 -0
- package/lib/core/kit-types.ts +59 -0
- package/lib/core/provider-core.d.ts +134 -0
- package/lib/core/provider-core.mjs +1223 -0
- package/lib/services/kit-service.d.ts +66 -0
- package/lib/services/kit-service.mjs +266 -0
- package/lib/services/provider-service.d.ts +63 -0
- package/lib/services/provider-service.mjs +183 -0
- package/package.json +94 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
KitApplyResult,
|
|
3
|
+
KitLoadoutRecord,
|
|
4
|
+
KitPolicyRecord,
|
|
5
|
+
KitRecord,
|
|
6
|
+
KitSyncMode,
|
|
7
|
+
} from '../core/kit-types'
|
|
8
|
+
|
|
9
|
+
export function normalizeKitMode(value: unknown): KitSyncMode
|
|
10
|
+
export function normalizeLoadoutItems(items: unknown): Array<{
|
|
11
|
+
skillPath: string
|
|
12
|
+
mode: KitSyncMode
|
|
13
|
+
sortOrder: number
|
|
14
|
+
}>
|
|
15
|
+
|
|
16
|
+
export function listKitPolicies(): KitPolicyRecord[]
|
|
17
|
+
export function addKitPolicy(values: {
|
|
18
|
+
name: string
|
|
19
|
+
description?: string
|
|
20
|
+
content: string
|
|
21
|
+
}): KitPolicyRecord
|
|
22
|
+
export function updateKitPolicy(values: {
|
|
23
|
+
id: string
|
|
24
|
+
name?: string
|
|
25
|
+
description?: string
|
|
26
|
+
content?: string
|
|
27
|
+
}): KitPolicyRecord
|
|
28
|
+
export function deleteKitPolicy(id: string): boolean
|
|
29
|
+
|
|
30
|
+
export function listKitLoadouts(): KitLoadoutRecord[]
|
|
31
|
+
export function addKitLoadout(values: {
|
|
32
|
+
name: string
|
|
33
|
+
description?: string
|
|
34
|
+
items: Array<{ skillPath: string; mode?: KitSyncMode; sortOrder?: number }>
|
|
35
|
+
}): KitLoadoutRecord
|
|
36
|
+
export function updateKitLoadout(values: {
|
|
37
|
+
id: string
|
|
38
|
+
name?: string
|
|
39
|
+
description?: string
|
|
40
|
+
items?: Array<{ skillPath: string; mode?: KitSyncMode; sortOrder?: number }>
|
|
41
|
+
}): KitLoadoutRecord
|
|
42
|
+
export function deleteKitLoadout(id: string): boolean
|
|
43
|
+
|
|
44
|
+
export function listKits(): KitRecord[]
|
|
45
|
+
export function addKit(values: {
|
|
46
|
+
name: string
|
|
47
|
+
description?: string
|
|
48
|
+
policyId: string
|
|
49
|
+
loadoutId: string
|
|
50
|
+
}): KitRecord
|
|
51
|
+
export function updateKit(values: {
|
|
52
|
+
id: string
|
|
53
|
+
name?: string
|
|
54
|
+
description?: string
|
|
55
|
+
policyId?: string
|
|
56
|
+
loadoutId?: string
|
|
57
|
+
}): KitRecord
|
|
58
|
+
export function deleteKit(id: string): boolean
|
|
59
|
+
|
|
60
|
+
export function applyKit(values: {
|
|
61
|
+
kitId: string
|
|
62
|
+
projectPath: string
|
|
63
|
+
agentName: string
|
|
64
|
+
mode?: KitSyncMode
|
|
65
|
+
overwriteAgentsMd?: boolean
|
|
66
|
+
}): Promise<KitApplyResult>
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import fs from 'fs-extra'
|
|
2
|
+
import os from 'os'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import {
|
|
5
|
+
addKit as addKitCore,
|
|
6
|
+
addKitLoadout as addKitLoadoutCore,
|
|
7
|
+
addKitPolicy as addKitPolicyCore,
|
|
8
|
+
deleteKit as deleteKitCore,
|
|
9
|
+
deleteKitLoadout as deleteKitLoadoutCore,
|
|
10
|
+
deleteKitPolicy as deleteKitPolicyCore,
|
|
11
|
+
getKitById,
|
|
12
|
+
getKitLoadoutById,
|
|
13
|
+
getKitPolicyById,
|
|
14
|
+
listKitLoadouts as listKitLoadoutsCore,
|
|
15
|
+
listKitPolicies as listKitPoliciesCore,
|
|
16
|
+
listKits as listKitsCore,
|
|
17
|
+
markKitApplied,
|
|
18
|
+
updateKit as updateKitCore,
|
|
19
|
+
updateKitLoadout as updateKitLoadoutCore,
|
|
20
|
+
updateKitPolicy as updateKitPolicyCore,
|
|
21
|
+
} from '../core/kit-core.mjs'
|
|
22
|
+
|
|
23
|
+
const CONFIG_PATH = path.join(os.homedir(), '.skills-hub', 'config.json')
|
|
24
|
+
|
|
25
|
+
function normalizeKitMode(value) {
|
|
26
|
+
return value === 'link' ? 'link' : 'copy'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizeLoadoutItems(items) {
|
|
30
|
+
if (!Array.isArray(items)) {
|
|
31
|
+
throw new Error('Skills package items must be an array.')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const seen = new Set()
|
|
35
|
+
const normalized = []
|
|
36
|
+
|
|
37
|
+
for (const [index, item] of items.entries()) {
|
|
38
|
+
if (!item || typeof item !== 'object' || Array.isArray(item)) continue
|
|
39
|
+
const raw = item
|
|
40
|
+
const skillPath = String(raw.skillPath || '').trim()
|
|
41
|
+
if (!skillPath || seen.has(skillPath)) continue
|
|
42
|
+
|
|
43
|
+
normalized.push({
|
|
44
|
+
skillPath,
|
|
45
|
+
mode: normalizeKitMode(raw.mode),
|
|
46
|
+
sortOrder: Number.isInteger(raw.sortOrder) ? Number(raw.sortOrder) : index,
|
|
47
|
+
})
|
|
48
|
+
seen.add(skillPath)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return normalized
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function readRuntimeConfig() {
|
|
55
|
+
try {
|
|
56
|
+
const raw = await fs.readFile(CONFIG_PATH, 'utf-8')
|
|
57
|
+
if (!raw.trim()) {
|
|
58
|
+
return { projects: [], agents: [] }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const parsed = JSON.parse(raw)
|
|
62
|
+
const projects = Array.isArray(parsed.projects)
|
|
63
|
+
? parsed.projects.map((entry) => String(entry || '').trim()).filter(Boolean)
|
|
64
|
+
: []
|
|
65
|
+
const agents = Array.isArray(parsed.agents)
|
|
66
|
+
? parsed.agents.filter((entry) => entry && typeof entry === 'object' && !Array.isArray(entry))
|
|
67
|
+
: []
|
|
68
|
+
|
|
69
|
+
return { projects, agents }
|
|
70
|
+
} catch {
|
|
71
|
+
return { projects: [], agents: [] }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function atomicWriteText(filePath, content) {
|
|
76
|
+
const dirPath = path.dirname(filePath)
|
|
77
|
+
await fs.ensureDir(dirPath)
|
|
78
|
+
const tempPath = path.join(
|
|
79
|
+
dirPath,
|
|
80
|
+
`.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`
|
|
81
|
+
)
|
|
82
|
+
await fs.writeFile(tempPath, content, 'utf-8')
|
|
83
|
+
await fs.move(tempPath, filePath, { overwrite: true })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function syncSkill(sourcePath, destParentPath, syncMode = 'copy') {
|
|
87
|
+
const skillDirName = path.basename(sourcePath)
|
|
88
|
+
const destPath = path.join(destParentPath, skillDirName)
|
|
89
|
+
|
|
90
|
+
if (sourcePath === destPath) {
|
|
91
|
+
return destPath
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
await fs.ensureDir(destParentPath)
|
|
95
|
+
|
|
96
|
+
if (syncMode === 'link') {
|
|
97
|
+
await fs.remove(destPath)
|
|
98
|
+
await fs.ensureSymlink(sourcePath, destPath)
|
|
99
|
+
return destPath
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const isSymlink = await fs
|
|
103
|
+
.lstat(destPath)
|
|
104
|
+
.then((stat) => stat.isSymbolicLink())
|
|
105
|
+
.catch(() => false)
|
|
106
|
+
|
|
107
|
+
if (isSymlink) {
|
|
108
|
+
await fs.remove(destPath)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await fs.copy(sourcePath, destPath, { overwrite: true, errorOnExist: false })
|
|
112
|
+
return destPath
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function listKitPolicies() {
|
|
116
|
+
return listKitPoliciesCore()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function addKitPolicy(values) {
|
|
120
|
+
return addKitPolicyCore(values)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function updateKitPolicy(values) {
|
|
124
|
+
return updateKitPolicyCore(values)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function deleteKitPolicy(id) {
|
|
128
|
+
return deleteKitPolicyCore(id)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function listKitLoadouts() {
|
|
132
|
+
return listKitLoadoutsCore()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function addKitLoadout(values) {
|
|
136
|
+
return addKitLoadoutCore({
|
|
137
|
+
...values,
|
|
138
|
+
items: normalizeLoadoutItems(values.items || []),
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function updateKitLoadout(values) {
|
|
143
|
+
return updateKitLoadoutCore({
|
|
144
|
+
...values,
|
|
145
|
+
items: values.items === undefined ? undefined : normalizeLoadoutItems(values.items),
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function deleteKitLoadout(id) {
|
|
150
|
+
return deleteKitLoadoutCore(id)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function listKits() {
|
|
154
|
+
return listKitsCore()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function addKit(values) {
|
|
158
|
+
return addKitCore(values)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function updateKit(values) {
|
|
162
|
+
return updateKitCore(values)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function deleteKit(id) {
|
|
166
|
+
return deleteKitCore(id)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function applyKit(values) {
|
|
170
|
+
const kitId = String(values?.kitId || '').trim()
|
|
171
|
+
const projectPath = String(values?.projectPath || '').trim()
|
|
172
|
+
const agentName = String(values?.agentName || '').trim()
|
|
173
|
+
const applyMode = normalizeKitMode(values?.mode)
|
|
174
|
+
const overwriteAgentsMd = values?.overwriteAgentsMd === true
|
|
175
|
+
|
|
176
|
+
if (!kitId) throw new Error('kitId is required')
|
|
177
|
+
if (!projectPath) throw new Error('projectPath is required')
|
|
178
|
+
if (!agentName) throw new Error('agentName is required')
|
|
179
|
+
|
|
180
|
+
const kit = getKitById(kitId)
|
|
181
|
+
if (!kit) throw new Error(`Kit not found: ${kitId}`)
|
|
182
|
+
|
|
183
|
+
const policy = getKitPolicyById(kit.policyId)
|
|
184
|
+
if (!policy) throw new Error(`AGENTS.md not found: ${kit.policyId}`)
|
|
185
|
+
|
|
186
|
+
const loadout = getKitLoadoutById(kit.loadoutId)
|
|
187
|
+
if (!loadout) throw new Error(`Skills package not found: ${kit.loadoutId}`)
|
|
188
|
+
|
|
189
|
+
const config = await readRuntimeConfig()
|
|
190
|
+
const projectExists = config.projects.includes(projectPath)
|
|
191
|
+
if (!projectExists) {
|
|
192
|
+
throw new Error('Target project is not registered in Skills Hub.')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const targetAgent = config.agents.find((agent) => agent.enabled && agent.name === agentName)
|
|
196
|
+
if (!targetAgent) {
|
|
197
|
+
throw new Error('Target agent is not enabled or not found.')
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const targetSkillParent = path.join(projectPath, targetAgent.projectPath)
|
|
201
|
+
const loadoutResults = []
|
|
202
|
+
|
|
203
|
+
for (const item of loadout.items) {
|
|
204
|
+
try {
|
|
205
|
+
const destination = await syncSkill(item.skillPath, targetSkillParent, applyMode)
|
|
206
|
+
loadoutResults.push({
|
|
207
|
+
skillPath: item.skillPath,
|
|
208
|
+
mode: applyMode,
|
|
209
|
+
destination,
|
|
210
|
+
status: 'success',
|
|
211
|
+
})
|
|
212
|
+
} catch (error) {
|
|
213
|
+
loadoutResults.push({
|
|
214
|
+
skillPath: item.skillPath,
|
|
215
|
+
mode: applyMode,
|
|
216
|
+
destination: path.join(targetSkillParent, path.basename(item.skillPath)),
|
|
217
|
+
status: 'failed',
|
|
218
|
+
error: error instanceof Error ? error.message : String(error),
|
|
219
|
+
})
|
|
220
|
+
throw new Error(`Failed to sync skill: ${item.skillPath}`)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const policyPath = path.join(projectPath, 'AGENTS.md')
|
|
225
|
+
const policyExists = await fs.pathExists(policyPath)
|
|
226
|
+
if (policyExists && !overwriteAgentsMd) {
|
|
227
|
+
throw new Error(`AGENTS_MD_EXISTS::${policyPath}`)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const policyContent = policy.content.endsWith('\n') ? policy.content : `${policy.content}\n`
|
|
231
|
+
await atomicWriteText(policyPath, policyContent)
|
|
232
|
+
|
|
233
|
+
const applied = markKitApplied({ id: kitId, projectPath, agentName })
|
|
234
|
+
if (!applied) {
|
|
235
|
+
throw new Error('Failed to record kit application metadata.')
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
kitId,
|
|
240
|
+
kitName: applied.name,
|
|
241
|
+
policyPath,
|
|
242
|
+
projectPath,
|
|
243
|
+
agentName,
|
|
244
|
+
appliedAt: applied.lastAppliedAt || Date.now(),
|
|
245
|
+
overwroteAgentsMd: policyExists && overwriteAgentsMd,
|
|
246
|
+
loadoutResults,
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export {
|
|
251
|
+
normalizeKitMode,
|
|
252
|
+
normalizeLoadoutItems,
|
|
253
|
+
listKitPolicies,
|
|
254
|
+
addKitPolicy,
|
|
255
|
+
updateKitPolicy,
|
|
256
|
+
deleteKitPolicy,
|
|
257
|
+
listKitLoadouts,
|
|
258
|
+
addKitLoadout,
|
|
259
|
+
updateKitLoadout,
|
|
260
|
+
deleteKitLoadout,
|
|
261
|
+
listKits,
|
|
262
|
+
addKit,
|
|
263
|
+
updateKit,
|
|
264
|
+
deleteKit,
|
|
265
|
+
applyKit,
|
|
266
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AppType,
|
|
3
|
+
ProviderRecord,
|
|
4
|
+
ProviderSwitchResult,
|
|
5
|
+
UniversalProviderApps,
|
|
6
|
+
UniversalProviderModels,
|
|
7
|
+
UniversalProviderRecord,
|
|
8
|
+
} from '../core/provider-types'
|
|
9
|
+
|
|
10
|
+
export const APP_TYPES: AppType[]
|
|
11
|
+
|
|
12
|
+
export function assertAppType(appType: string): asserts appType is AppType
|
|
13
|
+
export function normalizeProviderConfig(config: unknown): Record<string, unknown>
|
|
14
|
+
|
|
15
|
+
export function listProvidersMasked(appType?: string): ProviderRecord[]
|
|
16
|
+
export function getCurrentProviderMasked(appType: string): ProviderRecord | null
|
|
17
|
+
export function getProviderRaw(id: string): ProviderRecord
|
|
18
|
+
export function addProviderRecord(values: {
|
|
19
|
+
appType: string
|
|
20
|
+
name: string
|
|
21
|
+
config: unknown
|
|
22
|
+
}): ProviderRecord
|
|
23
|
+
export function updateProviderRecord(values: {
|
|
24
|
+
id: string
|
|
25
|
+
name?: string
|
|
26
|
+
config?: unknown
|
|
27
|
+
}): ProviderRecord
|
|
28
|
+
export function deleteProviderRecord(id: string): boolean
|
|
29
|
+
export function switchProviderRecord(values: {
|
|
30
|
+
appType: string
|
|
31
|
+
providerId: string
|
|
32
|
+
}): Promise<ProviderSwitchResult>
|
|
33
|
+
export function getLatestProviderBackup(appType: string): unknown
|
|
34
|
+
export function restoreLatestProviderBackup(appType: string): Promise<unknown>
|
|
35
|
+
export function captureProviderFromLiveRecord(values: {
|
|
36
|
+
appType: string
|
|
37
|
+
name: string
|
|
38
|
+
profile?: Record<string, unknown>
|
|
39
|
+
}): Promise<ProviderRecord>
|
|
40
|
+
|
|
41
|
+
export function listUniversalProvidersMasked(): UniversalProviderRecord[]
|
|
42
|
+
export function getUniversalProviderRaw(id: string): UniversalProviderRecord
|
|
43
|
+
export function addUniversalProviderRecord(values: {
|
|
44
|
+
name: string
|
|
45
|
+
baseUrl: string
|
|
46
|
+
apiKey: string
|
|
47
|
+
websiteUrl?: string
|
|
48
|
+
notes?: string
|
|
49
|
+
apps?: Partial<UniversalProviderApps>
|
|
50
|
+
models?: UniversalProviderModels
|
|
51
|
+
}): UniversalProviderRecord
|
|
52
|
+
export function updateUniversalProviderRecord(values: {
|
|
53
|
+
id: string
|
|
54
|
+
name?: string
|
|
55
|
+
baseUrl?: string
|
|
56
|
+
apiKey?: string
|
|
57
|
+
websiteUrl?: string
|
|
58
|
+
notes?: string
|
|
59
|
+
apps?: Partial<UniversalProviderApps>
|
|
60
|
+
models?: UniversalProviderModels
|
|
61
|
+
}): UniversalProviderRecord
|
|
62
|
+
export function deleteUniversalProviderRecord(id: string): boolean
|
|
63
|
+
export function applyUniversalProviderRecord(id: string): ProviderRecord[]
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APP_TYPES,
|
|
3
|
+
addProvider,
|
|
4
|
+
addUniversalProvider,
|
|
5
|
+
applyUniversalProvider,
|
|
6
|
+
captureProviderFromLive,
|
|
7
|
+
deleteProvider,
|
|
8
|
+
deleteUniversalProvider,
|
|
9
|
+
getCurrentProvider,
|
|
10
|
+
getLatestBackup,
|
|
11
|
+
getProviderById,
|
|
12
|
+
getUniversalProviderById,
|
|
13
|
+
listProviders,
|
|
14
|
+
listUniversalProviders,
|
|
15
|
+
maskProvider,
|
|
16
|
+
maskProviders,
|
|
17
|
+
restoreBackup,
|
|
18
|
+
switchProvider,
|
|
19
|
+
updateProvider,
|
|
20
|
+
updateUniversalProvider,
|
|
21
|
+
} from '../core/provider-core.mjs'
|
|
22
|
+
|
|
23
|
+
function assertAppType(appType) {
|
|
24
|
+
if (!APP_TYPES.includes(appType)) {
|
|
25
|
+
throw new Error(`Unsupported app type: ${appType}`)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizeProviderConfig(config) {
|
|
30
|
+
if (typeof config === 'string') {
|
|
31
|
+
const parsed = JSON.parse(config)
|
|
32
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
33
|
+
throw new Error('Provider config must be a JSON object.')
|
|
34
|
+
}
|
|
35
|
+
return parsed
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
39
|
+
throw new Error('Provider config must be an object.')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return config
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function maskUniversalProvider(provider) {
|
|
46
|
+
return {
|
|
47
|
+
...provider,
|
|
48
|
+
apiKey: provider.apiKey.trim() ? `${provider.apiKey.slice(0, 3)}****` : '',
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function listProvidersMasked(appType) {
|
|
53
|
+
if (appType) assertAppType(appType)
|
|
54
|
+
const providers = listProviders(appType)
|
|
55
|
+
return maskProviders(providers)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getCurrentProviderMasked(appType) {
|
|
59
|
+
assertAppType(appType)
|
|
60
|
+
return maskProvider(getCurrentProvider(appType))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getProviderRaw(id) {
|
|
64
|
+
const provider = getProviderById(id)
|
|
65
|
+
if (!provider) {
|
|
66
|
+
throw new Error(`Provider not found: ${id}`)
|
|
67
|
+
}
|
|
68
|
+
return provider
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function addProviderRecord(values) {
|
|
72
|
+
assertAppType(values.appType)
|
|
73
|
+
return maskProvider(
|
|
74
|
+
addProvider({
|
|
75
|
+
appType: values.appType,
|
|
76
|
+
name: values.name,
|
|
77
|
+
config: normalizeProviderConfig(values.config),
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function updateProviderRecord(values) {
|
|
83
|
+
return maskProvider(
|
|
84
|
+
updateProvider({
|
|
85
|
+
id: values.id,
|
|
86
|
+
name: values.name,
|
|
87
|
+
config: values.config === undefined ? undefined : normalizeProviderConfig(values.config),
|
|
88
|
+
})
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function deleteProviderRecord(id) {
|
|
93
|
+
return deleteProvider(id)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function switchProviderRecord(values) {
|
|
97
|
+
assertAppType(values.appType)
|
|
98
|
+
return switchProvider({
|
|
99
|
+
appType: values.appType,
|
|
100
|
+
providerId: values.providerId,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getLatestProviderBackup(appType) {
|
|
105
|
+
assertAppType(appType)
|
|
106
|
+
return getLatestBackup(appType)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function restoreLatestProviderBackup(appType) {
|
|
110
|
+
assertAppType(appType)
|
|
111
|
+
return restoreBackup(appType)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function captureProviderFromLiveRecord(values) {
|
|
115
|
+
assertAppType(values.appType)
|
|
116
|
+
return maskProvider(
|
|
117
|
+
await captureProviderFromLive({
|
|
118
|
+
appType: values.appType,
|
|
119
|
+
name: values.name,
|
|
120
|
+
profile: values.profile,
|
|
121
|
+
})
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function listUniversalProvidersMasked() {
|
|
126
|
+
const providers = listUniversalProviders()
|
|
127
|
+
return providers.map(maskUniversalProvider)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getUniversalProviderRaw(id) {
|
|
131
|
+
const provider = getUniversalProviderById(id)
|
|
132
|
+
if (!provider) {
|
|
133
|
+
throw new Error(`Universal provider not found: ${id}`)
|
|
134
|
+
}
|
|
135
|
+
return provider
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function addUniversalProviderRecord(values) {
|
|
139
|
+
const provider = addUniversalProvider(values)
|
|
140
|
+
if (!provider) {
|
|
141
|
+
throw new Error('Failed to create universal provider')
|
|
142
|
+
}
|
|
143
|
+
return maskUniversalProvider(provider)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function updateUniversalProviderRecord(values) {
|
|
147
|
+
const provider = updateUniversalProvider(values)
|
|
148
|
+
if (!provider) {
|
|
149
|
+
throw new Error('Failed to update universal provider')
|
|
150
|
+
}
|
|
151
|
+
return maskUniversalProvider(provider)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function deleteUniversalProviderRecord(id) {
|
|
155
|
+
return deleteUniversalProvider(id)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function applyUniversalProviderRecord(id) {
|
|
159
|
+
const applied = applyUniversalProvider({ id })
|
|
160
|
+
return maskProviders(applied)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
APP_TYPES,
|
|
165
|
+
assertAppType,
|
|
166
|
+
normalizeProviderConfig,
|
|
167
|
+
listProvidersMasked,
|
|
168
|
+
getCurrentProviderMasked,
|
|
169
|
+
getProviderRaw,
|
|
170
|
+
addProviderRecord,
|
|
171
|
+
updateProviderRecord,
|
|
172
|
+
deleteProviderRecord,
|
|
173
|
+
switchProviderRecord,
|
|
174
|
+
getLatestProviderBackup,
|
|
175
|
+
restoreLatestProviderBackup,
|
|
176
|
+
captureProviderFromLiveRecord,
|
|
177
|
+
listUniversalProvidersMasked,
|
|
178
|
+
getUniversalProviderRaw,
|
|
179
|
+
addUniversalProviderRecord,
|
|
180
|
+
updateUniversalProviderRecord,
|
|
181
|
+
deleteUniversalProviderRecord,
|
|
182
|
+
applyUniversalProviderRecord,
|
|
183
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skillshub-labs/cli",
|
|
3
|
+
"version": "0.1.17",
|
|
4
|
+
"description": "Unify your AI toolbox. A local hub to visualize, manage, and sync skills across Antigravity, Claude, Cursor, Trae, and other AI agents.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"skills",
|
|
7
|
+
"ai",
|
|
8
|
+
"agent",
|
|
9
|
+
"claude",
|
|
10
|
+
"cursor",
|
|
11
|
+
"antigravity",
|
|
12
|
+
"cli"
|
|
13
|
+
],
|
|
14
|
+
"author": "PotatoDog1669",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/PotatoDog1669/skills-hub.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/PotatoDog1669/skills-hub",
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"skills-hub": "bin/skills-hub"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/skills-hub",
|
|
29
|
+
"lib/core/provider-core.mjs",
|
|
30
|
+
"lib/core/provider-core.d.ts",
|
|
31
|
+
"lib/core/kit-core.mjs",
|
|
32
|
+
"lib/core/kit-core.d.ts",
|
|
33
|
+
"lib/core/kit-types.ts",
|
|
34
|
+
"lib/services/provider-service.mjs",
|
|
35
|
+
"lib/services/provider-service.d.ts",
|
|
36
|
+
"lib/services/kit-service.mjs",
|
|
37
|
+
"lib/services/kit-service.d.ts",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"dev": "npm run tauri:dev",
|
|
43
|
+
"build": "npm run tauri:ui:build",
|
|
44
|
+
"tauri:ui:dev": "vite --config apps/desktop-ui/vite.config.ts --host 127.0.0.1 --port 1420",
|
|
45
|
+
"tauri:ui:build": "vite build --config apps/desktop-ui/vite.config.ts",
|
|
46
|
+
"tauri:dev": "tauri dev --config src-tauri/tauri.conf.json",
|
|
47
|
+
"tauri:build": "tauri build --config src-tauri/tauri.conf.json",
|
|
48
|
+
"lint": "eslint",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"test": "vitest",
|
|
51
|
+
"prepack": "npm run typecheck"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@iarna/toml": "^2.2.5",
|
|
55
|
+
"@tailwindcss/typography": "^0.5.19",
|
|
56
|
+
"@tauri-apps/api": "^2.8.0",
|
|
57
|
+
"@tauri-apps/plugin-dialog": "^2.0.0",
|
|
58
|
+
"@types/react-syntax-highlighter": "^15.5.13",
|
|
59
|
+
"better-sqlite3": "^12.6.2",
|
|
60
|
+
"clsx": "^2.1.1",
|
|
61
|
+
"fs-extra": "^11.3.3",
|
|
62
|
+
"gray-matter": "^4.0.3",
|
|
63
|
+
"lucide-react": "^0.562.0",
|
|
64
|
+
"react": "19.2.3",
|
|
65
|
+
"react-dom": "19.2.3",
|
|
66
|
+
"react-markdown": "^10.1.0",
|
|
67
|
+
"react-syntax-highlighter": "^16.1.0",
|
|
68
|
+
"remark-gfm": "^4.0.1",
|
|
69
|
+
"simple-git": "^3.30.0"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@eslint/js": "^9.39.2",
|
|
73
|
+
"@tauri-apps/cli": "^2.9.2",
|
|
74
|
+
"@testing-library/dom": "^10.4.1",
|
|
75
|
+
"@testing-library/react": "^16.3.2",
|
|
76
|
+
"@types/fs-extra": "^11.0.4",
|
|
77
|
+
"@types/node": "^20",
|
|
78
|
+
"@types/react": "^19",
|
|
79
|
+
"@types/react-dom": "^19",
|
|
80
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
81
|
+
"autoprefixer": "^10.4.23",
|
|
82
|
+
"eslint": "^9",
|
|
83
|
+
"globals": "^17.3.0",
|
|
84
|
+
"jsdom": "^27.4.0",
|
|
85
|
+
"lint-staged": "^16.2.7",
|
|
86
|
+
"postcss": "^8.5.6",
|
|
87
|
+
"prettier": "^3.8.0",
|
|
88
|
+
"tailwindcss": "^3.4.17",
|
|
89
|
+
"typescript": "^5",
|
|
90
|
+
"typescript-eslint": "^8.55.0",
|
|
91
|
+
"vite": "^7.1.11",
|
|
92
|
+
"vitest": "^4.0.17"
|
|
93
|
+
}
|
|
94
|
+
}
|