@nospt/plugin-dev-ai-hub-backend 0.2.4 → 0.3.1
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/config.d.ts +22 -0
- package/dist/database/TelemetryStore.cjs.js +94 -0
- package/dist/database/TelemetryStore.cjs.js.map +1 -0
- package/dist/plugin.cjs.js +24 -45
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/router.cjs.js +147 -202
- package/dist/router.cjs.js.map +1 -1
- package/dist/service/bodyResolver.cjs.js +56 -0
- package/dist/service/bodyResolver.cjs.js.map +1 -0
- package/dist/service/telemetryHash.cjs.js +14 -0
- package/dist/service/telemetryHash.cjs.js.map +1 -0
- package/dist/service/toResourceSummary.cjs.js +31 -0
- package/dist/service/toResourceSummary.cjs.js.map +1 -0
- package/migrations/001_init.js +13 -42
- package/migrations/002_install_count.js +7 -12
- package/migrations/003_install_paths.js +7 -14
- package/migrations/004_label.js +7 -12
- package/migrations/005_remove_unused_fields.js +6 -16
- package/migrations/006_resources_content.js +10 -13
- package/migrations/007_telemetry.js +28 -0
- package/migrations/008_drop_legacy_tables.js +24 -0
- package/migrations/009_telemetry_settings.js +25 -0
- package/package.json +18 -8
- package/.eslintrc.js +0 -1
- package/dev/index.ts +0 -8
- package/dist/database/AiAssetStore.cjs.js +0 -225
- package/dist/database/AiAssetStore.cjs.js.map +0 -1
- package/dist/service/AiAssetSyncService.cjs.js +0 -235
- package/dist/service/AiAssetSyncService.cjs.js.map +0 -1
- package/dist/service/AssetParser.cjs.js +0 -74
- package/dist/service/AssetParser.cjs.js.map +0 -1
- package/dist/service/McpServerService.cjs.js +0 -366
- package/dist/service/McpServerService.cjs.js.map +0 -1
- package/package.json-prepack +0 -71
- package/src/database/AiAssetStore.test.ts +0 -294
- package/src/database/AiAssetStore.ts +0 -256
- package/src/index.ts +0 -2
- package/src/plugin.ts +0 -84
- package/src/router.smoke.test.ts +0 -262
- package/src/router.ts +0 -338
- package/src/service/AiAssetSyncService.ts +0 -298
- package/src/service/AssetParser.test.ts +0 -329
- package/src/service/AssetParser.ts +0 -103
- package/src/service/McpServerService.ts +0 -464
- package/src/types.ts +0 -31
- package/tsconfig.json +0 -8
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
|
-
|
|
5
|
-
class AiAssetStore {
|
|
6
|
-
constructor(db) {
|
|
7
|
-
this.db = db;
|
|
8
|
-
}
|
|
9
|
-
db;
|
|
10
|
-
static async create(options) {
|
|
11
|
-
const db = await options.database.getClient();
|
|
12
|
-
await db.migrate.latest({
|
|
13
|
-
directory: backendPluginApi.resolvePackagePath("@nospt/plugin-dev-ai-hub-backend", "migrations"),
|
|
14
|
-
loadExtensions: [".js"]
|
|
15
|
-
});
|
|
16
|
-
return new AiAssetStore(db);
|
|
17
|
-
}
|
|
18
|
-
async upsertAsset(input) {
|
|
19
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20
|
-
const row = {
|
|
21
|
-
id: input.id,
|
|
22
|
-
provider_id: input.providerId,
|
|
23
|
-
name: input.name,
|
|
24
|
-
label: input.label ?? null,
|
|
25
|
-
description: input.description,
|
|
26
|
-
type: input.type,
|
|
27
|
-
tools: JSON.stringify(input.tools),
|
|
28
|
-
tags: JSON.stringify(input.tags),
|
|
29
|
-
author: input.author,
|
|
30
|
-
icon: input.icon ?? null,
|
|
31
|
-
version: input.version,
|
|
32
|
-
install_path: input.installPath ?? null,
|
|
33
|
-
install_paths: input.installPaths ? JSON.stringify(input.installPaths) : null,
|
|
34
|
-
content: input.content,
|
|
35
|
-
yaml_raw: input.yamlRaw,
|
|
36
|
-
metadata: input.metadata ? JSON.stringify(input.metadata) : null,
|
|
37
|
-
resources_content: input.resourcesContent ? JSON.stringify(input.resourcesContent) : null,
|
|
38
|
-
yaml_path: input.yamlPath,
|
|
39
|
-
md_path: input.mdPath,
|
|
40
|
-
repo_url: input.repoUrl,
|
|
41
|
-
branch: input.branch,
|
|
42
|
-
commit_sha: input.commitSha ?? null,
|
|
43
|
-
synced_at: now,
|
|
44
|
-
updated_at: now
|
|
45
|
-
};
|
|
46
|
-
await this.db("ai_assets").insert({ ...row, created_at: now }).onConflict("id").merge(Object.keys(row));
|
|
47
|
-
}
|
|
48
|
-
async listAssets(filter) {
|
|
49
|
-
let query = this.db("ai_assets");
|
|
50
|
-
if (filter.type) {
|
|
51
|
-
query = query.where("type", filter.type);
|
|
52
|
-
}
|
|
53
|
-
if (filter.tool) {
|
|
54
|
-
query = query.where(function toolFilter() {
|
|
55
|
-
this.where("tools", "like", `%"${filter.tool}"%`).orWhere("tools", "like", `%"all"%`);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
if (filter.providerId) {
|
|
59
|
-
query = query.where("provider_id", filter.providerId);
|
|
60
|
-
}
|
|
61
|
-
if (filter.search) {
|
|
62
|
-
const words = filter.search.trim().split(/\s+/).filter(Boolean);
|
|
63
|
-
for (const word of words) {
|
|
64
|
-
const term = `%${word}%`;
|
|
65
|
-
query = query.where(function searchFilter() {
|
|
66
|
-
this.where("name", "like", term).orWhere("label", "like", term).orWhere("description", "like", term).orWhere("tags", "like", term).orWhere("content", "like", term);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (filter.tags && filter.tags.length > 0) {
|
|
71
|
-
for (const tag of filter.tags) {
|
|
72
|
-
query = query.where("tags", "like", `%"${tag}"%`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const countResult = await query.clone().count("id as count").first();
|
|
76
|
-
const totalCount = Number(countResult?.count ?? 0);
|
|
77
|
-
const page = Math.max(1, filter.page ?? 1);
|
|
78
|
-
const pageSize = Math.min(100, Math.max(1, filter.pageSize ?? 20));
|
|
79
|
-
const rows = await query.select(
|
|
80
|
-
"id",
|
|
81
|
-
"provider_id",
|
|
82
|
-
"name",
|
|
83
|
-
"label",
|
|
84
|
-
"description",
|
|
85
|
-
"type",
|
|
86
|
-
"tools",
|
|
87
|
-
"tags",
|
|
88
|
-
"author",
|
|
89
|
-
"icon",
|
|
90
|
-
"version",
|
|
91
|
-
"install_count",
|
|
92
|
-
"synced_at",
|
|
93
|
-
"created_at",
|
|
94
|
-
"updated_at"
|
|
95
|
-
).orderBy("name", "asc").limit(pageSize).offset((page - 1) * pageSize);
|
|
96
|
-
return { items: rows.map((r) => this.rowToAssetSummary(r)), totalCount };
|
|
97
|
-
}
|
|
98
|
-
async getAsset(id) {
|
|
99
|
-
const row = await this.db("ai_assets").where("id", id).first();
|
|
100
|
-
return row ? this.rowToAsset(row) : null;
|
|
101
|
-
}
|
|
102
|
-
async incrementInstallCount(id) {
|
|
103
|
-
await this.db("ai_assets").where("id", id).increment("install_count", 1);
|
|
104
|
-
}
|
|
105
|
-
async deleteAssetsNotIn(providerId, ids) {
|
|
106
|
-
let query = this.db("ai_assets").where("provider_id", providerId);
|
|
107
|
-
if (ids.length > 0) {
|
|
108
|
-
query = query.whereNotIn("id", ids);
|
|
109
|
-
}
|
|
110
|
-
await query.delete();
|
|
111
|
-
}
|
|
112
|
-
async upsertSyncStatus(status) {
|
|
113
|
-
const row = {
|
|
114
|
-
provider_id: status.providerId,
|
|
115
|
-
last_sync: status.lastSync ?? null,
|
|
116
|
-
last_commit: status.lastCommit ?? null,
|
|
117
|
-
status: status.status,
|
|
118
|
-
error: status.error ?? null,
|
|
119
|
-
asset_count: status.assetCount
|
|
120
|
-
};
|
|
121
|
-
await this.db("ai_asset_sync_status").insert(row).onConflict("provider_id").merge(Object.keys(row));
|
|
122
|
-
}
|
|
123
|
-
async getSyncStatus(providerId) {
|
|
124
|
-
const row = await this.db("ai_asset_sync_status").where("provider_id", providerId).first();
|
|
125
|
-
if (!row) return null;
|
|
126
|
-
return {
|
|
127
|
-
providerId: row.provider_id,
|
|
128
|
-
lastSync: row.last_sync ?? void 0,
|
|
129
|
-
lastCommit: row.last_commit ?? void 0,
|
|
130
|
-
status: row.status,
|
|
131
|
-
error: row.error ?? void 0,
|
|
132
|
-
assetCount: row.asset_count ?? 0
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
async getAllSyncStatuses() {
|
|
136
|
-
const rows = await this.db("ai_asset_sync_status").select("*");
|
|
137
|
-
return rows.map((row) => ({
|
|
138
|
-
providerId: row.provider_id,
|
|
139
|
-
lastSync: row.last_sync ?? void 0,
|
|
140
|
-
lastCommit: row.last_commit ?? void 0,
|
|
141
|
-
status: row.status,
|
|
142
|
-
error: row.error ?? void 0,
|
|
143
|
-
assetCount: row.asset_count ?? 0
|
|
144
|
-
}));
|
|
145
|
-
}
|
|
146
|
-
async getStats() {
|
|
147
|
-
const rows = await this.db("ai_assets").select("type", "tools", "provider_id");
|
|
148
|
-
const byType = {
|
|
149
|
-
instruction: 0,
|
|
150
|
-
agent: 0,
|
|
151
|
-
skill: 0,
|
|
152
|
-
workflow: 0
|
|
153
|
-
};
|
|
154
|
-
const byTool = {};
|
|
155
|
-
const byProvider = {};
|
|
156
|
-
for (const row of rows) {
|
|
157
|
-
byType[row.type] = (byType[row.type] ?? 0) + 1;
|
|
158
|
-
byProvider[row.provider_id] = (byProvider[row.provider_id] ?? 0) + 1;
|
|
159
|
-
const tools = JSON.parse(row.tools || "[]");
|
|
160
|
-
for (const tool of tools) {
|
|
161
|
-
byTool[tool] = (byTool[tool] ?? 0) + 1;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
const lastSyncRow = await this.db("ai_asset_sync_status").select(this.db.raw("max(last_sync) as last_sync")).first();
|
|
165
|
-
return {
|
|
166
|
-
totalAssets: rows.length,
|
|
167
|
-
byType,
|
|
168
|
-
byTool,
|
|
169
|
-
byProvider,
|
|
170
|
-
lastSync: lastSyncRow?.last_sync ?? void 0
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
rowToAssetSummary(row) {
|
|
174
|
-
return {
|
|
175
|
-
id: row.id,
|
|
176
|
-
providerId: row.provider_id,
|
|
177
|
-
name: row.name,
|
|
178
|
-
label: row.label ?? void 0,
|
|
179
|
-
description: row.description,
|
|
180
|
-
type: row.type,
|
|
181
|
-
tools: JSON.parse(row.tools || "[]"),
|
|
182
|
-
tags: JSON.parse(row.tags || "[]"),
|
|
183
|
-
author: row.author,
|
|
184
|
-
icon: row.icon ?? void 0,
|
|
185
|
-
version: row.version,
|
|
186
|
-
installCount: row.install_count ?? 0,
|
|
187
|
-
syncedAt: row.synced_at,
|
|
188
|
-
createdAt: row.created_at,
|
|
189
|
-
updatedAt: row.updated_at
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
rowToAsset(row) {
|
|
193
|
-
return {
|
|
194
|
-
id: row.id,
|
|
195
|
-
providerId: row.provider_id,
|
|
196
|
-
name: row.name,
|
|
197
|
-
label: row.label ?? void 0,
|
|
198
|
-
description: row.description,
|
|
199
|
-
type: row.type,
|
|
200
|
-
tools: JSON.parse(row.tools || "[]"),
|
|
201
|
-
tags: JSON.parse(row.tags || "[]"),
|
|
202
|
-
author: row.author,
|
|
203
|
-
icon: row.icon ?? void 0,
|
|
204
|
-
version: row.version,
|
|
205
|
-
installPath: row.install_path ?? void 0,
|
|
206
|
-
installPaths: row.install_paths ? JSON.parse(row.install_paths) : void 0,
|
|
207
|
-
content: row.content,
|
|
208
|
-
yamlRaw: row.yaml_raw,
|
|
209
|
-
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
210
|
-
resourcesContent: row.resources_content ? JSON.parse(row.resources_content) : void 0,
|
|
211
|
-
yamlPath: row.yaml_path,
|
|
212
|
-
mdPath: row.md_path,
|
|
213
|
-
repoUrl: row.repo_url,
|
|
214
|
-
branch: row.branch,
|
|
215
|
-
commitSha: row.commit_sha ?? void 0,
|
|
216
|
-
installCount: row.install_count ?? 0,
|
|
217
|
-
syncedAt: row.synced_at,
|
|
218
|
-
createdAt: row.created_at,
|
|
219
|
-
updatedAt: row.updated_at
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
exports.AiAssetStore = AiAssetStore;
|
|
225
|
-
//# sourceMappingURL=AiAssetStore.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AiAssetStore.cjs.js","sources":["../../src/database/AiAssetStore.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport { resolvePackagePath, type DatabaseService } from '@backstage/backend-plugin-api';\nimport type { AiAsset, AiAssetSummary, AiHubStats, AssetListFilter, AssetType } from '@nospt/plugin-dev-ai-hub-common';\nimport type { AiAssetInput, SyncStatus } from '../types';\n\nexport class AiAssetStore {\n private constructor(private readonly db: Knex) {}\n\n static async create(options: { database: DatabaseService }): Promise<AiAssetStore> {\n const db = await options.database.getClient();\n await db.migrate.latest({\n directory: resolvePackagePath('@nospt/plugin-dev-ai-hub-backend', 'migrations'),\n loadExtensions: ['.js'],\n });\n return new AiAssetStore(db);\n }\n\n async upsertAsset(input: AiAssetInput): Promise<void> {\n const now = new Date().toISOString();\n const row = {\n id: input.id,\n provider_id: input.providerId,\n name: input.name,\n label: input.label ?? null,\n description: input.description,\n type: input.type,\n tools: JSON.stringify(input.tools),\n tags: JSON.stringify(input.tags),\n author: input.author,\n icon: input.icon ?? null,\n version: input.version,\n install_path: input.installPath ?? null,\n install_paths: input.installPaths ? JSON.stringify(input.installPaths) : null,\n content: input.content,\n yaml_raw: input.yamlRaw,\n metadata: input.metadata ? JSON.stringify(input.metadata) : null,\n resources_content: input.resourcesContent ? JSON.stringify(input.resourcesContent) : null,\n yaml_path: input.yamlPath,\n md_path: input.mdPath,\n repo_url: input.repoUrl,\n branch: input.branch,\n commit_sha: input.commitSha ?? null,\n synced_at: now,\n updated_at: now,\n };\n\n await this.db('ai_assets')\n .insert({ ...row, created_at: now })\n .onConflict('id')\n .merge(Object.keys(row) as (keyof typeof row)[]);\n }\n\n async listAssets(\n filter: AssetListFilter,\n ): Promise<{ items: AiAssetSummary[]; totalCount: number }> {\n let query = this.db<Record<string, unknown>>('ai_assets');\n\n if (filter.type) {\n query = query.where('type', filter.type);\n }\n if (filter.tool) {\n query = query.where(function toolFilter() {\n this.where('tools', 'like', `%\"${filter.tool}\"%`)\n .orWhere('tools', 'like', `%\"all\"%`);\n });\n }\n if (filter.providerId) {\n query = query.where('provider_id', filter.providerId);\n }\n if (filter.search) {\n // Split into words so \"Python linting\" matches items containing both words\n const words = filter.search.trim().split(/\\s+/).filter(Boolean);\n for (const word of words) {\n const term = `%${word}%`;\n query = query.where(function searchFilter() {\n this.where('name', 'like', term)\n .orWhere('label', 'like', term)\n .orWhere('description', 'like', term)\n .orWhere('tags', 'like', term)\n .orWhere('content', 'like', term);\n });\n }\n }\n if (filter.tags && filter.tags.length > 0) {\n for (const tag of filter.tags) {\n query = query.where('tags', 'like', `%\"${tag}\"%`);\n }\n }\n\n const countResult = await query.clone().count('id as count').first();\n const totalCount = Number(countResult?.count ?? 0);\n\n const page = Math.max(1, filter.page ?? 1);\n const pageSize = Math.min(100, Math.max(1, filter.pageSize ?? 20));\n\n const rows = await query\n .select('id', 'provider_id', 'name', 'label', 'description', 'type', 'tools', 'tags',\n 'author', 'icon', 'version', 'install_count', 'synced_at', 'created_at', 'updated_at')\n .orderBy('name', 'asc')\n .limit(pageSize)\n .offset((page - 1) * pageSize);\n\n return { items: rows.map(r => this.rowToAssetSummary(r)), totalCount };\n }\n\n async getAsset(id: string): Promise<AiAsset | null> {\n const row = await this.db('ai_assets').where('id', id).first();\n return row ? this.rowToAsset(row) : null;\n }\n\n async incrementInstallCount(id: string): Promise<void> {\n await this.db('ai_assets').where('id', id).increment('install_count', 1);\n }\n\n async deleteAssetsNotIn(providerId: string, ids: string[]): Promise<void> {\n let query = this.db('ai_assets').where('provider_id', providerId);\n if (ids.length > 0) {\n query = query.whereNotIn('id', ids);\n }\n await query.delete();\n }\n\n async upsertSyncStatus(status: SyncStatus): Promise<void> {\n const row = {\n provider_id: status.providerId,\n last_sync: status.lastSync ?? null,\n last_commit: status.lastCommit ?? null,\n status: status.status,\n error: status.error ?? null,\n asset_count: status.assetCount,\n };\n await this.db('ai_asset_sync_status')\n .insert(row)\n .onConflict('provider_id')\n .merge(Object.keys(row) as (keyof typeof row)[]);\n }\n\n async getSyncStatus(providerId: string): Promise<SyncStatus | null> {\n const row = await this.db('ai_asset_sync_status')\n .where('provider_id', providerId)\n .first();\n if (!row) return null;\n return {\n providerId: row.provider_id,\n lastSync: row.last_sync ?? undefined,\n lastCommit: row.last_commit ?? undefined,\n status: row.status,\n error: row.error ?? undefined,\n assetCount: row.asset_count ?? 0,\n };\n }\n\n async getAllSyncStatuses(): Promise<SyncStatus[]> {\n const rows = await this.db('ai_asset_sync_status').select('*');\n return rows.map(row => ({\n providerId: row.provider_id,\n lastSync: row.last_sync ?? undefined,\n lastCommit: row.last_commit ?? undefined,\n status: row.status,\n error: row.error ?? undefined,\n assetCount: row.asset_count ?? 0,\n }));\n }\n\n async getStats(): Promise<AiHubStats> {\n const rows = await this.db('ai_assets').select('type', 'tools', 'provider_id');\n\n const byType: Record<AssetType, number> = {\n instruction: 0,\n agent: 0,\n skill: 0,\n workflow: 0,\n };\n const byTool: Record<string, number> = {};\n const byProvider: Record<string, number> = {};\n\n for (const row of rows) {\n byType[row.type as AssetType] = (byType[row.type as AssetType] ?? 0) + 1;\n byProvider[row.provider_id] = (byProvider[row.provider_id] ?? 0) + 1;\n\n const tools: string[] = JSON.parse(row.tools || '[]');\n for (const tool of tools) {\n byTool[tool] = (byTool[tool] ?? 0) + 1;\n }\n }\n\n const lastSyncRow = await this.db('ai_asset_sync_status')\n .select(this.db.raw('max(last_sync) as last_sync'))\n .first();\n\n return {\n totalAssets: rows.length,\n byType,\n byTool,\n byProvider,\n lastSync: (lastSyncRow?.last_sync as string | null) ?? undefined,\n };\n }\n\n private rowToAssetSummary(row: Record<string, unknown>): AiAssetSummary {\n return {\n id: row.id as string,\n providerId: row.provider_id as string,\n name: row.name as string,\n label: (row.label as string | null) ?? undefined,\n description: row.description as string,\n type: row.type as AssetType,\n tools: JSON.parse((row.tools as string) || '[]'),\n tags: JSON.parse((row.tags as string) || '[]'),\n author: row.author as string,\n icon: (row.icon as string | null) ?? undefined,\n version: row.version as string,\n installCount: (row.install_count as number) ?? 0,\n syncedAt: row.synced_at as string,\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n };\n }\n\n private rowToAsset(row: Record<string, unknown>): AiAsset {\n return {\n id: row.id as string,\n providerId: row.provider_id as string,\n name: row.name as string,\n label: (row.label as string | null) ?? undefined,\n description: row.description as string,\n type: row.type as AssetType,\n tools: JSON.parse((row.tools as string) || '[]'),\n tags: JSON.parse((row.tags as string) || '[]'),\n author: row.author as string,\n icon: (row.icon as string | null) ?? undefined,\n version: row.version as string,\n installPath: (row.install_path as string | null) ?? undefined,\n installPaths: row.install_paths\n ? JSON.parse(row.install_paths as string)\n : undefined,\n content: row.content as string,\n yamlRaw: row.yaml_raw as string,\n metadata: row.metadata\n ? JSON.parse(row.metadata as string)\n : undefined,\n resourcesContent: row.resources_content\n ? JSON.parse(row.resources_content as string)\n : undefined,\n yamlPath: row.yaml_path as string,\n mdPath: row.md_path as string,\n repoUrl: row.repo_url as string,\n branch: row.branch as string,\n commitSha: (row.commit_sha as string | null) ?? undefined,\n installCount: (row.install_count as number) ?? 0,\n syncedAt: row.synced_at as string,\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n };\n }\n}\n"],"names":["resolvePackagePath"],"mappings":"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"}
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var AssetParser = require('./AssetParser.cjs.js');
|
|
4
|
-
|
|
5
|
-
class AiAssetSyncService {
|
|
6
|
-
constructor(options) {
|
|
7
|
-
this.options = options;
|
|
8
|
-
}
|
|
9
|
-
options;
|
|
10
|
-
async start() {
|
|
11
|
-
const { scheduler, logger, providers, externalProviders } = this.options;
|
|
12
|
-
if (providers.length === 0 && externalProviders.length === 0) {
|
|
13
|
-
logger.warn(
|
|
14
|
-
"dev-ai-hub: no providers configured under devAiHub.providers"
|
|
15
|
-
);
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
for (const provider of providers) {
|
|
19
|
-
const { frequency, timeout } = provider.schedule;
|
|
20
|
-
const frequencyDuration = frequency.minutes ? { minutes: frequency.minutes } : { hours: frequency.hours ?? 1 };
|
|
21
|
-
const timeoutDuration = timeout.minutes ? { minutes: timeout.minutes } : { hours: timeout.hours ?? 1 };
|
|
22
|
-
await scheduler.scheduleTask({
|
|
23
|
-
id: `dev-ai-hub-sync-${provider.id}`,
|
|
24
|
-
frequency: frequencyDuration,
|
|
25
|
-
timeout: timeoutDuration,
|
|
26
|
-
initialDelay: { seconds: 15 },
|
|
27
|
-
fn: async () => {
|
|
28
|
-
await this.syncProvider(provider);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
logger.info(
|
|
32
|
-
`dev-ai-hub: scheduled sync for provider "${provider.id}" every ${JSON.stringify(frequencyDuration)}`
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
for (const extProvider of externalProviders) {
|
|
36
|
-
await scheduler.scheduleTask({
|
|
37
|
-
id: `dev-ai-hub-sync-external-${extProvider.id}`,
|
|
38
|
-
frequency: { minutes: 60 },
|
|
39
|
-
timeout: { minutes: 5 },
|
|
40
|
-
initialDelay: { seconds: 15 },
|
|
41
|
-
fn: async () => {
|
|
42
|
-
await this.syncExternalProvider(extProvider);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
logger.info(
|
|
46
|
-
`dev-ai-hub: scheduled sync for external provider "${extProvider.id}"`
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async syncProvider(provider) {
|
|
51
|
-
const { logger, urlReader, store } = this.options;
|
|
52
|
-
logger.info(`dev-ai-hub: starting sync for provider "${provider.id}"`);
|
|
53
|
-
await store.upsertSyncStatus({
|
|
54
|
-
providerId: provider.id,
|
|
55
|
-
status: "syncing",
|
|
56
|
-
assetCount: 0
|
|
57
|
-
});
|
|
58
|
-
try {
|
|
59
|
-
const treeUrl = buildTreeUrl(provider);
|
|
60
|
-
const tree = await urlReader.readTree(treeUrl);
|
|
61
|
-
const files = await tree.files();
|
|
62
|
-
const fileMap = /* @__PURE__ */ new Map();
|
|
63
|
-
for (const file of files) {
|
|
64
|
-
fileMap.set(normalizePath(file.path), file);
|
|
65
|
-
}
|
|
66
|
-
const syncedIds = [];
|
|
67
|
-
for (const [filePath, file] of fileMap) {
|
|
68
|
-
if (!filePath.endsWith(".yaml")) continue;
|
|
69
|
-
const yamlContent = (await file.content()).toString("utf-8");
|
|
70
|
-
const parsed = AssetParser.AssetParser.parseYaml(yamlContent, filePath);
|
|
71
|
-
if (!parsed) {
|
|
72
|
-
logger.warn(
|
|
73
|
-
`dev-ai-hub: skipping invalid YAML at ${filePath} (provider ${provider.id})`
|
|
74
|
-
);
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
if (provider.filters?.types && !provider.filters.types.includes(parsed.meta.type)) {
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
if (provider.filters?.tools) {
|
|
81
|
-
const hasMatchingTool = parsed.meta.tools.some(
|
|
82
|
-
(t) => provider.filters.tools.includes(t)
|
|
83
|
-
);
|
|
84
|
-
if (!hasMatchingTool) continue;
|
|
85
|
-
}
|
|
86
|
-
const yamlDir = filePath.includes("/") ? filePath.split("/").slice(0, -1).join("/") : "";
|
|
87
|
-
let resolvedMdPath;
|
|
88
|
-
let mdFile;
|
|
89
|
-
if (parsed.mdPath) {
|
|
90
|
-
resolvedMdPath = normalizePath(parsed.mdPath);
|
|
91
|
-
mdFile = fileMap.get(resolvedMdPath);
|
|
92
|
-
if (!mdFile) {
|
|
93
|
-
logger.warn(
|
|
94
|
-
`dev-ai-hub: content file "${parsed.mdPath}" not found for ${filePath}, skipping`
|
|
95
|
-
);
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
const mdCandidates = [...fileMap.keys()].filter((p) => {
|
|
100
|
-
const dir = p.includes("/") ? p.split("/").slice(0, -1).join("/") : "";
|
|
101
|
-
return dir === yamlDir && p.endsWith(".md");
|
|
102
|
-
});
|
|
103
|
-
if (mdCandidates.length === 1) {
|
|
104
|
-
resolvedMdPath = mdCandidates[0];
|
|
105
|
-
mdFile = fileMap.get(resolvedMdPath);
|
|
106
|
-
} else if (mdCandidates.length > 1) {
|
|
107
|
-
logger.warn(
|
|
108
|
-
`dev-ai-hub: multiple .md files in "${yamlDir || "."}" for ${filePath} \u2014 add a 'content' field to the YAML to specify which one, skipping`
|
|
109
|
-
);
|
|
110
|
-
continue;
|
|
111
|
-
} else {
|
|
112
|
-
logger.warn(
|
|
113
|
-
`dev-ai-hub: no .md file found for ${filePath}, skipping`
|
|
114
|
-
);
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
const mdContent = (await mdFile.content()).toString("utf-8");
|
|
119
|
-
let resourcesContent;
|
|
120
|
-
const resourcePaths = parsed.meta.resources;
|
|
121
|
-
if (resourcePaths && resourcePaths.length > 0) {
|
|
122
|
-
resourcesContent = {};
|
|
123
|
-
for (const resourcePath of resourcePaths) {
|
|
124
|
-
const fullPath = normalizePath(
|
|
125
|
-
yamlDir ? `${yamlDir}/${resourcePath}` : resourcePath
|
|
126
|
-
);
|
|
127
|
-
const resourceFile = fileMap.get(fullPath);
|
|
128
|
-
if (resourceFile) {
|
|
129
|
-
resourcesContent[resourcePath] = (await resourceFile.content()).toString("utf-8");
|
|
130
|
-
} else {
|
|
131
|
-
logger.warn(
|
|
132
|
-
`dev-ai-hub: resource file not found: ${fullPath} (asset ${filePath})`
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (Object.keys(resourcesContent).length === 0) resourcesContent = void 0;
|
|
137
|
-
}
|
|
138
|
-
const asset = AssetParser.AssetParser.buildAsset(
|
|
139
|
-
parsed,
|
|
140
|
-
mdContent,
|
|
141
|
-
provider.id,
|
|
142
|
-
provider.target,
|
|
143
|
-
provider.branch,
|
|
144
|
-
filePath,
|
|
145
|
-
resolvedMdPath,
|
|
146
|
-
resourcesContent
|
|
147
|
-
);
|
|
148
|
-
await store.upsertAsset(asset);
|
|
149
|
-
syncedIds.push(asset.id);
|
|
150
|
-
}
|
|
151
|
-
await store.deleteAssetsNotIn(provider.id, syncedIds);
|
|
152
|
-
await store.upsertSyncStatus({
|
|
153
|
-
providerId: provider.id,
|
|
154
|
-
lastSync: (/* @__PURE__ */ new Date()).toISOString(),
|
|
155
|
-
status: "idle",
|
|
156
|
-
assetCount: syncedIds.length
|
|
157
|
-
});
|
|
158
|
-
logger.info(
|
|
159
|
-
`dev-ai-hub: sync complete for provider "${provider.id}" \u2014 ${syncedIds.length} assets`
|
|
160
|
-
);
|
|
161
|
-
} catch (err) {
|
|
162
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
163
|
-
this.options.logger.error(
|
|
164
|
-
`dev-ai-hub: sync failed for provider "${provider.id}": ${message}`
|
|
165
|
-
);
|
|
166
|
-
await store.upsertSyncStatus({
|
|
167
|
-
providerId: provider.id,
|
|
168
|
-
status: "error",
|
|
169
|
-
error: message,
|
|
170
|
-
assetCount: 0
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
async syncExternalProvider(provider) {
|
|
175
|
-
const { logger, store } = this.options;
|
|
176
|
-
logger.info(`dev-ai-hub: syncing external provider "${provider.id}"`);
|
|
177
|
-
await store.upsertSyncStatus({
|
|
178
|
-
providerId: provider.id,
|
|
179
|
-
status: "syncing",
|
|
180
|
-
assetCount: 0
|
|
181
|
-
});
|
|
182
|
-
try {
|
|
183
|
-
const assets = await provider.getAssets();
|
|
184
|
-
const syncedIds = [];
|
|
185
|
-
for (const assetData of assets) {
|
|
186
|
-
const id = AssetParser.AssetParser.buildId(provider.id, assetData.yamlPath);
|
|
187
|
-
await store.upsertAsset({ ...assetData, id });
|
|
188
|
-
syncedIds.push(id);
|
|
189
|
-
}
|
|
190
|
-
await store.deleteAssetsNotIn(provider.id, syncedIds);
|
|
191
|
-
await store.upsertSyncStatus({
|
|
192
|
-
providerId: provider.id,
|
|
193
|
-
lastSync: (/* @__PURE__ */ new Date()).toISOString(),
|
|
194
|
-
status: "idle",
|
|
195
|
-
assetCount: syncedIds.length
|
|
196
|
-
});
|
|
197
|
-
logger.info(
|
|
198
|
-
`dev-ai-hub: external sync complete for "${provider.id}" \u2014 ${syncedIds.length} assets`
|
|
199
|
-
);
|
|
200
|
-
} catch (err) {
|
|
201
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
202
|
-
logger.error(
|
|
203
|
-
`dev-ai-hub: external sync failed for "${provider.id}": ${message}`
|
|
204
|
-
);
|
|
205
|
-
await store.upsertSyncStatus({
|
|
206
|
-
providerId: provider.id,
|
|
207
|
-
status: "error",
|
|
208
|
-
error: message,
|
|
209
|
-
assetCount: 0
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
function normalizePath(p) {
|
|
215
|
-
return p.replace(/\\/g, "/").replace(/^\//, "");
|
|
216
|
-
}
|
|
217
|
-
function buildTreeUrl(provider) {
|
|
218
|
-
const base = provider.target.replace(/\.git$/, "");
|
|
219
|
-
const { branch, type } = provider;
|
|
220
|
-
switch (type) {
|
|
221
|
-
case "gitlab":
|
|
222
|
-
return `${base}/-/tree/${branch}/`;
|
|
223
|
-
case "bitbucket":
|
|
224
|
-
return `${base}/src/${branch}/`;
|
|
225
|
-
case "azure-devops":
|
|
226
|
-
return `${base}?version=GB${branch}`;
|
|
227
|
-
case "github":
|
|
228
|
-
case "git":
|
|
229
|
-
default:
|
|
230
|
-
return `${base}/tree/${branch}/`;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
exports.AiAssetSyncService = AiAssetSyncService;
|
|
235
|
-
//# sourceMappingURL=AiAssetSyncService.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AiAssetSyncService.cjs.js","sources":["../../src/service/AiAssetSyncService.ts"],"sourcesContent":["import type {\n LoggerService,\n SchedulerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport type { AiAssetStore } from '../database/AiAssetStore';\nimport type { ProviderConfig } from '../types';\nimport type { AiAssetProvider } from '@nospt/plugin-dev-ai-hub-node';\nimport { AssetParser } from './AssetParser';\n\ninterface Options {\n logger: LoggerService;\n store: AiAssetStore;\n scheduler: SchedulerService;\n urlReader: UrlReaderService;\n providers: ProviderConfig[];\n externalProviders: AiAssetProvider[];\n}\n\nexport class AiAssetSyncService {\n constructor(private readonly options: Options) {}\n\n async start(): Promise<void> {\n const { scheduler, logger, providers, externalProviders } = this.options;\n\n if (providers.length === 0 && externalProviders.length === 0) {\n logger.warn(\n 'dev-ai-hub: no providers configured under devAiHub.providers',\n );\n return;\n }\n\n for (const provider of providers) {\n const { frequency, timeout } = provider.schedule;\n const frequencyDuration = frequency.minutes\n ? { minutes: frequency.minutes }\n : { hours: frequency.hours ?? 1 };\n const timeoutDuration = timeout.minutes\n ? { minutes: timeout.minutes }\n : { hours: timeout.hours ?? 1 };\n\n await scheduler.scheduleTask({\n id: `dev-ai-hub-sync-${provider.id}`,\n frequency: frequencyDuration,\n timeout: timeoutDuration,\n initialDelay: { seconds: 15 },\n fn: async () => {\n await this.syncProvider(provider);\n },\n });\n\n logger.info(\n `dev-ai-hub: scheduled sync for provider \"${provider.id}\" every ${JSON.stringify(frequencyDuration)}`,\n );\n }\n\n for (const extProvider of externalProviders) {\n await scheduler.scheduleTask({\n id: `dev-ai-hub-sync-external-${extProvider.id}`,\n frequency: { minutes: 60 },\n timeout: { minutes: 5 },\n initialDelay: { seconds: 15 },\n fn: async () => {\n await this.syncExternalProvider(extProvider);\n },\n });\n\n logger.info(\n `dev-ai-hub: scheduled sync for external provider \"${extProvider.id}\"`,\n );\n }\n }\n\n async syncProvider(provider: ProviderConfig): Promise<void> {\n const { logger, urlReader, store } = this.options;\n\n logger.info(`dev-ai-hub: starting sync for provider \"${provider.id}\"`);\n\n await store.upsertSyncStatus({\n providerId: provider.id,\n status: 'syncing',\n assetCount: 0,\n });\n\n try {\n const treeUrl = buildTreeUrl(provider);\n const tree = await urlReader.readTree(treeUrl);\n const files = await tree.files();\n\n const fileMap = new Map<\n string,\n { content(): Promise<Buffer>; path: string }\n >();\n for (const file of files) {\n fileMap.set(normalizePath(file.path), file);\n }\n\n const syncedIds: string[] = [];\n\n for (const [filePath, file] of fileMap) {\n if (!filePath.endsWith('.yaml')) continue;\n\n const yamlContent = (await file.content()).toString('utf-8');\n const parsed = AssetParser.parseYaml(yamlContent, filePath);\n\n if (!parsed) {\n logger.warn(\n `dev-ai-hub: skipping invalid YAML at ${filePath} (provider ${provider.id})`,\n );\n continue;\n }\n\n if (\n provider.filters?.types &&\n !provider.filters.types.includes(parsed.meta.type)\n ) {\n continue;\n }\n if (provider.filters?.tools) {\n const hasMatchingTool = parsed.meta.tools.some(t =>\n provider.filters!.tools!.includes(t),\n );\n if (!hasMatchingTool) continue;\n }\n\n // Resolve the .md file:\n // - explicit: yaml has a content: field → use that exact path\n // - junction: find the single .md co-located in the same directory\n const yamlDir = filePath.includes('/')\n ? filePath.split('/').slice(0, -1).join('/')\n : '';\n\n let resolvedMdPath: string;\n let mdFile: { content(): Promise<Buffer>; path: string } | undefined;\n\n if (parsed.mdPath) {\n resolvedMdPath = normalizePath(parsed.mdPath);\n mdFile = fileMap.get(resolvedMdPath);\n if (!mdFile) {\n logger.warn(\n `dev-ai-hub: content file \"${parsed.mdPath}\" not found for ${filePath}, skipping`,\n );\n continue;\n }\n } else {\n const mdCandidates = [...fileMap.keys()].filter(p => {\n const dir = p.includes('/') ? p.split('/').slice(0, -1).join('/') : '';\n return dir === yamlDir && p.endsWith('.md');\n });\n if (mdCandidates.length === 1) {\n resolvedMdPath = mdCandidates[0];\n mdFile = fileMap.get(resolvedMdPath)!;\n } else if (mdCandidates.length > 1) {\n logger.warn(\n `dev-ai-hub: multiple .md files in \"${yamlDir || '.'}\" for ${filePath} — add a 'content' field to the YAML to specify which one, skipping`,\n );\n continue;\n } else {\n logger.warn(\n `dev-ai-hub: no .md file found for ${filePath}, skipping`,\n );\n continue;\n }\n }\n\n const mdContent = (await mdFile.content()).toString('utf-8');\n\n // For skills: read bundled resource files and store their content\n let resourcesContent: Record<string, string> | undefined;\n const resourcePaths = parsed.meta.resources;\n if (resourcePaths && resourcePaths.length > 0) {\n resourcesContent = {};\n for (const resourcePath of resourcePaths) {\n const fullPath = normalizePath(\n yamlDir ? `${yamlDir}/${resourcePath}` : resourcePath,\n );\n const resourceFile = fileMap.get(fullPath);\n if (resourceFile) {\n resourcesContent[resourcePath] = (await resourceFile.content()).toString('utf-8');\n } else {\n logger.warn(\n `dev-ai-hub: resource file not found: ${fullPath} (asset ${filePath})`,\n );\n }\n }\n if (Object.keys(resourcesContent).length === 0) resourcesContent = undefined;\n }\n\n const asset = AssetParser.buildAsset(\n parsed,\n mdContent,\n provider.id,\n provider.target,\n provider.branch,\n filePath,\n resolvedMdPath,\n resourcesContent,\n );\n\n await store.upsertAsset(asset);\n syncedIds.push(asset.id);\n }\n\n await store.deleteAssetsNotIn(provider.id, syncedIds);\n\n await store.upsertSyncStatus({\n providerId: provider.id,\n lastSync: new Date().toISOString(),\n status: 'idle',\n assetCount: syncedIds.length,\n });\n\n logger.info(\n `dev-ai-hub: sync complete for provider \"${provider.id}\" — ${syncedIds.length} assets`,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.options.logger.error(\n `dev-ai-hub: sync failed for provider \"${provider.id}\": ${message}`,\n );\n await store.upsertSyncStatus({\n providerId: provider.id,\n status: 'error',\n error: message,\n assetCount: 0,\n });\n }\n }\n\n private async syncExternalProvider(provider: AiAssetProvider): Promise<void> {\n const { logger, store } = this.options;\n\n logger.info(`dev-ai-hub: syncing external provider \"${provider.id}\"`);\n\n await store.upsertSyncStatus({\n providerId: provider.id,\n status: 'syncing',\n assetCount: 0,\n });\n\n try {\n const assets = await provider.getAssets();\n const syncedIds: string[] = [];\n\n for (const assetData of assets) {\n const id = AssetParser.buildId(provider.id, assetData.yamlPath);\n await store.upsertAsset({ ...assetData, id });\n syncedIds.push(id);\n }\n\n await store.deleteAssetsNotIn(provider.id, syncedIds);\n\n await store.upsertSyncStatus({\n providerId: provider.id,\n lastSync: new Date().toISOString(),\n status: 'idle',\n assetCount: syncedIds.length,\n });\n\n logger.info(\n `dev-ai-hub: external sync complete for \"${provider.id}\" — ${syncedIds.length} assets`,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(\n `dev-ai-hub: external sync failed for \"${provider.id}\": ${message}`,\n );\n await store.upsertSyncStatus({\n providerId: provider.id,\n status: 'error',\n error: message,\n assetCount: 0,\n });\n }\n }\n}\n\nfunction normalizePath(p: string): string {\n return p.replace(/\\\\/g, '/').replace(/^\\//, '');\n}\n\nfunction buildTreeUrl(provider: ProviderConfig): string {\n const base = provider.target.replace(/\\.git$/, '');\n const { branch, type } = provider;\n\n switch (type) {\n case 'gitlab':\n return `${base}/-/tree/${branch}/`;\n case 'bitbucket':\n return `${base}/src/${branch}/`;\n case 'azure-devops':\n return `${base}?version=GB${branch}`;\n case 'github':\n case 'git':\n default:\n return `${base}/tree/${branch}/`;\n }\n}\n"],"names":["AssetParser"],"mappings":"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"}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var yaml = require('js-yaml');
|
|
4
|
-
var path = require('path');
|
|
5
|
-
var pluginDevAiHubCommon = require('@nospt/plugin-dev-ai-hub-common');
|
|
6
|
-
|
|
7
|
-
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
8
|
-
|
|
9
|
-
var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
|
|
10
|
-
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
11
|
-
|
|
12
|
-
class AssetParser {
|
|
13
|
-
/**
|
|
14
|
-
* Parse the YAML metadata file (the envelope).
|
|
15
|
-
* Returns null when the YAML is invalid or missing required fields.
|
|
16
|
-
*/
|
|
17
|
-
static parseYaml(yamlContent, yamlFilePath) {
|
|
18
|
-
let data;
|
|
19
|
-
try {
|
|
20
|
-
data = yaml__default.default.load(yamlContent);
|
|
21
|
-
} catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
const result = pluginDevAiHubCommon.AiAssetFrontmatterSchema.safeParse(data);
|
|
25
|
-
if (!result.success) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
const meta = result.data;
|
|
29
|
-
const mdPath = meta.content ? path__default.default.posix.join(path__default.default.posix.dirname(yamlFilePath), meta.content) : void 0;
|
|
30
|
-
return { meta, mdPath, yamlRaw: yamlContent };
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Build the full AiAssetInput from parsed metadata + raw markdown content.
|
|
34
|
-
* The mdContent is stored verbatim — never modified.
|
|
35
|
-
* actualMdPath is the resolved path of the md file as found by the sync service.
|
|
36
|
-
*/
|
|
37
|
-
static buildAsset(parsed, mdContent, providerId, repoUrl, branch, yamlFilePath, actualMdPath, resourcesContent) {
|
|
38
|
-
const { meta } = parsed;
|
|
39
|
-
const metadata = {};
|
|
40
|
-
if (meta.resources) metadata.resources = meta.resources;
|
|
41
|
-
if (meta.mcpServers) metadata.mcpServers = meta.mcpServers;
|
|
42
|
-
if (meta.steps) metadata.steps = meta.steps;
|
|
43
|
-
return {
|
|
44
|
-
id: AssetParser.buildId(providerId, yamlFilePath),
|
|
45
|
-
providerId,
|
|
46
|
-
name: meta.name,
|
|
47
|
-
label: meta.label,
|
|
48
|
-
description: meta.description,
|
|
49
|
-
type: meta.type,
|
|
50
|
-
tools: meta.tools,
|
|
51
|
-
tags: meta.tags ?? [],
|
|
52
|
-
author: meta.author ?? "Unknown",
|
|
53
|
-
icon: meta.icon,
|
|
54
|
-
version: meta.version ?? "1.0.0",
|
|
55
|
-
installPath: meta.installPath,
|
|
56
|
-
installPaths: meta.installPaths,
|
|
57
|
-
content: mdContent,
|
|
58
|
-
yamlRaw: parsed.yamlRaw,
|
|
59
|
-
metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
|
|
60
|
-
resourcesContent,
|
|
61
|
-
yamlPath: yamlFilePath,
|
|
62
|
-
mdPath: actualMdPath,
|
|
63
|
-
repoUrl,
|
|
64
|
-
branch
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
static buildId(providerId, yamlPath) {
|
|
68
|
-
const normalized = yamlPath.replace(/\\/g, "/").replace(/^\//, "");
|
|
69
|
-
return Buffer.from(`${providerId}:${normalized}`).toString("base64url");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
exports.AssetParser = AssetParser;
|
|
74
|
-
//# sourceMappingURL=AssetParser.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AssetParser.cjs.js","sources":["../../src/service/AssetParser.ts"],"sourcesContent":["import yaml from 'js-yaml';\nimport path from 'path';\nimport { AiAssetFrontmatterSchema } from '@nospt/plugin-dev-ai-hub-common';\nimport type { AiAssetFrontmatter } from '@nospt/plugin-dev-ai-hub-common';\nimport type { AiAssetInput } from '../types';\n\nexport interface ParsedAssetMeta {\n meta: AiAssetFrontmatter;\n /**\n * Resolved explicit .md path — only set when the YAML has a `content:` field.\n * When absent, the sync service resolves the md file by directory junction.\n */\n mdPath?: string;\n yamlRaw: string;\n}\n\nexport class AssetParser {\n /**\n * Parse the YAML metadata file (the envelope).\n * Returns null when the YAML is invalid or missing required fields.\n */\n static parseYaml(\n yamlContent: string,\n yamlFilePath: string,\n ): ParsedAssetMeta | null {\n let data: unknown;\n try {\n data = yaml.load(yamlContent);\n } catch {\n return null;\n }\n\n const result = AiAssetFrontmatterSchema.safeParse(data);\n if (!result.success) {\n return null;\n }\n\n const meta = result.data;\n\n // Only resolve mdPath when content: is explicitly set in the YAML.\n // Otherwise the sync service pairs yaml + md by directory junction.\n const mdPath = meta.content\n ? path.posix.join(path.posix.dirname(yamlFilePath), meta.content)\n : undefined;\n\n return { meta, mdPath, yamlRaw: yamlContent };\n }\n\n /**\n * Build the full AiAssetInput from parsed metadata + raw markdown content.\n * The mdContent is stored verbatim — never modified.\n * actualMdPath is the resolved path of the md file as found by the sync service.\n */\n static buildAsset(\n parsed: ParsedAssetMeta,\n mdContent: string,\n providerId: string,\n repoUrl: string,\n branch: string,\n yamlFilePath: string,\n actualMdPath: string,\n resourcesContent?: Record<string, string>,\n ): AiAssetInput {\n const { meta } = parsed;\n\n // Store extra fields in metadata (used for display/reference)\n const metadata: Record<string, unknown> = {};\n if (meta.resources) metadata.resources = meta.resources;\n if ((meta as any).mcpServers) metadata.mcpServers = (meta as any).mcpServers;\n if ((meta as any).steps) metadata.steps = (meta as any).steps;\n\n return {\n id: AssetParser.buildId(providerId, yamlFilePath),\n providerId,\n name: meta.name,\n label: meta.label,\n description: meta.description,\n type: meta.type,\n tools: meta.tools,\n tags: meta.tags ?? [],\n author: meta.author ?? 'Unknown',\n icon: meta.icon,\n version: meta.version ?? '1.0.0',\n installPath: meta.installPath,\n installPaths: meta.installPaths,\n content: mdContent,\n yamlRaw: parsed.yamlRaw,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n resourcesContent,\n yamlPath: yamlFilePath,\n mdPath: actualMdPath,\n repoUrl,\n branch,\n };\n }\n\n static buildId(providerId: string, yamlPath: string): string {\n // Simple deterministic ID: provider + normalized path\n const normalized = yamlPath.replace(/\\\\/g, '/').replace(/^\\//, '');\n return Buffer.from(`${providerId}:${normalized}`).toString('base64url');\n }\n\n}\n"],"names":["yaml","AiAssetFrontmatterSchema","path"],"mappings":";;;;;;;;;;;AAgBO,MAAM,WAAA,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAKvB,OAAO,SAAA,CACL,WAAA,EACA,YAAA,EACwB;AACxB,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAOA,qBAAA,CAAK,KAAK,WAAW,CAAA;AAAA,IAC9B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,MAAA,GAASC,6CAAA,CAAyB,SAAA,CAAU,IAAI,CAAA;AACtD,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AAIpB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,GAChBC,qBAAA,CAAK,KAAA,CAAM,IAAA,CAAKA,qBAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,GAC9D,MAAA;AAEJ,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,WAAA,EAAY;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WACL,MAAA,EACA,SAAA,EACA,YACA,OAAA,EACA,MAAA,EACA,YAAA,EACA,YAAA,EACA,gBAAA,EACc;AACd,IAAA,MAAM,EAAE,MAAK,GAAI,MAAA;AAGjB,IAAA,MAAM,WAAoC,EAAC;AAC3C,IAAA,IAAI,IAAA,CAAK,SAAA,EAAW,QAAA,CAAS,SAAA,GAAY,IAAA,CAAK,SAAA;AAC9C,IAAA,IAAK,IAAA,CAAa,UAAA,EAAY,QAAA,CAAS,UAAA,GAAc,IAAA,CAAa,UAAA;AAClE,IAAA,IAAK,IAAA,CAAa,KAAA,EAAO,QAAA,CAAS,KAAA,GAAS,IAAA,CAAa,KAAA;AAExD,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,WAAA,CAAY,OAAA,CAAQ,UAAA,EAAY,YAAY,CAAA;AAAA,MAChD,UAAA;AAAA,MACA,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,IAAA,EAAM,IAAA,CAAK,IAAA,IAAQ,EAAC;AAAA,MACpB,MAAA,EAAQ,KAAK,MAAA,IAAU,SAAA;AAAA,MACvB,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAA,EAAS,KAAK,OAAA,IAAW,OAAA;AAAA,MACzB,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,OAAA,EAAS,SAAA;AAAA,MACT,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,CAAE,MAAA,GAAS,IAAI,QAAA,GAAW,MAAA;AAAA,MACxD,gBAAA;AAAA,MACA,QAAA,EAAU,YAAA;AAAA,MACV,MAAA,EAAQ,YAAA;AAAA,MACR,OAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA,EAEA,OAAO,OAAA,CAAQ,UAAA,EAAoB,QAAA,EAA0B;AAE3D,IAAA,MAAM,UAAA,GAAa,SAAS,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACjE,IAAA,OAAO,MAAA,CAAO,KAAK,CAAA,EAAG,UAAU,IAAI,UAAU,CAAA,CAAE,CAAA,CAAE,QAAA,CAAS,WAAW,CAAA;AAAA,EACxE;AAEF;;;;"}
|