create-loopengine 0.1.73 → 0.1.74
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/package.json +1 -1
- package/template/adapters/http.ts +53 -0
- package/template/package.json +1 -1
package/package.json
CHANGED
|
@@ -82,10 +82,16 @@ import {
|
|
|
82
82
|
interviewTools,
|
|
83
83
|
listInterviews,
|
|
84
84
|
pickInterviewModel,
|
|
85
|
+
pickAgentModel,
|
|
85
86
|
previewCandidate,
|
|
86
87
|
startInterview,
|
|
87
88
|
setInterviewProject,
|
|
88
89
|
type InterviewAgentSource,
|
|
90
|
+
templatesPageHtml,
|
|
91
|
+
TemplateError,
|
|
92
|
+
createFromTemplate,
|
|
93
|
+
listTemplates,
|
|
94
|
+
previewTemplate,
|
|
89
95
|
globalConfigPageHtml,
|
|
90
96
|
addGatewayTool,
|
|
91
97
|
agentDir,
|
|
@@ -958,6 +964,44 @@ async function handleInterviews(req: IncomingMessage, res: ServerResponse, pathn
|
|
|
958
964
|
}
|
|
959
965
|
}
|
|
960
966
|
|
|
967
|
+
// Templates (loopengine's web/templates-admin.ts): ready-made agents,
|
|
968
|
+
// created through the same scaffold and registration as Agents → + New.
|
|
969
|
+
// A template agent takes the model of an agent that already works here,
|
|
970
|
+
// as an interview's does; with none, it starts on the scaffold's default.
|
|
971
|
+
async function handleStarterTemplates(req: IncomingMessage, res: ServerResponse, pathname: string): Promise<void> {
|
|
972
|
+
const json = (status: number, body: unknown): void => {
|
|
973
|
+
res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store' }).end(JSON.stringify(body))
|
|
974
|
+
}
|
|
975
|
+
const [id, action] = pathname.split('/').slice(2).map(decodeURIComponent) // after /starter-templates
|
|
976
|
+
const exists = (name: string) => Boolean(getEntry(name)) || existsSync(join(projectDir(), 'agents', name))
|
|
977
|
+
try {
|
|
978
|
+
if (!id) {
|
|
979
|
+
if (req.method === 'GET') return json(200, { templates: listTemplates() })
|
|
980
|
+
return json(405, { error: 'method not allowed' })
|
|
981
|
+
}
|
|
982
|
+
if (action === 'preview' && req.method === 'GET') return json(200, previewTemplate(id, { agentExists: exists }))
|
|
983
|
+
if (action === 'create' && req.method === 'POST') {
|
|
984
|
+
const model = pickAgentModel(interviewAgents())
|
|
985
|
+
const created = await createFromTemplate(id, {
|
|
986
|
+
agentExists: exists,
|
|
987
|
+
createAgent: async (name, systemPrompt) => {
|
|
988
|
+
const parsed = parseAgentTemplateOptions({ systemPrompt, ...(model ? { model } : {}) })
|
|
989
|
+
if (!parsed.ok) throw new TemplateError(parsed.error)
|
|
990
|
+
const indexPath = await scaffoldAgent(projectDir(), name, parsed.value)
|
|
991
|
+
registerAgent(await loadAgentModule(indexPath, indexPath))
|
|
992
|
+
},
|
|
993
|
+
})
|
|
994
|
+
return json(200, created)
|
|
995
|
+
}
|
|
996
|
+
return json(404, { error: 'not found' })
|
|
997
|
+
} catch (err) {
|
|
998
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
999
|
+
if (err instanceof TemplateError) return json(message === 'No such template' ? 404 : 400, { error: message })
|
|
1000
|
+
console.error('[loopengine] template failed:', err)
|
|
1001
|
+
return json(500, { error: `Couldn't create it: ${message}` })
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
961
1005
|
async function handleCreateAgent(req: IncomingMessage, res: ServerResponse): Promise<void> {
|
|
962
1006
|
const body = await readJsonBody(req)
|
|
963
1007
|
if (typeof body.name !== 'string' || !body.name) {
|
|
@@ -3272,6 +3316,15 @@ const server = createServer(async (req, res) => {
|
|
|
3272
3316
|
await handleInterviews(req, res, pathname)
|
|
3273
3317
|
return
|
|
3274
3318
|
}
|
|
3319
|
+
// Templates: the page, and its routes.
|
|
3320
|
+
if (req.method === 'GET' && pathname === '/templates') {
|
|
3321
|
+
res.writeHead(200, { 'content-type': 'text/html' }).end(templatesPageHtml)
|
|
3322
|
+
return
|
|
3323
|
+
}
|
|
3324
|
+
if (pathname === '/starter-templates' || pathname.startsWith('/starter-templates/')) {
|
|
3325
|
+
await handleStarterTemplates(req, res, pathname)
|
|
3326
|
+
return
|
|
3327
|
+
}
|
|
3275
3328
|
const editAgentMatch = req.method === 'PUT' && pathname.match(/^\/agents\/([^/]+)$/)
|
|
3276
3329
|
if (editAgentMatch) {
|
|
3277
3330
|
await handleEditAgent(req, res, decodeURIComponent(editAgentMatch[1]))
|