create-loopengine 0.1.56 → 0.1.58

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-loopengine",
3
- "version": "0.1.56",
3
+ "version": "0.1.58",
4
4
  "description": "Scaffold a new loopengine agent project — a runnable HTTP server with one example agent, in your own repo.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -2696,7 +2696,20 @@ async function handleSlackInteraction(req: IncomingMessage, res: ServerResponse,
2696
2696
  }
2697
2697
  }
2698
2698
 
2699
+ // Set once shutdown() starts, so /healthz turns 503 while the server
2700
+ // drains and a router or load balancer stops sending it new requests.
2701
+ let shuttingDown = false
2702
+
2699
2703
  const server = createServer(async (req, res) => {
2704
+ // Liveness for whatever runs this server (Docker, Fly, a router): no
2705
+ // login, nothing about the server in the answer, and not counted as
2706
+ // activity, so polling it never keeps an idle server awake.
2707
+ if ((req.method === 'GET' || req.method === 'HEAD') && (req.url ?? '/').split('?')[0] === '/healthz') {
2708
+ res.writeHead(shuttingDown ? 503 : 200, { 'content-type': 'application/json', 'cache-control': 'no-store' })
2709
+ res.end(req.method === 'HEAD' ? undefined : JSON.stringify({ ok: !shuttingDown }))
2710
+ return
2711
+ }
2712
+
2700
2713
  const slackHookMatch = req.method === 'POST' && (req.url ?? '/').split('?')[0].match(/^\/hooks\/slack\/([^/]+)$/)
2701
2714
  if (slackHookMatch) {
2702
2715
  try {
@@ -2773,6 +2786,13 @@ const server = createServer(async (req, res) => {
2773
2786
  // web/playground.ts. GET, not POST, and an exact path match
2774
2787
  // (neither has a :name segment), so no risk of colliding with the
2775
2788
  // regexes above (already partitioned by method).
2789
+ // The bare address is the console itself, the same page as
2790
+ // /agents/config (all its links and requests use absolute paths).
2791
+ if (req.method === 'GET' && pathname === '/') {
2792
+ res.writeHead(200, { 'content-type': 'text/html' }).end(agentsConfigPageHtml)
2793
+ return
2794
+ }
2795
+
2776
2796
  if (req.method === 'GET' && pathname === '/playground') {
2777
2797
  res.writeHead(200, { 'content-type': 'text/html' }).end(playgroundHtml)
2778
2798
  return
@@ -3334,6 +3354,7 @@ async function warmAgentTools(): Promise<void> {
3334
3354
  // process restart, just this one process's own event loop.
3335
3355
  async function shutdown() {
3336
3356
  console.log('[loopengine] shutting down — draining in-flight requests...')
3357
+ shuttingDown = true
3337
3358
  scheduler.stop()
3338
3359
  const graceMs = Number(process.env.LOOPENGINE_SHUTDOWN_GRACE_MS ?? 30000)
3339
3360
  const closed = new Promise<void>((resolve) => server.close(() => resolve()))
@@ -9,7 +9,7 @@
9
9
  "cli": "tsx adapters/cli.ts"
10
10
  },
11
11
  "dependencies": {
12
- "loopengine": "^0.1.71",
12
+ "loopengine": "^0.1.73",
13
13
  "actauth": "^0.0.12"
14
14
  },
15
15
  "devDependencies": {