create-loopengine 0.1.20 → 0.1.22
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 +64 -0
- package/template/package.json +1 -1
package/package.json
CHANGED
|
@@ -85,6 +85,9 @@ import {
|
|
|
85
85
|
deleteSkill,
|
|
86
86
|
SkillInvalidIdError,
|
|
87
87
|
SkillNotFoundError,
|
|
88
|
+
listDeclaredEnvVars,
|
|
89
|
+
setEnvVar,
|
|
90
|
+
EnvVarNameError,
|
|
88
91
|
listSkillgardenCatalog,
|
|
89
92
|
readSkillgardenCatalogEntry,
|
|
90
93
|
addSkillgardenSkillToAgent,
|
|
@@ -503,6 +506,7 @@ function parseHttpToolBody(body: Record<string, unknown>): { ok: true; value: Ht
|
|
|
503
506
|
headers: body.headers as HttpToolSpec['headers'],
|
|
504
507
|
sendFieldsAsJsonBody: body.sendFieldsAsJsonBody === true,
|
|
505
508
|
responseJsonPath: body.responseJsonPath as string | undefined,
|
|
509
|
+
safe: body.safe === true,
|
|
506
510
|
},
|
|
507
511
|
decision: body.decision as Decision | undefined,
|
|
508
512
|
}
|
|
@@ -920,6 +924,53 @@ function handleSkillDelete(res: ServerResponse, agentName: string, skillId: stri
|
|
|
920
924
|
res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ ok: true }))
|
|
921
925
|
}
|
|
922
926
|
|
|
927
|
+
// Backs the Admin UI's "Environment" section — every env var a package
|
|
928
|
+
// (see loopengine's own PACKAGES.md, bin/package-manager.ts) declared it
|
|
929
|
+
// needs for this agent, with set/not-set status only. Read-only, so no
|
|
930
|
+
// extra auth gate beyond the normal Basic Auth middleware every admin
|
|
931
|
+
// route already has.
|
|
932
|
+
function handleEnvGet(res: ServerResponse, agentName: string): void {
|
|
933
|
+
if (!getEntry(agentName)) {
|
|
934
|
+
res.writeHead(404, { 'content-type': 'application/json' }).end(JSON.stringify({ error: `unknown agent '${agentName}'` }))
|
|
935
|
+
return
|
|
936
|
+
}
|
|
937
|
+
res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify(listDeclaredEnvVars(agentName)))
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
// Writes a raw secret value into .env — meaningfully more sensitive than
|
|
941
|
+
// the rest of the admin surface (config/business data vs. an actual
|
|
942
|
+
// credential), so unlike every other route here, this one refuses
|
|
943
|
+
// outright when LOOPENGINE_ADMIN_AUTH isn't set at all, rather than just
|
|
944
|
+
// warning at startup and proceeding open like the rest of this file does
|
|
945
|
+
// (see loopengine's own PACKAGES.md, "Managing package secrets in the
|
|
946
|
+
// Admin UI" — LOOPENGINE_ADMIN_AUTH being optional today is an
|
|
947
|
+
// acceptable gap for config, not for secrets).
|
|
948
|
+
async function handleEnvPut(req: IncomingMessage, res: ServerResponse, agentName: string, varName: string): Promise<void> {
|
|
949
|
+
if (!adminAuth) {
|
|
950
|
+
res.writeHead(403, { 'content-type': 'application/json' }).end(
|
|
951
|
+
JSON.stringify({ error: 'Refusing to set an env var without LOOPENGINE_ADMIN_AUTH configured — set it before managing secrets through this route.' }),
|
|
952
|
+
)
|
|
953
|
+
return
|
|
954
|
+
}
|
|
955
|
+
if (!getEntry(agentName)) {
|
|
956
|
+
res.writeHead(404, { 'content-type': 'application/json' }).end(JSON.stringify({ error: `unknown agent '${agentName}'` }))
|
|
957
|
+
return
|
|
958
|
+
}
|
|
959
|
+
const body = await readJsonBody(req)
|
|
960
|
+
if (typeof body.value !== 'string') {
|
|
961
|
+
res.writeHead(400, { 'content-type': 'application/json' }).end(JSON.stringify({ error: 'value is required' }))
|
|
962
|
+
return
|
|
963
|
+
}
|
|
964
|
+
try {
|
|
965
|
+
setEnvVar(varName, body.value)
|
|
966
|
+
} catch (err) {
|
|
967
|
+
const status = err instanceof EnvVarNameError ? 400 : 500
|
|
968
|
+
res.writeHead(status, { 'content-type': 'application/json' }).end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }))
|
|
969
|
+
return
|
|
970
|
+
}
|
|
971
|
+
res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ ok: true }))
|
|
972
|
+
}
|
|
973
|
+
|
|
923
974
|
// Backs the Skills tab's "Browse skillgarden catalog" section — a
|
|
924
975
|
// read-only, agent-independent list of everything skillgarden ships in
|
|
925
976
|
// its own bundled registry (see loopengine's own web/skillgarden-admin.ts).
|
|
@@ -2119,6 +2170,19 @@ const server = createServer(async (req, res) => {
|
|
|
2119
2170
|
return
|
|
2120
2171
|
}
|
|
2121
2172
|
|
|
2173
|
+
// Backs the Admin UI's "Environment" section — see
|
|
2174
|
+
// handleEnvGet/handleEnvPut's own doc comments above.
|
|
2175
|
+
const envListMatch = pathname.match(/^\/agents\/([^/]+)\/env$/)
|
|
2176
|
+
if (envListMatch && req.method === 'GET') {
|
|
2177
|
+
handleEnvGet(res, decodeURIComponent(envListMatch[1]))
|
|
2178
|
+
return
|
|
2179
|
+
}
|
|
2180
|
+
const envVarMatch = pathname.match(/^\/agents\/([^/]+)\/env\/([^/]+)$/)
|
|
2181
|
+
if (envVarMatch && req.method === 'PUT') {
|
|
2182
|
+
await handleEnvPut(req, res, decodeURIComponent(envVarMatch[1]), decodeURIComponent(envVarMatch[2]))
|
|
2183
|
+
return
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2122
2186
|
// Backs the Skills tab's "Browse skillgarden catalog" section — see
|
|
2123
2187
|
// the three handlers above it.
|
|
2124
2188
|
if (req.method === 'GET' && pathname === '/skillgarden-catalog') {
|