feat: migrate to DSH 0.1.5-rc.2 with TypeScript refactor, official slot footer and codex selector

This commit is contained in:
2026-09-11 13:58:29 +08:00
parent 4401e9cea7
commit fa098b5192
27 changed files with 4976 additions and 6727 deletions
+27 -97
View File
@@ -1,22 +1,17 @@
import fs from 'node:fs';
import path from 'node:path';
export const name = 'dsh-plugin-model-enhancer';
export const inject = ['webServer'];
const name = "dsh-plugin-model-enhancer";
const inject = ["webServer"];
let cachedData = null;
let lastFetchedAt = 0;
const CACHE_TTL_MS = 3600 * 1000; // 1 hour
const CACHE_TTL_MS = 3600 * 1e3;
async function getModelsDevData() {
const now = Date.now();
if (cachedData && now - lastFetchedAt < CACHE_TTL_MS) {
return cachedData;
}
try {
const res = await fetch('https://models.dev/api.json', {
const res = await fetch("https://models.dev/api.json", {
headers: {
'User-Agent': 'DSH-Model-Enhancer/1.0.0'
"User-Agent": "DSH-Model-Enhancer/1.0.0"
}
});
if (!res.ok) {
@@ -28,114 +23,49 @@ async function getModelsDevData() {
return json;
} catch (err) {
if (cachedData) {
// Fallback to stale cache if network fails
return cachedData;
}
throw err;
}
}
export function apply(ctx) {
// 1. Models.dev Cache Proxy
function apply(ctx) {
ctx.effect(() => {
return ctx.webServer.register({
kind: 'exact',
path: '/api/models-dev/models',
kind: "exact",
path: "/api/models-dev/models",
handler: async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
if (req.method === "OPTIONS") {
res.writeHead(204);
res.end();
return;
}
if (req.method !== 'GET') {
res.writeHead(405, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Method Not Allowed' }));
if (req.method !== "GET") {
res.writeHead(405, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Method Not Allowed" }));
return;
}
try {
const data = await getModelsDevData();
res.writeHead(200, {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=3600'
"Content-Type": "application/json",
"Cache-Control": "public, max-age=3600"
});
res.end(JSON.stringify(data));
} catch (err) {
ctx.logger?.error?.('[model-enhancer] Error fetching models.dev:', err);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: err.message || 'Internal Server Error' }));
ctx.logger?.error?.("[model-enhancer] Error fetching models.dev:", err);
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: err.message || "Internal Server Error" }));
}
}
});
}, 'dsh-plugin-model-enhancer: webServer proxy route');
// 2. Binary / Large Document File Upload to Workspace Endpoint
ctx.effect(() => {
return ctx.webServer.register({
kind: 'exact',
path: '/api/model-enhancer/upload',
handler: async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Filename');
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
if (req.method !== 'POST') {
res.writeHead(405, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Method Not Allowed' }));
return;
}
try {
const urlObj = new URL(req.url, 'http://127.0.0.1');
const rawName = req.headers['x-filename'] || urlObj.searchParams.get('filename') || `upload_${Date.now()}.bin`;
const decodedName = decodeURIComponent(rawName);
const safeName = path.basename(decodedName);
const uploadDir = path.join(process.cwd(), 'uploads');
fs.mkdirSync(uploadDir, { recursive: true });
const targetPath = path.join(uploadDir, safeName);
const writeStream = fs.createWriteStream(targetPath);
let totalBytes = 0;
req.on('data', (chunk) => {
totalBytes += chunk.length;
});
req.pipe(writeStream);
writeStream.on('finish', () => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
ok: true,
filename: safeName,
path: path.join('uploads', safeName),
size: totalBytes
}));
});
writeStream.on('error', (err) => {
ctx.logger?.error?.('[model-enhancer] Upload stream error:', err);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: err.message || 'File write error' }));
});
} catch (err) {
ctx.logger?.error?.('[model-enhancer] Upload handler error:', err);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: err.message || 'Upload processing error' }));
}
}
});
}, 'dsh-plugin-model-enhancer: workspace file upload endpoint');
}, "dsh-plugin-model-enhancer: webServer proxy route");
}
export {
apply,
getModelsDevData,
inject,
name
};