create-loopengine 0.1.75 → 0.1.76

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.75",
3
+ "version": "0.1.76",
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",
@@ -197,6 +197,10 @@ import {
197
197
  setModelProviderKey,
198
198
  clearModelProviderKey,
199
199
  ModelKeyError,
200
+ describeTimeZone,
201
+ setWorkspaceTimeZone,
202
+ TimeZoneError,
203
+ workspaceTimeZone,
200
204
  describeGateways,
201
205
  scaffoldAgent,
202
206
  AgentNameError,
@@ -1294,7 +1298,7 @@ function scheduleJson(res: ServerResponse, status: number, body: unknown): void
1294
1298
 
1295
1299
  async function handleSchedulesGet(res: ServerResponse, agentName: string): Promise<void> {
1296
1300
  if (!getEntry(agentName)) return scheduleJson(res, 404, { error: `unknown agent '${agentName}'` })
1297
- scheduleJson(res, 200, { tasks: await listScheduledTasks({ agent: agentName }) })
1301
+ scheduleJson(res, 200, { tasks: await listScheduledTasks({ agent: agentName }), time_zone: workspaceTimeZone() })
1298
1302
  }
1299
1303
 
1300
1304
  async function handleSchedulesPost(req: IncomingMessage, res: ServerResponse, agentName: string): Promise<void> {
@@ -1304,7 +1308,7 @@ async function handleSchedulesPost(req: IncomingMessage, res: ServerResponse, ag
1304
1308
  const task = await createScheduledTask({
1305
1309
  agent: agentName,
1306
1310
  message: String(body.message ?? ''),
1307
- schedule: (body.schedule ?? {}) as { run_at?: unknown; every?: unknown; start_at?: unknown },
1311
+ schedule: (body.schedule ?? {}) as { run_at?: unknown; every?: unknown; start_at?: unknown; at?: unknown; weekday?: unknown },
1308
1312
  task_name: typeof body.task_name === 'string' ? body.task_name : undefined,
1309
1313
  notify: body.notify === true,
1310
1314
  })
@@ -3374,6 +3378,7 @@ const server = createServer(async (req, res) => {
3374
3378
  environment: process.env.LOOPENGINE_ENV ?? 'production',
3375
3379
  publicUrl: process.env.LOOPENGINE_PUBLIC_URL ?? null,
3376
3380
  scheduler: process.env.LOOPENGINE_SCHEDULER === 'off' ? 'off' : 'on',
3381
+ timeZone: workspaceTimeZone(),
3377
3382
  }),
3378
3383
  )
3379
3384
  return
@@ -3433,6 +3438,29 @@ const server = createServer(async (req, res) => {
3433
3438
  res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ ok: true }))
3434
3439
  return
3435
3440
  }
3441
+ // Settings → Time zone (web/global-config.ts): what "9:00" means in
3442
+ // schedules. Saved like a model key, so refused without auth too.
3443
+ if (req.method === 'GET' && pathname === '/config/time-zone') {
3444
+ res.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' }).end(JSON.stringify({ ...describeTimeZone(), canSave: secretsProtected }))
3445
+ return
3446
+ }
3447
+ if (req.method === 'PUT' && pathname === '/config/time-zone') {
3448
+ if (!secretsProtected) {
3449
+ res.writeHead(403, { 'content-type': 'application/json' }).end(
3450
+ JSON.stringify({ error: 'Refusing to change settings without LOOPENGINE_ADMIN_AUTH configured: set it first, or put LOOPENGINE_TIME_ZONE in .env.' }),
3451
+ )
3452
+ return
3453
+ }
3454
+ try {
3455
+ const body = await readJsonBody(req)
3456
+ const outcome = await setWorkspaceTimeZone(body.timeZone, { moveSchedules: body.moveSchedules === true })
3457
+ res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ ok: true, ...outcome }))
3458
+ } catch (err) {
3459
+ const status = err instanceof TimeZoneError ? 400 : 500
3460
+ res.writeHead(status, { 'content-type': 'application/json' }).end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }))
3461
+ }
3462
+ return
3463
+ }
3436
3464
  if (req.method === 'GET' && pathname === '/config/gateways') {
3437
3465
  res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify(await describeGateways()))
3438
3466
  return
@@ -9,7 +9,7 @@
9
9
  "cli": "tsx adapters/cli.ts"
10
10
  },
11
11
  "dependencies": {
12
- "loopengine": "^0.1.93",
12
+ "loopengine": "^0.1.94",
13
13
  "actauth": "^0.0.12",
14
14
  "tsx": "^4.19.0",
15
15
  "typescript": "^5.7.0"