feat: Functions — JS/TS execution with run log

core.functions + core.function_runs: project-scoped code executed by a
runtime binary on the backend host (bun or deno per function). Payload
arrives on stdin + PRIMORA_PAYLOAD env; stdout/stderr captured per run
(capped), with status/exit code/duration. Invoke returns 502 + the
recorded run on failure so errors stay observable.

Dashboard gains a Functions page: code editor, JSON payload invoke,
live result, run history. Runner config via FUNCTIONS_RUNTIME /
FUNCTIONS_TIMEOUT_SECONDS / FUNCTIONS_MAX_OUTPUT_BYTES.

Verified live: bun ran code, stdin payload delivered, error path returns
502 with captured stderr; timeout kills at deadline.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-24 19:46:32 +02:00
1 parent 3aca5bd1e0
commit 32587c8063
37 files changed
+2157 -6

No files matched your search

+7
View File
@@ -84,6 +84,13 @@ func (h *HTTPHandler) Register(router *gin.Engine) {
api.POST("/projects/:projectID/inbound-hooks", h.createInboundHook)
api.DELETE("/projects/:projectID/inbound-hooks/:hookID", h.deleteInboundHook)
api.GET("/projects/:projectID/emails", h.listEmailLog)
api.GET("/projects/:projectID/functions", h.listFunctions)
api.POST("/projects/:projectID/functions", h.createFunction)
api.GET("/projects/:projectID/functions/:functionID", h.getFunction)
api.PUT("/projects/:projectID/functions/:functionID", h.updateFunction)
api.DELETE("/projects/:projectID/functions/:functionID", h.deleteFunction)
api.POST("/projects/:projectID/functions/:functionID/invoke", h.invokeFunction)
api.GET("/projects/:projectID/functions/:functionID/runs", h.listFunctionRuns)
api.GET("/projects/:projectID/events", h.listEvents)
api.GET("/projects/:projectID/issues", h.listIssues)
api.GET("/projects/:projectID/components", h.listComponents)