@cloud-cli/on 1.10.0 โ†’ 1.12.0

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/README.md CHANGED
@@ -177,10 +177,11 @@ npx @cloud-cli/on [command] [options]
177
177
  | `-p` | `--port` | `11235` | `PORT` | Port for the Ingress HTTP server. |
178
178
  | `-k` | `--workers` | `5` | `RUNNER_WORKERS` | Maximum concurrent jobs on this node. |
179
179
  | | | | `RUNNER_ADMIN_SECRET` | Admin token to refresh secrets via API |
180
+ | | | | `RUNNER_WORKER_SECRET` | Worker token for job events and secret retrieval |
180
181
  | | | | `RUNNER_SERVER_URL` | Webhook server URL used by workers. |
181
182
  | | | | `RUNNER_TAGS` | Comma-separated worker capability tags. |
182
183
 
183
- Set the same non-empty `RUNNER_ADMIN_SECRET` on the server and workers to publish live job-status refresh events and let workers retrieve job-scoped secrets. The dashboard workflow APIs accept either Bearer authentication or HTTP Basic authentication with username `admin` and this secret.
184
+ Set `RUNNER_ADMIN_SECRET` only on the HTTP server for dashboard and management APIs. Set the same non-empty `RUNNER_WORKER_SECRET` on the server and every worker to publish job-status refresh events and retrieve job-scoped secrets. The dashboard workflow APIs accept either Bearer authentication or HTTP Basic authentication with username `admin` and the admin secret.
184
185
 
185
186
  ### Secrets
186
187
 
@@ -222,6 +223,8 @@ The GitHub status plugin publishes commit states when a workflow starts and fini
222
223
 
223
224
  Run details are available as HTML at `/runs/:id` and as sanitized JSON at `/api/runs/:id`. The HTML view refreshes reactively through job-specific SSE events while a run is active. Both representations omit raw webhook bodies, sensitive input fields, execution environment values, and internal rerun state.
224
225
 
226
+ Open `/workflows` to list workflows and manage secret values. Open `/workflows/new` to create a definition or `/workflows/:id` to edit one. These pages are protected by the administrator HTTP Basic credential; secret values are write-only.
227
+
225
228
  ---
226
229
 
227
230
  ## ๐Ÿ“ Deterministic Evaluation Rules
@@ -298,14 +301,10 @@ The Ingress Gateway listens for incoming HTTP requests and serves the live web U
298
301
 
299
302
  ## systemd Deployment
300
303
 
301
- Install the unit files from `systemd/`, create a non-login `on` user, and create a root-owned `/etc/on/runner.env` with `RUNNER_DATABASE_URL`, `RUNNER_SERVER_URL`, `RUNNER_ADMIN_SECRET`, `RUNNER_TAGS`, and `RUNNER_TMP`. Use `systemctl edit` for per-machine overrides.
304
+ Install the unit files from `systemd/` and create root-owned environment files in `/etc/on/`: `server.env` for `RUNNER_DATABASE_URL`, `RUNNER_SERVER_URL`, `RUNNER_ADMIN_SECRET`, and `RUNNER_WORKER_SECRET`; `scheduler.env` for `RUNNER_DATABASE_URL`; and `worker.env` for `RUNNER_DATABASE_URL`, `RUNNER_SERVER_URL`, `RUNNER_WORKER_SECRET`, `RUNNER_TAGS`, and `RUNNER_TMP`. Workers receive only `RUNNER_WORKER_SECRET`; the admin secret stays on the HTTP server. The supplied units run as root because the systemd execution driver creates transient system services. Use `systemctl edit` for per-machine overrides.
302
305
 
303
306
  Place the server master key in `/etc/on/credentials/on-master-key` with permissions readable only by the `on` user. `runner-server.service` exposes it privately through systemd's credentials directory. Start the primary control plane with `systemctl enable --now runner.target`; enable `runner-worker.service` separately on worker machines. Use `systemctl edit runner-worker.service` for machine-specific labels and paths.
304
307
 
305
- ## Database Migration
306
-
307
- Before deploying the revision-reference queue code to an existing database, run `migrations/20260904_job_workflow_revisions.sql` once through the SQLite HTTPS query service. It adds `jobs.workflow_revision` and `jobs.required_tags`, backfills routing tags, links jobs to the currently published workflow revision, and cancels only pending/running legacy jobs that cannot be linked. New installations receive both columns from `QueueManager.createTables()`.
308
-
309
308
  Workers now resolve the immutable revision when they claim a job. A workflow can safely use a checkout step followed by `if: files.exists('Dockerfile')`; `files` is constrained to the job's `workingDir`, so it cannot inspect files outside that workspace.
310
309
 
311
310
  ## Future Security Work
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG5D,wBAAsB,UAAU,CAAC,MAAM,KAAA,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAmBrE;AAED,wBAAgB,aAAa,CAAC,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,GAAG,YAAY,CAe7G;AAED,wBAAgB,SAAS,SAsBxB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAuB9F"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG5D,wBAAsB,UAAU,CAAC,MAAM,KAAA,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAmBrE;AAED,wBAAgB,aAAa,CAAC,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,GAAG,YAAY,CAgB7G;AAED,wBAAgB,SAAS,SAsBxB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAuB9F"}
package/dist/on.js CHANGED
@@ -66,6 +66,7 @@ function ie(e, t) {
66
66
  return {
67
67
  port: r,
68
68
  adminToken: e.adminToken ?? n.RUNNER_ADMIN_SECRET ?? "",
69
+ workerToken: e.workerToken ?? n.RUNNER_WORKER_SECRET ?? "",
69
70
  database: e.database ?? t.database ?? n.RUNNER_DATABASE_URL ?? "",
70
71
  workers: Number(e.workers ?? t.workers ?? n.RUNNER_WORKERS ?? 5),
71
72
  serverUrl: e.serverUrl ?? n.RUNNER_SERVER_URL ?? `http://127.0.0.1:${r}`,
@@ -139,12 +140,16 @@ var se = class {
139
140
  await S.run("UPDATE jobs SET status = ?, finished_at = CURRENT_TIMESTAMP WHERE id = ?;", [t, e]);
140
141
  }
141
142
  async completeJob(e, t, n) {
142
- await S.run("UPDATE jobs\n SET status = ?, report = ?, updated_at = CURRENT_TIMESTAMP, finished_at = CURRENT_TIMESTAMP\n WHERE id = ?;", [
143
+ await S.run("UPDATE jobs\n SET status = CASE WHEN status = 'cancelled' THEN 'cancelled' ELSE ? END,\n report = ?, updated_at = CURRENT_TIMESTAMP, finished_at = CURRENT_TIMESTAMP\n WHERE id = ?;", [
143
144
  t,
144
145
  JSON.stringify(n),
145
146
  e
146
147
  ]);
147
148
  }
149
+ async cancelJob(e) {
150
+ let t = await this.getJob(e);
151
+ return t ? t.status !== "pending" && t.status !== "running" ? "not_active" : (await S.run("UPDATE jobs SET status = 'cancelled', updated_at = CURRENT_TIMESTAMP, finished_at = CURRENT_TIMESTAMP\n WHERE id = ? AND status IN ('pending', 'running');", [e]), (await this.getJob(e))?.status === "cancelled" ? "cancelled" : "not_active") : "not_found";
152
+ }
148
153
  async restartJob(e) {
149
154
  let t = await this.getJob(e);
150
155
  if (t) return t.status === "running" && await S.run("UPDATE jobs SET status = 'cancelled', finished_at = CURRENT_TIMESTAMP WHERE id = ?;", [e]), (await S.get("INSERT INTO jobs (parentId, workflow_id, workflow_revision, required_tags, concurrency_key, payload) SELECT id, workflow_id, workflow_revision, required_tags, concurrency_key, payload FROM jobs WHERE id = ? RETURNING *", [e])).id;
@@ -3650,7 +3655,7 @@ var En = class {
3650
3655
  inputs: e
3651
3656
  };
3652
3657
  }
3653
- }, Dn = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Engine Dashboard</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <main class=\"max-w-6xl mx-auto space-y-6\">\n <header class=\"flex flex-col sm:flex-row sm:items-center justify-between gap-3 border-b border-gray-800 pb-4\">\n <div>\n <h1 class=\"text-2xl font-bold text-white\">Runner Engine Status</h1>\n <p class=\"text-xs text-gray-400\">Live Job Queue &amp; Execution Traces</p>\n </div>\n <div class=\"flex items-center gap-3 text-xs font-mono\">\n <span class=\"text-gray-500\">Updated {{ lastUpdated }}</span>\n <span\n class=\"px-3 py-1 rounded-full border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': !refreshError,\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': refreshError\n }\"\n >\n {{ refreshError ? 'Refresh failed' : 'System operational' }}\n </span>\n </div>\n </header>\n\n <section class=\"bg-gray-900 border border-gray-800 rounded-xl overflow-hidden hidden md:block\">\n <table class=\"w-full text-left text-sm\">\n <thead class=\"bg-gray-800/50 text-gray-400 text-xs uppercase font-mono border-b border-gray-800\">\n <tr>\n <th class=\"py-3 px-4\">Job ID</th>\n <th class=\"py-3 px-4\">Workflow</th>\n <th class=\"py-3 px-4\">Status</th>\n <th class=\"py-3 px-4 hidden xl:table-cell\">Worker</th>\n <th class=\"py-3 px-4 hidden lg:table-cell\">Created At</th>\n <th class=\"py-3 px-4 text-right\">Action</th>\n </tr>\n </thead>\n <tbody>\n <template for=\"job of jobs\">\n <tr class=\"border-b border-gray-800 hover:bg-gray-800/40 transition\">\n <td class=\"py-3 px-4 font-mono text-indigo-400\">\n <a attr-href=\"'/runs/' + job.id\" class=\"hover:underline\">#{{ job.id }}</a>\n </td>\n <td class=\"py-3 px-4 font-medium text-white\">{{ job.workflowId }}</td>\n <td class=\"py-3 px-4\">\n <span\n class=\"px-2.5 py-0.5 rounded-full text-xs font-semibold\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400': job.status === 'success',\n 'bg-rose-500/10.text-rose-400': job.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.animate-pulse': job.status === 'running',\n 'bg-gray-500/10.text-gray-400': !['success', 'failed', 'running'].includes(job.status)\n }\"\n >\n {{ upper(job.status) }}\n </span>\n </td>\n <td class=\"py-3 px-4 hidden xl:table-cell text-xs font-mono text-gray-400\">{{ job.workerId || '-' }}</td>\n <td class=\"py-3 px-4 hidden lg:table-cell text-xs text-gray-400\">{{ job.createdAt }}</td>\n <td class=\"py-3 px-4 text-right whitespace-nowrap\">\n <a attr-href=\"'/runs/' + job.id\" class=\"text-xs bg-gray-800 hover:bg-gray-700 text-gray-200 px-3 py-1 rounded border border-gray-700\">View Trace</a>\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n <template if=\"!jobs.length\">\n <div class=\"p-8 text-center text-gray-500\">No jobs recorded yet.</div>\n </template>\n </section>\n\n <section class=\"md:hidden bg-gray-900 border border-gray-800 rounded-xl divide-y divide-gray-800 overflow-hidden\">\n <template for=\"job of jobs\">\n <article class=\"p-4 bg-gray-900/60\">\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <div class=\"flex items-center gap-2\">\n <span\n class=\"w-2.5 h-2.5 rounded-full shrink-0\"\n bind-class=\"{\n 'bg-emerald-400': job.status === 'success',\n 'bg-rose-400': job.status === 'failed',\n 'bg-indigo-400.animate-pulse': job.status === 'running',\n 'bg-gray-500': !['success', 'failed', 'running'].includes(job.status)\n }\"\n ></span>\n <h2 class=\"font-medium text-white truncate\">{{ job.workflowId }}</h2>\n </div>\n <p class=\"mt-1 pl-[18px] text-xs font-mono text-gray-400\">#{{ job.id }} ยท {{ upper(job.status) }}</p>\n </div>\n <a attr-href=\"'/runs/' + job.id\" class=\"shrink-0 text-xs bg-gray-800 hover:bg-gray-700 text-gray-300 px-2.5 py-1 rounded border border-gray-700\">Trace</a>\n </div>\n </article>\n </template>\n <template if=\"!jobs.length\">\n <div class=\"p-8 text-center text-gray-500\">No jobs recorded yet.</div>\n </template>\n </section>\n\n <template if=\"hasMore\">\n <div class=\"flex justify-center\">\n <button\n class=\"px-4 py-2 text-sm text-gray-200 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded-lg\"\n on-click=\"loadMore()\"\n >\n {{ loadingMore ? 'Loading...' : 'Load more' }}\n </button>\n </div>\n </template>\n </main>\n\n <script setup>\n import { onDestroy, onInit, ref } from '@li3/web';\n\n export default function setup() {\n const jobs = ref([]);\n const lastUpdated = ref('now');\n const refreshError = ref(false);\n const hasMore = ref(false);\n const loadingMore = ref(false);\n let refreshTimer;\n let eventSource;\n let refreshing = false;\n let refreshPending = false;\n\n const upper = (value) => String(value || '').toUpperCase();\n const terminalStatuses = new Set(['success', 'failed', 'cancelled']);\n const refreshJobs = async () => {\n if (refreshing) {\n refreshPending = true;\n return;\n }\n refreshing = true;\n\n try {\n const activeIds = jobs.value\n .filter((job) => !terminalStatuses.has(job.status))\n .map((job) => Number(job.id));\n const knownIds = jobs.value.map((job) => Number(job.id));\n const afterId = activeIds.length\n ? Math.max(0, Math.min(...activeIds) - 1)\n : knownIds.length\n ? Math.max(...knownIds)\n : null;\n const url = afterId === null ? '/api/jobs?limit=500' : `/api/jobs?afterId=${afterId}&limit=500`;\n const response = await fetch(url, { headers: { accept: 'application/json' } });\n if (!response.ok) throw new Error(`Dashboard refresh failed: ${response.status}`);\n\n const data = await response.json();\n const merged = new Map(jobs.value.map((job) => [job.id, job]));\n for (const job of data.jobs) merged.set(job.id, job);\n jobs.value = Array.from(merged.values()).sort((a, b) => Number(b.id) - Number(a.id));\n lastUpdated.value = new Date().toLocaleTimeString();\n refreshError.value = false;\n } catch (error) {\n console.error(error);\n refreshError.value = true;\n } finally {\n refreshing = false;\n if (refreshPending) {\n refreshPending = false;\n void refreshJobs();\n }\n }\n };\n\n const loadMore = async () => {\n if (loadingMore.value || !hasMore.value || !jobs.value.length) return;\n loadingMore.value = true;\n\n try {\n const beforeId = Math.min(...jobs.value.map((job) => Number(job.id)));\n const response = await fetch(`/api/jobs?beforeId=${beforeId}`, {\n headers: { accept: 'application/json' },\n });\n if (!response.ok) throw new Error(`Loading older jobs failed: ${response.status}`);\n\n const data = await response.json();\n const merged = new Map(jobs.value.map((job) => [job.id, job]));\n for (const job of data.jobs) merged.set(job.id, job);\n jobs.value = Array.from(merged.values()).sort((a, b) => Number(b.id) - Number(a.id));\n hasMore.value = data.hasMore;\n } catch (error) {\n console.error(error);\n refreshError.value = true;\n } finally {\n loadingMore.value = false;\n }\n };\n\n onInit(() => {\n eventSource = new EventSource('/api/events');\n eventSource.addEventListener('jobs.available', refreshJobs);\n eventSource.addEventListener('jobs.changed', refreshJobs);\n eventSource.onerror = () => {\n refreshError.value = true;\n };\n refreshTimer = setInterval(refreshJobs, 60000);\n });\n onDestroy(() => {\n eventSource?.close();\n clearInterval(refreshTimer);\n });\n\n return { jobs, lastUpdated, refreshError, hasMore, loadingMore, loadMore, upper };\n }\n <\/script>\n <script state>__DASHBOARD_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n";
3658
+ }, Dn = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Engine Dashboard</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <main class=\"max-w-6xl mx-auto space-y-6\">\n <header class=\"flex flex-col sm:flex-row sm:items-center justify-between gap-3 border-b border-gray-800 pb-4\">\n <div>\n <h1 class=\"text-2xl font-bold text-white\">Runner Engine Status</h1>\n <p class=\"text-xs text-gray-400\">Live Job Queue &amp; Execution Traces</p>\n </div>\n <div class=\"flex items-center gap-3 text-xs font-mono\">\n <a href=\"/workflows\" class=\"text-indigo-400 hover:text-indigo-300 hover:underline\">Manage workflows</a>\n <span class=\"text-gray-500\">Updated {{ lastUpdated }}</span>\n <span\n class=\"px-3 py-1 rounded-full border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': !refreshError,\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': refreshError\n }\"\n >\n {{ refreshError ? 'Refresh failed' : 'System operational' }}\n </span>\n </div>\n </header>\n\n <section class=\"bg-gray-900 border border-gray-800 rounded-xl overflow-hidden hidden md:block\">\n <table class=\"w-full text-left text-sm\">\n <thead class=\"bg-gray-800/50 text-gray-400 text-xs uppercase font-mono border-b border-gray-800\">\n <tr>\n <th class=\"py-3 px-4\">Job ID</th>\n <th class=\"py-3 px-4\">Workflow</th>\n <th class=\"py-3 px-4\">Status</th>\n <th class=\"py-3 px-4 hidden xl:table-cell\">Worker</th>\n <th class=\"py-3 px-4 hidden lg:table-cell\">Created At</th>\n <th class=\"py-3 px-4 text-right\">Action</th>\n </tr>\n </thead>\n <tbody>\n <template for=\"job of jobs\">\n <tr class=\"border-b border-gray-800 hover:bg-gray-800/40 transition\">\n <td class=\"py-3 px-4 font-mono text-indigo-400\">\n <a attr-href=\"'/runs/' + job.id\" class=\"hover:underline\">#{{ job.id }}</a>\n </td>\n <td class=\"py-3 px-4 font-medium text-white\">{{ job.workflowId }}</td>\n <td class=\"py-3 px-4\">\n <span\n class=\"px-2.5 py-0.5 rounded-full text-xs font-semibold\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400': job.status === 'success',\n 'bg-rose-500/10.text-rose-400': job.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.animate-pulse': job.status === 'running',\n 'bg-gray-500/10.text-gray-400': !['success', 'failed', 'running'].includes(job.status)\n }\"\n >\n {{ upper(job.status) }}\n </span>\n </td>\n <td class=\"py-3 px-4 hidden xl:table-cell text-xs font-mono text-gray-400\">{{ job.workerId || '-' }}</td>\n <td class=\"py-3 px-4 hidden lg:table-cell text-xs text-gray-400\">{{ job.createdAt }}</td>\n <td class=\"py-3 px-4 text-right whitespace-nowrap\">\n <a attr-href=\"'/runs/' + job.id\" class=\"text-xs bg-gray-800 hover:bg-gray-700 text-gray-200 px-3 py-1 rounded border border-gray-700\">View Trace</a>\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n <template if=\"!jobs.length\">\n <div class=\"p-8 text-center text-gray-500\">No jobs recorded yet.</div>\n </template>\n </section>\n\n <section class=\"md:hidden bg-gray-900 border border-gray-800 rounded-xl divide-y divide-gray-800 overflow-hidden\">\n <template for=\"job of jobs\">\n <article class=\"p-4 bg-gray-900/60\">\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <div class=\"flex items-center gap-2\">\n <span\n class=\"w-2.5 h-2.5 rounded-full shrink-0\"\n bind-class=\"{\n 'bg-emerald-400': job.status === 'success',\n 'bg-rose-400': job.status === 'failed',\n 'bg-indigo-400.animate-pulse': job.status === 'running',\n 'bg-gray-500': !['success', 'failed', 'running'].includes(job.status)\n }\"\n ></span>\n <h2 class=\"font-medium text-white truncate\">{{ job.workflowId }}</h2>\n </div>\n <p class=\"mt-1 pl-[18px] text-xs font-mono text-gray-400\">#{{ job.id }} ยท {{ upper(job.status) }}</p>\n </div>\n <a attr-href=\"'/runs/' + job.id\" class=\"shrink-0 text-xs bg-gray-800 hover:bg-gray-700 text-gray-300 px-2.5 py-1 rounded border border-gray-700\">Trace</a>\n </div>\n </article>\n </template>\n <template if=\"!jobs.length\">\n <div class=\"p-8 text-center text-gray-500\">No jobs recorded yet.</div>\n </template>\n </section>\n\n <template if=\"hasMore\">\n <div class=\"flex justify-center\">\n <button\n class=\"px-4 py-2 text-sm text-gray-200 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded-lg\"\n on-click=\"loadMore()\"\n >\n {{ loadingMore ? 'Loading...' : 'Load more' }}\n </button>\n </div>\n </template>\n </main>\n\n <script setup>\n import { onDestroy, onInit, ref } from '@li3/web';\n\n export default function setup() {\n const jobs = ref([]);\n const lastUpdated = ref('now');\n const refreshError = ref(false);\n const hasMore = ref(false);\n const loadingMore = ref(false);\n let refreshTimer;\n let eventSource;\n let refreshing = false;\n let refreshPending = false;\n\n const upper = (value) => String(value || '').toUpperCase();\n const terminalStatuses = new Set(['success', 'failed', 'cancelled']);\n const refreshJobs = async () => {\n if (refreshing) {\n refreshPending = true;\n return;\n }\n refreshing = true;\n\n try {\n const activeIds = jobs.value\n .filter((job) => !terminalStatuses.has(job.status))\n .map((job) => Number(job.id));\n const knownIds = jobs.value.map((job) => Number(job.id));\n const afterId = activeIds.length\n ? Math.max(0, Math.min(...activeIds) - 1)\n : knownIds.length\n ? Math.max(...knownIds)\n : null;\n const url = afterId === null ? '/api/jobs?limit=500' : `/api/jobs?afterId=${afterId}&limit=500`;\n const response = await fetch(url, { headers: { accept: 'application/json' } });\n if (!response.ok) throw new Error(`Dashboard refresh failed: ${response.status}`);\n\n const data = await response.json();\n const merged = new Map(jobs.value.map((job) => [job.id, job]));\n for (const job of data.jobs) merged.set(job.id, job);\n jobs.value = Array.from(merged.values()).sort((a, b) => Number(b.id) - Number(a.id));\n lastUpdated.value = new Date().toLocaleTimeString();\n refreshError.value = false;\n } catch (error) {\n console.error(error);\n refreshError.value = true;\n } finally {\n refreshing = false;\n if (refreshPending) {\n refreshPending = false;\n void refreshJobs();\n }\n }\n };\n\n const loadMore = async () => {\n if (loadingMore.value || !hasMore.value || !jobs.value.length) return;\n loadingMore.value = true;\n\n try {\n const beforeId = Math.min(...jobs.value.map((job) => Number(job.id)));\n const response = await fetch(`/api/jobs?beforeId=${beforeId}`, {\n headers: { accept: 'application/json' },\n });\n if (!response.ok) throw new Error(`Loading older jobs failed: ${response.status}`);\n\n const data = await response.json();\n const merged = new Map(jobs.value.map((job) => [job.id, job]));\n for (const job of data.jobs) merged.set(job.id, job);\n jobs.value = Array.from(merged.values()).sort((a, b) => Number(b.id) - Number(a.id));\n hasMore.value = data.hasMore;\n } catch (error) {\n console.error(error);\n refreshError.value = true;\n } finally {\n loadingMore.value = false;\n }\n };\n\n onInit(() => {\n eventSource = new EventSource('/api/events');\n eventSource.addEventListener('jobs.available', refreshJobs);\n eventSource.addEventListener('jobs.changed', refreshJobs);\n eventSource.onerror = () => {\n refreshError.value = true;\n };\n refreshTimer = setInterval(refreshJobs, 60000);\n });\n onDestroy(() => {\n eventSource?.close();\n clearInterval(refreshTimer);\n });\n\n return { jobs, lastUpdated, refreshError, hasMore, loadingMore, loadMore, upper };\n }\n <\/script>\n <script state>__DASHBOARD_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n";
3654
3659
  //#endregion
3655
3660
  //#region src/html-state.ts
3656
3661
  function On(e) {
@@ -3731,7 +3736,7 @@ async function Mn(e, t, n, r) {
3731
3736
  }
3732
3737
  //#endregion
3733
3738
  //#region src/run.html?raw
3734
- var Nn = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Run</title>\n <script type=\"importmap\">\n {\n \"imports\": {\n \"@li3/\": \"https://cdn.li3.dev/@li3/\",\n \"ansi_up\": \"https://esm.sh/ansi_up@6.0.6\"\n }\n }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <div class=\"max-w-5xl mx-auto space-y-4\">\n <header class=\"flex flex-col md:flex-row md:items-center justify-between border-b border-gray-800 pb-6 gap-4\">\n <div class=\"min-w-0\">\n <a href=\"/runs\" class=\"text-xs text-indigo-400 hover:underline mb-1 inline-block\">Back to Dashboard</a>\n <h1 class=\"text-2xl font-bold text-white flex flex-wrap items-center gap-3\">\n {{ report.workflowName }}\n <span class=\"text-sm font-mono text-gray-500\">#{{ report.jobId }}</span>\n <template if=\"report.parentId\">\n <a attr-href=\"'/runs/' + report.parentId\" class=\"text-sm font-mono text-indigo-400 hover:underline\">\n from #{{ report.parentId }}\n </a>\n </template>\n </h1>\n <p class=\"text-xs text-gray-400 mt-1\">Started {{ report.startedAt }} ยท {{ timing }}</p>\n </div>\n <div class=\"flex items-center gap-2 shrink-0\">\n <span\n class=\"px-4 py-1.5 rounded-full text-sm font-semibold border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': report.status === 'success',\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': report.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.border-indigo-500/20': report.status === 'running',\n 'bg-amber-500/10.text-amber-400.border-amber-500/20': !['success', 'failed', 'running'].includes(report.status)\n }\"\n >\n {{ upper(report.status) }}\n </span>\n <button\n class=\"text-sm text-white px-4 py-1.5 border border-gray-600 hover:border-gray-400 rounded-full\"\n on-click=\"restartJob()\"\n >\n Restart\n </button>\n </div>\n </header>\n\n <section class=\"rounded overflow-hidden border-b border-gray-800\">\n <h2 class=\"sr-only\">Execution Steps</h2>\n <template for=\"[step, index] of report.steps\">\n <details class=\"border border-b-0 border-gray-800 bg-gray-900/50 text-sm\">\n <summary class=\"flex flex-col md:flex-row md:items-center justify-between gap-2 p-3 bg-gray-800/40 border-b border-gray-800 cursor-pointer\">\n <div class=\"flex flex-wrap items-center gap-3 min-w-0\">\n <span class=\"font-mono text-gray-500\">\n #{{ index + 1 }}<template if=\"step.exitCode !== undefined && step.exitCode !== 0\"> ({{ step.exitCode }})</template>\n </span>\n <h3 class=\"font-semibold text-gray-200 break-words\">{{ step.name }}</h3>\n <span\n class=\"px-2.5 py-0.5 rounded-full font-medium\"\n bind-class=\"{\n 'text-emerald-400.bg-emerald-500/10': step.status === 'success',\n 'text-rose-400.bg-rose-500/10': step.status === 'failed',\n 'text-indigo-400.bg-indigo-500/10': step.status === 'running',\n 'text-gray-400.bg-gray-500/10': !['success', 'failed', 'running'].includes(step.status)\n }\"\n >\n {{ upper(step.status) }}\n </span>\n </div>\n <div class=\"font-mono text-gray-400 shrink-0\">{{ step.durationMs }}ms</div>\n </summary>\n <div class=\"p-4 bg-gray-950 font-mono text-gray-300 leading-relaxed overflow-auto w-full\">\n <pre class=\"whitespace-pre-wrap\" bind-innerhtml=\"stepLog(step)\"></pre>\n </div>\n </details>\n </template>\n </section>\n\n <details class=\"bg-gray-900 border border-gray-800 rounded-xl p-4 overflow-auto max-h-[400px]\">\n <summary class=\"cursor-pointer\">\n <h2 class=\"inline text-xs font-semibold text-gray-400 uppercase tracking-wider\">Trigger Inputs</h2>\n </summary>\n <pre class=\"font-mono text-xs text-gray-200 bg-gray-950 p-3 mt-3 rounded-lg overflow-x-auto\">{{ inputsJson }}</pre>\n </details>\n </div>\n\n <script setup>\n import { computed, onDestroy, onInit, ref } from '@li3/web';\n import { AnsiUp } from 'ansi_up';\n\n export default function setup() {\n const report = ref({});\n const now = ref(Date.now());\n const ansiUp = new AnsiUp();\n ansiUp.use_classes = false;\n let eventSource;\n let refreshTimer;\n let clockTimer;\n let refreshing = false;\n let refreshPending = false;\n\n const active = computed(() => ['pending', 'running'].includes(report.value.status));\n const inputsJson = computed(() => JSON.stringify(report.value.inputs || {}, null, 2));\n const timing = computed(() => {\n if (report.value.status === 'pending') return 'Waiting for a worker';\n if (report.value.status === 'running') {\n return `Running for ${Math.max(0, now.value - Date.parse(report.value.startedAt))}ms`;\n }\n return `Finished in ${report.value.durationMs}ms`;\n });\n\n const upper = (value) => String(value || '').toUpperCase();\n const stepLog = (step) => {\n if (step.status === 'skipped') return '';\n if (step.status === 'running') return '<span class=\"text-indigo-400\">Step is running. Logs will appear after it finishes.</span>';\n if (step.status === 'pending') return '<span class=\"text-gray-500\">Waiting to run.</span>';\n if (step.logContent) return ansiUp.ansi_to_html(step.logContent);\n return '<span class=\"text-gray-500\">(No terminal log output recorded for this step)</span>';\n };\n const restartJob = async () => {\n const response = await fetch(`/restart/${report.value.jobId}`, { method: 'POST' });\n if (response.ok) {\n const { id } = await response.json();\n location.href = `/runs/${id}`;\n }\n };\n const refreshRun = async () => {\n if (refreshing) {\n refreshPending = true;\n return;\n }\n refreshing = true;\n\n try {\n const response = await fetch(`/api/runs/${report.value.jobId}`, {\n headers: { accept: 'application/json' },\n });\n if (!response.ok) throw new Error(`Run refresh failed: ${response.status}`);\n report.value = await response.json();\n } catch (error) {\n console.error(error);\n } finally {\n refreshing = false;\n if (refreshPending) {\n refreshPending = false;\n void refreshRun();\n }\n }\n };\n const handleJobChange = (event) => {\n const data = JSON.parse(event.data || '{}');\n if (!data.jobId || String(data.jobId) === String(report.value.jobId)) void refreshRun();\n };\n\n onInit(() => {\n document.title = `Run #${report.value.jobId} - ${report.value.workflowName}`;\n eventSource = new EventSource('/api/events');\n eventSource.addEventListener('jobs.changed', handleJobChange);\n refreshTimer = setInterval(() => {\n if (active.value) void refreshRun();\n }, 60000);\n clockTimer = setInterval(() => {\n now.value = Date.now();\n }, 1000);\n });\n onDestroy(() => {\n eventSource?.close();\n clearInterval(refreshTimer);\n clearInterval(clockTimer);\n });\n\n return { report, inputsJson, timing, upper, stepLog, restartJob };\n }\n <\/script>\n <script state>__REPORT_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n", Pn = /(?:^|[_-])auth(?:entication)?(?:$|[_-])|access[_-]?key|api[_-]?key|authorization|cookie|credential|passphrase|password|private[_-]?key|secret|session(?:id)?|signing[_-]?key|token/i;
3739
+ var Nn = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Workflow Run</title>\n <script type=\"importmap\">\n {\n \"imports\": {\n \"@li3/\": \"https://cdn.li3.dev/@li3/\",\n \"ansi_up\": \"https://esm.sh/ansi_up@6.0.6\"\n }\n }\n <\/script>\n</head>\n<body class=\"bg-gray-950 text-gray-100 min-h-screen p-4 md:p-6 font-sans\">\n <template app>\n <div class=\"max-w-5xl mx-auto space-y-4\">\n <header class=\"flex flex-col md:flex-row md:items-center justify-between border-b border-gray-800 pb-6 gap-4\">\n <div class=\"min-w-0\">\n <a href=\"/runs\" class=\"text-xs text-indigo-400 hover:underline mb-1 inline-block\">Back to Dashboard</a>\n <h1 class=\"text-2xl font-bold text-white flex flex-wrap items-center gap-3\">\n {{ report.workflowName }}\n <span class=\"text-sm font-mono text-gray-500\">#{{ report.jobId }}</span>\n <template if=\"report.parentId\">\n <a attr-href=\"'/runs/' + report.parentId\" class=\"text-sm font-mono text-indigo-400 hover:underline\">\n from #{{ report.parentId }}\n </a>\n </template>\n </h1>\n <p class=\"text-xs text-gray-400 mt-1\">Started {{ report.startedAt }} ยท {{ timing }}</p>\n </div>\n <div class=\"flex items-center gap-2 shrink-0\">\n <span\n class=\"px-4 py-1.5 rounded-full text-sm font-semibold border\"\n bind-class=\"{\n 'bg-emerald-500/10.text-emerald-400.border-emerald-500/20': report.status === 'success',\n 'bg-rose-500/10.text-rose-400.border-rose-500/20': report.status === 'failed',\n 'bg-indigo-500/10.text-indigo-400.border-indigo-500/20': report.status === 'running',\n 'bg-amber-500/10.text-amber-400.border-amber-500/20': !['success', 'failed', 'running'].includes(report.status)\n }\"\n >\n {{ upper(report.status) }}\n </span>\n <template if=\"report.status === 'running'\">\n <button\n class=\"text-sm text-rose-300 px-4 py-1.5 border border-rose-500/50 hover:border-rose-400 rounded-full disabled:opacity-50\"\n on-click=\"cancelJob()\"\n attr-disabled=\"cancelling\"\n >\n {{ cancelling ? 'Cancelling...' : 'Cancel' }}\n </button>\n </template>\n <template if=\"report.status !== 'running'\">\n <button\n class=\"text-sm text-white px-4 py-1.5 border border-gray-600 hover:border-gray-400 rounded-full\"\n on-click=\"restartJob()\"\n >\n Restart\n </button>\n </template>\n </div>\n </header>\n\n <section class=\"rounded overflow-hidden border-b border-gray-800\">\n <h2 class=\"sr-only\">Execution Steps</h2>\n <template for=\"[step, index] of report.steps\">\n <details class=\"border border-b-0 border-gray-800 bg-gray-900/50 text-sm\">\n <summary class=\"flex flex-col md:flex-row md:items-center justify-between gap-2 p-3 bg-gray-800/40 border-b border-gray-800 cursor-pointer\">\n <div class=\"flex flex-wrap items-center gap-3 min-w-0\">\n <span class=\"font-mono text-gray-500\">\n #{{ index + 1 }}<template if=\"step.exitCode !== undefined && step.exitCode !== 0\"> ({{ step.exitCode }})</template>\n </span>\n <h3 class=\"font-semibold text-gray-200 break-words\">{{ step.name }}</h3>\n <span\n class=\"px-2.5 py-0.5 rounded-full font-medium\"\n bind-class=\"{\n 'text-emerald-400.bg-emerald-500/10': step.status === 'success',\n 'text-rose-400.bg-rose-500/10': step.status === 'failed',\n 'text-indigo-400.bg-indigo-500/10': step.status === 'running',\n 'text-gray-400.bg-gray-500/10': !['success', 'failed', 'running'].includes(step.status)\n }\"\n >\n {{ upper(step.status) }}\n </span>\n </div>\n <div class=\"font-mono text-gray-400 shrink-0\">{{ step.durationMs }}ms</div>\n </summary>\n <div class=\"p-4 bg-gray-950 font-mono text-gray-300 leading-relaxed overflow-auto w-full\">\n <pre class=\"whitespace-pre-wrap\" bind-innerhtml=\"stepLog(step)\"></pre>\n </div>\n </details>\n </template>\n </section>\n\n <details class=\"bg-gray-900 border border-gray-800 rounded-xl p-4 overflow-auto max-h-[400px]\">\n <summary class=\"cursor-pointer\">\n <h2 class=\"inline text-xs font-semibold text-gray-400 uppercase tracking-wider\">Trigger Inputs</h2>\n </summary>\n <pre class=\"font-mono text-xs text-gray-200 bg-gray-950 p-3 mt-3 rounded-lg overflow-x-auto\">{{ inputsJson }}</pre>\n </details>\n </div>\n\n <script setup>\n import { computed, onDestroy, onInit, ref } from '@li3/web';\n import { AnsiUp } from 'ansi_up';\n\n export default function setup() {\n const report = ref({});\n const now = ref(Date.now());\n const ansiUp = new AnsiUp();\n ansiUp.use_classes = false;\n let eventSource;\n let refreshTimer;\n let clockTimer;\n let refreshing = false;\n let refreshPending = false;\n const cancelling = ref(false);\n\n const active = computed(() => ['pending', 'running'].includes(report.value.status));\n const inputsJson = computed(() => JSON.stringify(report.value.inputs || {}, null, 2));\n const timing = computed(() => {\n if (report.value.status === 'pending') return 'Waiting for a worker';\n if (report.value.status === 'running') {\n return `Running for ${Math.max(0, now.value - Date.parse(report.value.startedAt))}ms`;\n }\n return `Finished in ${report.value.durationMs}ms`;\n });\n\n const upper = (value) => String(value || '').toUpperCase();\n const stepLog = (step) => {\n if (step.status === 'skipped') return '';\n if (step.status === 'running') return '<span class=\"text-indigo-400\">Step is running. Logs will appear after it finishes.</span>';\n if (step.status === 'pending') return '<span class=\"text-gray-500\">Waiting to run.</span>';\n if (step.logContent) return ansiUp.ansi_to_html(step.logContent);\n return '<span class=\"text-gray-500\">(No terminal log output recorded for this step)</span>';\n };\n const restartJob = async () => {\n const response = await fetch(`/restart/${report.value.jobId}`, { method: 'POST' });\n if (response.ok) {\n const { id } = await response.json();\n location.href = `/runs/${id}`;\n }\n };\n const cancelJob = async () => {\n if (cancelling.value || report.value.status !== 'running') return;\n cancelling.value = true;\n try {\n const response = await fetch(`/api/jobs/${report.value.jobId}/cancel`, { method: 'POST' });\n if (!response.ok) throw new Error(`Cancel failed: ${response.status}`);\n await refreshRun();\n } catch (error) {\n console.error(error);\n } finally {\n cancelling.value = false;\n }\n };\n const refreshRun = async () => {\n if (refreshing) {\n refreshPending = true;\n return;\n }\n refreshing = true;\n\n try {\n const response = await fetch(`/api/runs/${report.value.jobId}`, {\n headers: { accept: 'application/json' },\n });\n if (!response.ok) throw new Error(`Run refresh failed: ${response.status}`);\n report.value = await response.json();\n } catch (error) {\n console.error(error);\n } finally {\n refreshing = false;\n if (refreshPending) {\n refreshPending = false;\n void refreshRun();\n }\n }\n };\n const handleJobChange = (event) => {\n const data = JSON.parse(event.data || '{}');\n if (!data.jobId || String(data.jobId) === String(report.value.jobId)) void refreshRun();\n };\n\n onInit(() => {\n document.title = `Run #${report.value.jobId} - ${report.value.workflowName}`;\n eventSource = new EventSource('/api/events');\n eventSource.addEventListener('jobs.changed', handleJobChange);\n refreshTimer = setInterval(() => {\n if (active.value) void refreshRun();\n }, 60000);\n clockTimer = setInterval(() => {\n now.value = Date.now();\n }, 1000);\n });\n onDestroy(() => {\n eventSource?.close();\n clearInterval(refreshTimer);\n clearInterval(clockTimer);\n });\n\n return { report, inputsJson, timing, upper, stepLog, restartJob, cancelJob, cancelling };\n }\n <\/script>\n <script state>__REPORT_STATE__<\/script>\n </template>\n\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n</body>\n</html>\n", Pn = /(?:^|[_-])auth(?:entication)?(?:$|[_-])|access[_-]?key|api[_-]?key|authorization|cookie|credential|passphrase|password|private[_-]?key|secret|session(?:id)?|signing[_-]?key|token/i;
3735
3740
  function Fn(e, t, n, r = []) {
3736
3741
  let i = JSON.parse(e.payload), a = e.report ? JSON.parse(e.report) : Ln(e, i, r), o = e.status;
3737
3742
  return {
@@ -8190,6 +8195,9 @@ var Bo = class {
8190
8195
  status: t.status
8191
8196
  } : null;
8192
8197
  }
8198
+ async delete(e) {
8199
+ return await this.get(e) ? (await S.run("DELETE FROM scheduled_runs WHERE workflow_id = ?", [e]), await S.run("DELETE FROM workflow_revisions WHERE workflow_id = ?", [e]), await S.run("DELETE FROM workflows WHERE id = ?", [e]), !0) : !1;
8200
+ }
8193
8201
  async published() {
8194
8202
  return (await S.all("SELECT w.id AS workflow_id, r.revision, r.normalized_json FROM workflows w JOIN workflow_revisions r\n ON r.workflow_id = w.id AND r.revision = w.active_revision WHERE w.status = 'published'")).map((e) => ({
8195
8203
  workflowId: e.workflow_id,
@@ -8240,11 +8248,23 @@ var Ho = class {
8240
8248
  async names() {
8241
8249
  return (await S.all("SELECT name FROM secrets ORDER BY name")).map((e) => e.name);
8242
8250
  }
8251
+ async delete(e) {
8252
+ let t = await S.run("DELETE FROM secrets WHERE name = ?", [e]);
8253
+ return Number(t?.changes || 0) > 0;
8254
+ }
8243
8255
  decrypt(e) {
8244
8256
  let t = Buffer.from(e, "base64"), n = l.createDecipheriv("aes-256-gcm", this.encryptionKey(), t.subarray(0, 12));
8245
8257
  return n.setAuthTag(t.subarray(12, 28)), Buffer.concat([n.update(t.subarray(28)), n.final()]).toString("utf8");
8246
8258
  }
8247
- }, Uo = 50, Wo = 500, Go = class e {
8259
+ }, Uo = "<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Runner Workflow Management</title>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n <style>\n body[data-page=\"list\"] .editor-panel { display: none; }\n body[data-page=\"editor\"] .workflow-list, body[data-page=\"editor\"] .secrets-panel { display: none; }\n body[data-page=\"list\"] #workflow-layout { grid-template-columns: minmax(0, 1fr); }\n </style>\n</head>\n<body data-page=\"__WORKFLOW_PAGE__\" class=\"min-h-screen bg-gray-950 p-4 font-sans text-gray-100 md:p-6\">\n <main class=\"mx-auto max-w-7xl space-y-5\">\n <header class=\"flex flex-col justify-between gap-3 border-b border-gray-800 pb-4 sm:flex-row sm:items-end\">\n <div>\n <a href=\"/runs\" class=\"text-xs text-indigo-400 hover:underline\">Back to dashboard</a>\n <h1 class=\"mt-1 text-2xl font-bold text-white\">Workflow control room</h1>\n <p class=\"text-sm text-gray-400\">Draft, validate, and publish revisioned YAML definitions.</p>\n </div>\n <a href=\"/workflows/new\" class=\"rounded-lg border border-indigo-500/50 bg-indigo-500/10 px-4 py-2 text-sm font-medium text-indigo-200 hover:bg-indigo-500/20\">New workflow</a>\n </header>\n\n <p id=\"notice\" role=\"status\" class=\"hidden rounded-lg border px-3 py-2 text-sm\"></p>\n\n <section id=\"workflow-layout\" class=\"grid gap-5 lg:grid-cols-[17rem_1fr]\">\n <aside class=\"workflow-list rounded-xl border border-gray-800 bg-gray-900 p-3\">\n <h2 class=\"mb-2 px-1 text-xs font-semibold uppercase tracking-wider text-gray-400\">Workflows</h2>\n <div id=\"workflow-list\" class=\"space-y-1\"></div>\n </aside>\n\n <section class=\"editor-panel rounded-xl border border-gray-800 bg-gray-900 p-4\">\n <div class=\"mb-3 flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between\">\n <label class=\"block flex-1 text-xs font-semibold uppercase tracking-wider text-gray-400\">Workflow ID\n <input id=\"workflow-id\" class=\"mt-1 w-full rounded border border-gray-700 bg-gray-950 px-3 py-2 font-mono text-sm text-white outline-none focus:border-indigo-500\" placeholder=\"derived-from-workflow-name\">\n </label>\n <div class=\"flex flex-wrap gap-2\">\n <button id=\"validate\" class=\"rounded border border-gray-700 px-3 py-2 text-sm hover:border-gray-500\">Validate</button>\n <button id=\"save\" class=\"rounded border border-indigo-500 bg-indigo-500 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-400\">Save draft</button>\n <button id=\"publish\" class=\"rounded border border-emerald-500/60 px-3 py-2 text-sm text-emerald-300 hover:bg-emerald-500/10\">Publish</button>\n <button id=\"delete\" class=\"rounded border border-rose-500/60 px-3 py-2 text-sm text-rose-300 hover:bg-rose-500/10\">Delete</button>\n </div>\n </div>\n <textarea id=\"source-yaml\" spellcheck=\"false\" class=\"h-[34rem] w-full rounded-lg border border-gray-700 bg-gray-950 p-4 font-mono text-sm leading-6 text-gray-100 outline-none focus:border-indigo-500\" placeholder=\"name: Example&#10;on:&#10; github:&#10; events: [push]&#10;steps:&#10; - run: echo hello\"></textarea>\n </section>\n </section>\n\n <section class=\"secrets-panel rounded-xl border border-gray-800 bg-gray-900 p-4\">\n <div class=\"mb-3\">\n <h2 class=\"text-base font-semibold text-white\">Secrets</h2>\n <p class=\"text-sm text-gray-400\">Values are write-only and encrypted. Re-saving a name replaces its value.</p>\n </div>\n <div class=\"grid gap-3 md:grid-cols-[14rem_1fr_auto_auto]\">\n <input id=\"secret-name\" class=\"rounded border border-gray-700 bg-gray-950 px-3 py-2 font-mono text-sm uppercase outline-none focus:border-indigo-500\" placeholder=\"NPM_TOKEN\">\n <input id=\"secret-value\" type=\"password\" class=\"rounded border border-gray-700 bg-gray-950 px-3 py-2 font-mono text-sm outline-none focus:border-indigo-500\" placeholder=\"New secret value\">\n <button id=\"save-secret\" class=\"rounded border border-indigo-500 px-3 py-2 text-sm text-indigo-200 hover:bg-indigo-500/10\">Save value</button>\n <button id=\"delete-secret\" class=\"rounded border border-rose-500/60 px-3 py-2 text-sm text-rose-300 hover:bg-rose-500/10\">Delete</button>\n </div>\n <div id=\"secret-list\" class=\"mt-4 flex flex-wrap gap-2\"></div>\n </section>\n </main>\n\n <script>\n const notice = document.querySelector('#notice');\n const workflowList = document.querySelector('#workflow-list');\n const source = document.querySelector('#source-yaml');\n const workflowId = document.querySelector('#workflow-id');\n const secretList = document.querySelector('#secret-list');\n const secretName = document.querySelector('#secret-name');\n const secretValue = document.querySelector('#secret-value');\n const page = document.body.dataset.page;\n const initialId = __WORKFLOW_ID__;\n let workflows = [];\n let selectedId = '';\n\n const showNotice = (message, error = false) => {\n notice.textContent = message;\n notice.className = `rounded-lg border px-3 py-2 text-sm ${error ? 'border-rose-500/40 bg-rose-500/10 text-rose-200' : 'border-emerald-500/40 bg-emerald-500/10 text-emerald-200'}`;\n };\n const api = async (url, options = {}) => {\n const response = await fetch(url, { headers: { accept: 'application/json', ...(options.body ? { 'content-type': 'application/json' } : {}) }, ...options });\n const body = response.status === 204 ? null : await response.json().catch(() => ({}));\n if (!response.ok) throw new Error(body.error || `Request failed: ${response.status}`);\n return body;\n };\n const derivedId = () => source.value.match(/^\\s*(?:id:\\s*([^\\n]+)|name:\\s*([^\\n]+))/m)?.slice(1).find(Boolean)?.trim().toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/(^-|-$)/g, '') || '';\n const renderWorkflows = () => {\n workflowList.replaceChildren();\n for (const workflow of workflows) {\n const button = document.createElement('button');\n button.className = `block w-full rounded px-3 py-2 text-left text-sm hover:bg-gray-800 ${workflow.id === selectedId ? 'bg-indigo-500/15 text-indigo-200' : 'text-gray-300'}`;\n button.textContent = `${workflow.name} ยท ${workflow.status}`;\n button.onclick = () => { window.location.href = `/workflows/${workflow.id}`; };\n workflowList.append(button);\n }\n };\n const loadWorkflows = async () => {\n workflows = (await api('/api/workflows')).workflows;\n renderWorkflows();\n };\n const openWorkflow = async (id) => {\n const workflow = await api(`/api/workflows/${id}`);\n selectedId = workflow.id;\n workflowId.value = workflow.id;\n source.value = workflow.sourceYaml;\n renderWorkflows();\n };\n const loadSecrets = async () => {\n const secrets = (await api('/api/secrets')).secrets;\n secretList.replaceChildren();\n for (const name of secrets) {\n const button = document.createElement('button');\n button.className = 'rounded border border-gray-700 px-2 py-1 font-mono text-xs text-gray-300 hover:border-indigo-500';\n button.textContent = name;\n button.onclick = () => { secretName.value = name; secretValue.focus(); };\n secretList.append(button);\n }\n };\n document.querySelector('#validate').onclick = async () => {\n try { const result = await api('/api/workflows/validate', { method: 'POST', body: JSON.stringify({ sourceYaml: source.value }) }); showNotice(`Valid: ${result.workflows.length} workflow definition(s).`); } catch (error) { showNotice(error.message, true); }\n };\n document.querySelector('#save').onclick = async () => {\n const id = workflowId.value.trim() || derivedId();\n if (!id) return showNotice('Set an ID or add a workflow name first.', true);\n try { const workflow = await api(`/api/workflows/${id}`, { method: 'PUT', body: JSON.stringify({ sourceYaml: source.value }) }); selectedId = workflow.id; workflowId.value = workflow.id; showNotice(`Saved ${workflow.id} as draft revision ${workflow.revision}.`); if (!initialId) history.replaceState(null, '', `/workflows/${workflow.id}`); } catch (error) { showNotice(error.message, true); }\n };\n document.querySelector('#publish').onclick = async () => {\n const id = workflowId.value.trim() || selectedId;\n if (!id) return showNotice('Save a workflow before publishing it.', true);\n try { const workflow = await api(`/api/workflows/${id}/publish`, { method: 'POST' }); selectedId = workflow.id; showNotice(`Published ${workflow.id} revision ${workflow.revision}.`); } catch (error) { showNotice(error.message, true); }\n };\n document.querySelector('#delete').onclick = async () => {\n const id = workflowId.value.trim() || selectedId;\n if (!id || !confirm(`Delete ${id} and all of its revisions?`)) return;\n try { await api(`/api/workflows/${id}`, { method: 'DELETE' }); window.location.href = '/workflows'; } catch (error) { showNotice(error.message, true); }\n };\n document.querySelector('#save-secret').onclick = async () => {\n try { await api(`/api/secrets/${secretName.value.trim()}`, { method: 'PUT', body: JSON.stringify({ value: secretValue.value }) }); secretValue.value = ''; await loadSecrets(); showNotice(`Saved ${secretName.value.trim()}.`); } catch (error) { showNotice(error.message, true); }\n };\n document.querySelector('#delete-secret').onclick = async () => {\n const name = secretName.value.trim();\n if (!name || !confirm(`Delete ${name}?`)) return;\n try { await api(`/api/secrets/${name}`, { method: 'DELETE' }); secretName.value = ''; secretValue.value = ''; await loadSecrets(); showNotice(`Deleted ${name}.`); } catch (error) { showNotice(error.message, true); }\n };\n const loadPage = page === 'editor'\n ? (initialId ? openWorkflow(initialId) : Promise.resolve())\n : Promise.all([loadWorkflows(), loadSecrets()]);\n loadPage.catch((error) => showNotice(error.message, true));\n <\/script>\n</body>\n</html>\n";
8260
+ //#endregion
8261
+ //#region src/workflows-ui.ts
8262
+ function Wo(e, t = "") {
8263
+ return Uo.replace("__WORKFLOW_PAGE__", e).replace("__WORKFLOW_ID__", JSON.stringify(t));
8264
+ }
8265
+ //#endregion
8266
+ //#region src/server.ts
8267
+ var Go = 50, Ko = 500, qo = class e {
8248
8268
  server;
8249
8269
  preprocessors = /* @__PURE__ */ new Map();
8250
8270
  workflows = new Bo();
@@ -8252,6 +8272,7 @@ var Ho = class {
8252
8272
  queue;
8253
8273
  secrets;
8254
8274
  adminToken;
8275
+ workerToken;
8255
8276
  events = new jn();
8256
8277
  workflowsLoaded;
8257
8278
  static async withPort(t) {
@@ -8259,7 +8280,7 @@ var Ho = class {
8259
8280
  return new e(r).listen(n);
8260
8281
  }
8261
8282
  constructor(e) {
8262
- this.queue = e.queue, this.secrets = e.secrets, this.adminToken = e.adminToken, this.workflowsLoaded = Promise.all([this.workflows.init(), this.secretRepository.init()]).then(() => void 0), this.registerPreprocessor(new En()), this.server = c.createServer((e, t) => this.handleRequest(e, t));
8283
+ this.queue = e.queue, this.secrets = e.secrets, this.adminToken = e.adminToken, this.workerToken = e.config.workerToken, this.workflowsLoaded = Promise.all([this.workflows.init(), this.secretRepository.init()]).then(() => void 0), this.registerPreprocessor(new En()), this.server = c.createServer((e, t) => this.handleRequest(e, t));
8263
8284
  }
8264
8285
  registerPreprocessor(e) {
8265
8286
  this.preprocessors.set(e.name, e);
@@ -8267,23 +8288,40 @@ var Ho = class {
8267
8288
  async handleRequest(e, t) {
8268
8289
  let n = new u(e.url || "/", `${e.headers["x-forwarded-proto"] || "http"}://${e.headers["x-forwarded-host"] || e.headers.host}`);
8269
8290
  if (e.method === "GET" && (n.pathname === "/runs" || n.pathname === "/")) return this.renderDashboard(t);
8291
+ if (e.method === "GET" && n.pathname === "/workflows") return this.requireAdmin(e, t) ? (t.writeHead(200, {
8292
+ "Content-Type": "text/html; charset=utf-8",
8293
+ "Cache-Control": "no-store"
8294
+ }), t.end(Wo("list"))) : void 0;
8295
+ let r = n.pathname.match(/^\/workflows\/(new|[a-z0-9-]+)$/);
8296
+ if (e.method === "GET" && r) {
8297
+ if (!this.requireAdmin(e, t)) return;
8298
+ let n = r[1] === "new" ? "" : r[1];
8299
+ return t.writeHead(200, {
8300
+ "Content-Type": "text/html; charset=utf-8",
8301
+ "Cache-Control": "no-store"
8302
+ }), t.end(Wo("editor", n));
8303
+ }
8270
8304
  if (e.method === "GET" && n.pathname === "/api/jobs") {
8271
- let e = n.searchParams.get("afterId"), r = n.searchParams.get("beforeId"), i = n.searchParams.get("limit"), a = e === null ? void 0 : Number(e), o = r === null ? void 0 : Number(r), s = i === null ? Uo : Number(i);
8272
- return a !== void 0 && (!Number.isSafeInteger(a) || a < 0) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "afterId must be a non-negative integer" }))) : o !== void 0 && (!Number.isSafeInteger(o) || o < 1) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "beforeId must be a positive integer" }))) : !Number.isSafeInteger(s) || s < 1 || s > Wo ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: `limit must be an integer from 1 to ${Wo}` }))) : this.renderDashboardJobs(t, s, a, o);
8305
+ let e = n.searchParams.get("afterId"), r = n.searchParams.get("beforeId"), i = n.searchParams.get("limit"), a = e === null ? void 0 : Number(e), o = r === null ? void 0 : Number(r), s = i === null ? Go : Number(i);
8306
+ return a !== void 0 && (!Number.isSafeInteger(a) || a < 0) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "afterId must be a non-negative integer" }))) : o !== void 0 && (!Number.isSafeInteger(o) || o < 1) ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: "beforeId must be a positive integer" }))) : !Number.isSafeInteger(s) || s < 1 || s > Ko ? (t.writeHead(400, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: `limit must be an integer from 1 to ${Ko}` }))) : this.renderDashboardJobs(t, s, a, o);
8273
8307
  }
8274
8308
  if (e.method === "GET" && n.pathname === "/api/events") return this.events.subscribe(e, t);
8275
8309
  if (n.pathname === "/api/workflows/validate" && e.method === "POST") return this.handleWorkflowValidation(e, t);
8276
8310
  if (n.pathname === "/api/secrets" && e.method === "GET") return this.handleSecretList(e, t);
8277
- let r = n.pathname.match(/^\/api\/secrets\/([A-Z][A-Z0-9_]*)$/);
8278
- if (r && e.method === "PUT") return this.handleSecretSave(e, t, r[1]);
8279
- let i = n.pathname.match(/^\/api\/jobs\/(\d+)\/secrets$/);
8280
- if (i && e.method === "GET") return this.handleJobSecrets(e, t, i[1]);
8311
+ let i = n.pathname.match(/^\/api\/secrets\/([A-Z][A-Z0-9_]*)$/);
8312
+ if (i && e.method === "PUT") return this.handleSecretSave(e, t, i[1]);
8313
+ if (i && e.method === "DELETE") return this.handleSecretDelete(e, t, i[1]);
8314
+ let a = n.pathname.match(/^\/api\/jobs\/(\d+)\/secrets$/);
8315
+ if (a && e.method === "GET") return this.handleJobSecrets(e, t, a[1]);
8316
+ let o = n.pathname.match(/^\/api\/jobs\/(\d+)\/cancel$/);
8317
+ if (o && e.method === "POST") return this.handleCancelJob(e, t, o[1]);
8281
8318
  if (n.pathname === "/api/workflows" && e.method === "GET") return this.handleWorkflowList(e, t);
8282
- let a = n.pathname.match(/^\/api\/workflows\/([a-z0-9-]+)(\/publish)?$/);
8283
- if (a) {
8284
- let [, n, r] = a;
8319
+ let s = n.pathname.match(/^\/api\/workflows\/([a-z0-9-]+)(\/publish)?$/);
8320
+ if (s) {
8321
+ let [, n, r] = s;
8285
8322
  if (e.method === "GET" && !r) return this.handleWorkflowGet(e, t, n);
8286
8323
  if (e.method === "PUT" && !r) return this.handleWorkflowSave(e, t, n);
8324
+ if (e.method === "DELETE" && !r) return this.handleWorkflowDelete(e, t, n);
8287
8325
  if (e.method === "POST" && r) return this.handleWorkflowPublish(e, t, n);
8288
8326
  }
8289
8327
  if (e.method === "POST" && n.pathname === "/api/events") return this.handleWorkerEvent(e, t);
@@ -8390,16 +8428,22 @@ var Ho = class {
8390
8428
  }
8391
8429
  }
8392
8430
  isAdmin(e) {
8393
- if (!this.adminToken) return !1;
8394
- let t = e.headers.authorization || "", n = (e) => {
8395
- let t = Buffer.from(this.adminToken), n = Buffer.from(e);
8396
- return t.length === n.length && l.timingSafeEqual(t, n);
8431
+ return this.matchesToken(e, this.adminToken, !0);
8432
+ }
8433
+ isWorker(e) {
8434
+ return this.matchesToken(e, this.workerToken, !1);
8435
+ }
8436
+ matchesToken(e, t, n) {
8437
+ if (!t) return !1;
8438
+ let r = e.headers.authorization || "", i = (e) => {
8439
+ let n = Buffer.from(t), r = Buffer.from(e);
8440
+ return n.length === r.length && l.timingSafeEqual(n, r);
8397
8441
  };
8398
- if (t.startsWith("Bearer ") && n(t.slice(7))) return !0;
8399
- if (!t.startsWith("Basic ")) return !1;
8442
+ if (r.startsWith("Bearer ") && i(r.slice(7))) return !0;
8443
+ if (!n || !r.startsWith("Basic ")) return !1;
8400
8444
  try {
8401
- let e = Buffer.from(t.slice(6), "base64").toString("utf8"), r = e.indexOf(":");
8402
- return r > 0 && e.slice(0, r) === "admin" && n(e.slice(r + 1));
8445
+ let e = Buffer.from(r.slice(6), "base64").toString("utf8"), t = e.indexOf(":");
8446
+ return t > 0 && e.slice(0, t) === "admin" && i(e.slice(t + 1));
8403
8447
  } catch {
8404
8448
  return !1;
8405
8449
  }
@@ -8458,6 +8502,12 @@ var Ho = class {
8458
8502
  t.writeHead(422, { "Content-Type": "application/json; charset=utf-8" }), t.end(JSON.stringify({ error: e.message }));
8459
8503
  }
8460
8504
  }
8505
+ async handleWorkflowDelete(e, t, n) {
8506
+ if (this.requireAdmin(e, t)) {
8507
+ if (!await this.workflows.delete(n)) return t.writeHead(404, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Workflow not found" }));
8508
+ t.writeHead(204).end();
8509
+ }
8510
+ }
8461
8511
  async handleWorkflowPublish(e, t, n) {
8462
8512
  if (!this.requireAdmin(e, t)) return;
8463
8513
  let r = await this.workflows.publish(n);
@@ -8480,8 +8530,14 @@ var Ho = class {
8480
8530
  t.writeHead(422, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: e.message }));
8481
8531
  }
8482
8532
  }
8533
+ async handleSecretDelete(e, t, n) {
8534
+ if (this.requireAdmin(e, t)) {
8535
+ if (!await this.secretRepository.delete(n)) return t.writeHead(404, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Secret not found" }));
8536
+ t.writeHead(204).end();
8537
+ }
8538
+ }
8483
8539
  async handleJobSecrets(e, t, n) {
8484
- if (!this.isAdmin(e)) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
8540
+ if (!this.isWorker(e)) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
8485
8541
  let r = await this.queue.getJob(n);
8486
8542
  if (!r || r.status !== "running" || r.worker_id !== e.headers["x-runner-worker-id"]) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Job is not assigned to this worker" }));
8487
8543
  t.writeHead(200, {
@@ -8490,11 +8546,11 @@ var Ho = class {
8490
8546
  }), t.end(JSON.stringify({ secrets: await this.secretRepository.getAll() }));
8491
8547
  }
8492
8548
  async handleSecretReload(e, t) {
8493
- if (e.headers.authorization !== `Bearer ${this.adminToken}`) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
8549
+ if (!this.isAdmin(e)) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
8494
8550
  this.secrets.reload(), console.log("๐Ÿ”„ SecretStore reloaded successfully without downtime!"), t.writeHead(200, { "Content-Type": "application/json" }), t.end(JSON.stringify({ message: "Secrets reloaded successfully" }));
8495
8551
  }
8496
8552
  async handleWorkerEvent(e, t) {
8497
- if (!this.adminToken || e.headers.authorization !== `Bearer ${this.adminToken}`) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
8553
+ if (!this.isWorker(e)) return t.writeHead(403, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Unauthorized" }));
8498
8554
  let { rawBuffer: n } = await this.readRequest(e, t);
8499
8555
  if (!n || t.headersSent) return;
8500
8556
  let r;
@@ -8507,7 +8563,7 @@ var Ho = class {
8507
8563
  this.events.publish("jobs.changed", r ? { jobId: r } : {}), t.writeHead(202).end();
8508
8564
  }
8509
8565
  async renderDashboard(e) {
8510
- let t = await this.queue.listJobs(51), n = kn(t.slice(0, Uo)), r = await this.redactText(An(n, t.length > Uo));
8566
+ let t = await this.queue.listJobs(51), n = kn(t.slice(0, Go)), r = await this.redactText(An(n, t.length > Go));
8511
8567
  e.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), e.end(r);
8512
8568
  }
8513
8569
  async renderDashboardJobs(e, t, n, r) {
@@ -8542,6 +8598,16 @@ var Ho = class {
8542
8598
  }
8543
8599
  n.writeHead(404, { "Content-Type": "application/json" }), n.end(JSON.stringify({ error: "Job not found" }));
8544
8600
  }
8601
+ async handleCancelJob(e, t, n) {
8602
+ if (!this.requireAdmin(e, t)) return;
8603
+ let r = await this.queue.cancelJob(n);
8604
+ if (r === "not_found") return t.writeHead(404, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Job not found" }));
8605
+ if (r === "not_active") return t.writeHead(409, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Job is no longer running" }));
8606
+ this.events.publish("jobs.changed", { jobId: Number(n) }), t.writeHead(200, { "Content-Type": "application/json" }), t.end(JSON.stringify({
8607
+ id: Number(n),
8608
+ status: "cancelled"
8609
+ }));
8610
+ }
8545
8611
  async currentSecrets() {
8546
8612
  try {
8547
8613
  return await this.secretRepository.getAll();
@@ -8571,7 +8637,7 @@ var Ho = class {
8571
8637
  });
8572
8638
  });
8573
8639
  }
8574
- }, Ko = s(d), qo = class {
8640
+ }, Jo = s(d), Yo = class {
8575
8641
  name = "systemd";
8576
8642
  async isSupported() {
8577
8643
  try {
@@ -8694,7 +8760,7 @@ var Ho = class {
8694
8760
  cancel: async () => {
8695
8761
  d = !0;
8696
8762
  try {
8697
- t.image && await Ko(`docker stop -t 2 ${o}`).catch(() => {}), await Ko(`systemctl stop ${o}.service`).catch(() => {});
8763
+ t.image && await Jo(`docker stop -t 2 ${o}`).catch(() => {}), await Jo(`systemctl stop ${o}.service`).catch(() => {});
8698
8764
  } catch {}
8699
8765
  },
8700
8766
  logFilePath: a
@@ -8704,7 +8770,7 @@ var Ho = class {
8704
8770
  let t = await p(e, "utf-8"), n = t.includes("Running as unit: ") ? t.indexOf("\n") + 1 : 0, r = t.includes("Finished with result: ") ? t.lastIndexOf("Finished with result: ") : t.length;
8705
8771
  return t.slice(n, r);
8706
8772
  }
8707
- }, Jo = class {
8773
+ }, Xo = class {
8708
8774
  name = "standard-process";
8709
8775
  async isSupported() {
8710
8776
  return !0;
@@ -8819,13 +8885,13 @@ var Ho = class {
8819
8885
  };
8820
8886
  //#endregion
8821
8887
  //#region src/drivers/index.ts
8822
- async function Yo() {
8823
- let e = new qo();
8824
- return await e.isSupported() ? (console.log("โšก Selected Execution Driver: Systemd (cgroups enabled)"), e) : (console.log("๐Ÿ“ฆ Selected Execution Driver: Standard Process (Fallback)"), new Jo());
8888
+ async function Zo() {
8889
+ let e = new Yo();
8890
+ return await e.isSupported() ? (console.log("โšก Selected Execution Driver: Systemd (cgroups enabled)"), e) : (console.log("๐Ÿ“ฆ Selected Execution Driver: Standard Process (Fallback)"), new Xo());
8825
8891
  }
8826
8892
  //#endregion
8827
8893
  //#region src/signals.ts
8828
- async function Xo(e) {
8894
+ async function Qo(e) {
8829
8895
  let t = !1;
8830
8896
  async function n(n) {
8831
8897
  if (!t) {
@@ -8833,7 +8899,7 @@ async function Xo(e) {
8833
8899
  console.error("โš ๏ธ Graceful shutdown timed out after 10s. Forcing exit!"), process.exit(1);
8834
8900
  }, 1e4).unref();
8835
8901
  try {
8836
- rs(), e.length > 0 && (console.log("โš™๏ธ Waiting for active worker jobs to drain..."), await Promise.allSettled(e)), console.log("โœจ Engine stopped cleanly. Goodbye!"), process.exit(0);
8902
+ as(), e.length > 0 && (console.log("โš™๏ธ Waiting for active worker jobs to drain..."), await Promise.allSettled(e)), console.log("โœจ Engine stopped cleanly. Goodbye!"), process.exit(0);
8837
8903
  } catch (e) {
8838
8904
  console.error("โŒ Error during graceful shutdown:", e.message), process.exit(1);
8839
8905
  }
@@ -8843,7 +8909,7 @@ async function Xo(e) {
8843
8909
  }
8844
8910
  //#endregion
8845
8911
  //#region src/plugins/manager.ts
8846
- var Zo = class {
8912
+ var $o = class {
8847
8913
  plugins;
8848
8914
  constructor(e = []) {
8849
8915
  this.plugins = e;
@@ -8865,38 +8931,38 @@ var Zo = class {
8865
8931
  console.error(`[Plugin Error] ${n.name}.onWorkflowFinish:`, e);
8866
8932
  }
8867
8933
  }
8868
- }, Qo = !!process.env.DEBUG, $o = { isStopping: !1 }, es = /* @__PURE__ */ new Set(), ts = null, ns = null;
8869
- function rs() {
8870
- $o.isStopping = !0, ts?.abort(), ns?.();
8934
+ }, es = !!process.env.DEBUG, ts = { isStopping: !1 }, ns = /* @__PURE__ */ new Set(), rs = null, is = null;
8935
+ function as() {
8936
+ ts.isStopping = !0, rs?.abort(), is?.();
8871
8937
  }
8872
- function is(e, t, n, r) {
8873
- $o.isStopping = !1;
8874
- let i = [as(e, t, n, r)];
8875
- return Xo(i), i;
8938
+ function os(e, t, n, r) {
8939
+ ts.isStopping = !1;
8940
+ let i = [ss(e, t, n, r)];
8941
+ return Qo(i), i;
8876
8942
  }
8877
- async function as(e, t, n, r) {
8878
- let i = await Yo(), a = new Bo(), o = /* @__PURE__ */ new Set(), s = 0, c = null, l = () => {
8943
+ async function ss(e, t, n, r) {
8944
+ let i = await Zo(), a = new Bo(), o = /* @__PURE__ */ new Set(), s = 0, c = null, l = () => {
8879
8945
  s++, c?.();
8880
8946
  };
8881
- ns = l, ts = new AbortController();
8882
- let u = os(r, ts.signal, l);
8883
- for (console.log(`๐Ÿš€ Worker scheduler started. Driver: ${i.name}. Concurrency: ${e}. Tags: ${r.tags.join(", ") || "(none)"}`); !$o.isStopping;) {
8947
+ is = l, rs = new AbortController();
8948
+ let u = cs(r, rs.signal, l);
8949
+ for (console.log(`๐Ÿš€ Worker scheduler started. Driver: ${i.name}. Concurrency: ${e}. Tags: ${r.tags.join(", ") || "(none)"}`); !ts.isStopping;) {
8884
8950
  let n = s;
8885
8951
  try {
8886
- for (; o.size < e && !$o.isStopping;) {
8952
+ for (; o.size < e && !ts.isStopping;) {
8887
8953
  let e = await t.claimNextJob(r.tags);
8888
8954
  if (!e) break;
8889
- if ($o.isStopping) {
8955
+ if (ts.isStopping) {
8890
8956
  await t.releaseJob(e.id);
8891
8957
  break;
8892
8958
  }
8893
- let n = `worker-${e.id}`, s;
8959
+ let n = process.env.WORKER_NAME || "cli", s;
8894
8960
  s = (async () => {
8895
- ls(r, e.id);
8961
+ ds(r, e.id);
8896
8962
  let o = await a.getRevision(e.workflow_id, e.workflow_revision);
8897
8963
  if (!o) throw await t.finishJob(e.id, "failed"), Error(`Workflow ${e.workflow_id} revision ${e.workflow_revision} was not found`);
8898
8964
  let s = new ce();
8899
- s.replace(await us(r, n, e.id)), await ds({
8965
+ s.replace(await fs(r, n, e.id)), await ps({
8900
8966
  workerId: n,
8901
8967
  job: e,
8902
8968
  queue: t,
@@ -8906,17 +8972,17 @@ async function as(e, t, n, r) {
8906
8972
  workflow: o
8907
8973
  });
8908
8974
  })().catch((e) => console.error(`[${n}] โš ๏ธ Worker execution error:`, e)).finally(() => {
8909
- o.delete(s), ls(r, e.id), l();
8975
+ o.delete(s), ds(r, e.id), l();
8910
8976
  }), o.add(s);
8911
8977
  }
8912
8978
  } catch (e) {
8913
8979
  console.error("โš ๏ธ Worker scheduler claim error:", e), setTimeout(l, 5e3).unref();
8914
8980
  }
8915
- !$o.isStopping && s === n && (await ss(n, () => s, (e) => c = e), c = null);
8981
+ !ts.isStopping && s === n && (await ls(n, () => s, (e) => c = e), c = null);
8916
8982
  }
8917
- ts.abort(), await Promise.allSettled(o), await u, ns = null, console.log("๐Ÿ›‘ Worker scheduler stopped cleanly.");
8983
+ rs.abort(), await Promise.allSettled(o), await u, is = null, console.log("๐Ÿ›‘ Worker scheduler stopped cleanly.");
8918
8984
  }
8919
- async function os(e, t, n) {
8985
+ async function cs(e, t, n) {
8920
8986
  let r = 1e3;
8921
8987
  for (; !t.aborted;) {
8922
8988
  try {
@@ -8927,10 +8993,10 @@ async function os(e, t, n) {
8927
8993
  if (t.aborted || e?.name === "AbortError") break;
8928
8994
  console.error(`โš ๏ธ Worker event stream disconnected: ${e.message}`);
8929
8995
  }
8930
- await cs(r, t), r = Math.min(r * 2, 3e4);
8996
+ await us(r, t), r = Math.min(r * 2, 3e4);
8931
8997
  }
8932
8998
  }
8933
- function ss(e, t, n) {
8999
+ function ls(e, t, n) {
8934
9000
  return new Promise((r) => {
8935
9001
  if (t() !== e) return r();
8936
9002
  let i = setTimeout(r, 6e4);
@@ -8939,7 +9005,7 @@ function ss(e, t, n) {
8939
9005
  });
8940
9006
  });
8941
9007
  }
8942
- function cs(e, t) {
9008
+ function us(e, t) {
8943
9009
  return new Promise((n) => {
8944
9010
  if (t.aborted) return n();
8945
9011
  let r = () => {
@@ -8950,28 +9016,28 @@ function cs(e, t) {
8950
9016
  t.addEventListener("abort", r, { once: !0 });
8951
9017
  });
8952
9018
  }
8953
- async function ls(e, t) {
8954
- if (e.adminToken) try {
9019
+ async function ds(e, t) {
9020
+ if (e.workerToken) try {
8955
9021
  let n = await fetch(new URL("/api/events", e.serverUrl), {
8956
9022
  method: "POST",
8957
9023
  headers: {
8958
- Authorization: `Bearer ${e.adminToken}`,
9024
+ Authorization: `Bearer ${e.workerToken}`,
8959
9025
  "Content-Type": "application/json"
8960
9026
  },
8961
9027
  body: JSON.stringify({ jobId: t }),
8962
9028
  signal: AbortSignal.timeout(5e3)
8963
9029
  });
8964
- !n.ok && Qo && console.error(`Failed to publish job status event: HTTP ${n.status}`);
9030
+ !n.ok && es && console.error(`Failed to publish job status event: HTTP ${n.status}`);
8965
9031
  } catch (e) {
8966
- Qo && console.error("Failed to publish job status event:", e);
9032
+ es && console.error("Failed to publish job status event:", e);
8967
9033
  }
8968
9034
  }
8969
- async function us(e, t, n) {
8970
- if (!e.adminToken) return {};
9035
+ async function fs(e, t, n) {
9036
+ if (!e.workerToken) return {};
8971
9037
  try {
8972
9038
  let r = await fetch(new URL(`/api/jobs/${n}/secrets`, e.serverUrl), {
8973
9039
  headers: {
8974
- Authorization: `Bearer ${e.adminToken}`,
9040
+ Authorization: `Bearer ${e.workerToken}`,
8975
9041
  "X-Runner-Worker-Id": t
8976
9042
  },
8977
9043
  signal: AbortSignal.timeout(5e3)
@@ -8982,7 +9048,7 @@ async function us(e, t, n) {
8982
9048
  throw console.error(`Unable to retrieve secrets for job ${n}:`, e), e;
8983
9049
  }
8984
9050
  }
8985
- async function ds(e) {
9051
+ async function ps(e) {
8986
9052
  let { workerId: t, job: n, config: r, secrets: a, queue: o } = e;
8987
9053
  console.log(`\n[${t}] ๐Ÿ“ฆ Claimed Job #${n.id} (Workflow: ${n.workflow_id})`);
8988
9054
  let s = typeof n.payload == "string" ? JSON.parse(n.payload) : n.payload;
@@ -9002,27 +9068,27 @@ async function ds(e) {
9002
9068
  durationMs: 0,
9003
9069
  outputs: {},
9004
9070
  logContent: ""
9005
- })), g = vs(n, "running", u, l, m.env, h, s);
9006
- await o.saveReport(n.id, g), ls(r, n.id);
9007
- let _ = new Zo(r.plugins), v = {
9071
+ })), g = bs(n, "running", u, l, m.env, h, s);
9072
+ await o.saveReport(n.id, g), ds(r, n.id);
9073
+ let _ = new $o(r.plugins), v = {
9008
9074
  jobId: String(n.id),
9009
9075
  workflowName: n.workflow_id,
9010
9076
  inputs: l,
9011
9077
  runUrl: new URL(`/runs/${n.id}`, r.serverUrl).toString()
9012
9078
  };
9013
9079
  await _.triggerWorkflowStart(v);
9014
- let { cancelled: y, failed: ee } = await fs({
9080
+ let { cancelled: y, failed: ee } = await ms({
9015
9081
  payload: s,
9016
9082
  steps: c,
9017
9083
  executionContext: m,
9018
9084
  ...e
9019
9085
  }, g), b = y ? "cancelled" : ee ? "failed" : "success";
9020
- g.status = b, g.durationMs = Date.now() - u, g.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), await o.completeJob(n.id, b, g), ls(r, n.id), console.log(`[${t}] โœ… Job #${n.id} completed as: ${b}`), await _.triggerWorkflowFinish(v, b);
9086
+ g.status = b, g.durationMs = Date.now() - u, g.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), await o.completeJob(n.id, b, g), ds(r, n.id), console.log(`[${t}] โœ… Job #${n.id} completed as: ${b}`), await _.triggerWorkflowFinish(v, b);
9021
9087
  }
9022
- async function fs(e, t) {
9088
+ async function ms(e, t) {
9023
9089
  let { driver: n, workerId: r, queue: i, config: a, job: o, payload: s, steps: c, executionContext: l } = e, u = t.steps, d = !1, f = !1, p = 0;
9024
9090
  try {
9025
- e.workflow?.env && Object.assign(l.env, await hs(e.workflow.env, l));
9091
+ e.workflow?.env && Object.assign(l.env, await _s(e.workflow.env, l));
9026
9092
  for (let e = 0; e < c.length; e++) {
9027
9093
  let s = c[e], m = (/* @__PURE__ */ new Date()).toISOString();
9028
9094
  u[e] = {
@@ -9035,8 +9101,8 @@ async function fs(e, t) {
9035
9101
  logContent: "",
9036
9102
  startedAt: m,
9037
9103
  finishedAt: void 0
9038
- }, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), ls(a, o.id);
9039
- let h = await ps({
9104
+ }, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), ds(a, o.id);
9105
+ let h = await hs({
9040
9106
  workerId: r,
9041
9107
  jobId: o.id,
9042
9108
  step: s,
@@ -9063,7 +9129,7 @@ async function fs(e, t) {
9063
9129
  exitCode: 1,
9064
9130
  error: "Step failed before execution started",
9065
9131
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
9066
- }, p = e + 1, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), ls(a, o.id), h.skipped) break;
9132
+ }, p = e + 1, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), ds(a, o.id), h.skipped) break;
9067
9133
  if (h.cancelled) {
9068
9134
  f = !0, d = !0;
9069
9135
  break;
@@ -9076,22 +9142,22 @@ async function fs(e, t) {
9076
9142
  } catch (e) {
9077
9143
  console.log("๐Ÿ›‘ Step failed", e), d = !0;
9078
9144
  }
9079
- return p < c.length && (_s(c, p, u), t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), ls(a, o.id)), {
9145
+ return p < c.length && (ys(c, p, u), t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), ds(a, o.id)), {
9080
9146
  failed: d,
9081
9147
  cancelled: f,
9082
9148
  stepReports: u
9083
9149
  };
9084
9150
  }
9085
- async function ps(e) {
9151
+ async function hs(e) {
9086
9152
  let { step: t, stepIndex: n, executionContext: r } = e;
9087
- if (t.id ||= `step-${n}`, t.name ||= t.id, t.if && !await Cn.evaluateConditions(t.if, r)) return Qo && console.log(`โฉ Skipped step ${t.id} based on condition: ${t.if}`, r), {
9153
+ if (t.id ||= `step-${n}`, t.name ||= t.id, t.if && !await Cn.evaluateConditions(t.if, r)) return es && console.log(`โฉ Skipped step ${t.id} based on condition: ${t.if}`, r), {
9088
9154
  failed: !1,
9089
9155
  cancelled: !1,
9090
9156
  skipped: !0,
9091
9157
  report: null
9092
9158
  };
9093
9159
  try {
9094
- let n = await hs(t.env, r), i = {
9160
+ let n = await _s(t.env, r), i = {
9095
9161
  jobId: String(e.jobId),
9096
9162
  step: t,
9097
9163
  command: t.run,
@@ -9105,15 +9171,15 @@ async function ps(e) {
9105
9171
  WORKING_DIR: r.workingDir
9106
9172
  }
9107
9173
  };
9108
- return t.eval ? ms({
9174
+ return t.eval ? gs({
9109
9175
  ...e,
9110
9176
  stepContext: i
9111
- }) : gs({
9177
+ }) : vs({
9112
9178
  ...e,
9113
9179
  stepContext: i
9114
9180
  });
9115
9181
  } catch (e) {
9116
- return Qo && console.error(`โฉ Failed to run step ${t.id}`, r, e), {
9182
+ return es && console.error(`โฉ Failed to run step ${t.id}`, r, e), {
9117
9183
  failed: !0,
9118
9184
  cancelled: !1,
9119
9185
  skipped: !1,
@@ -9121,7 +9187,7 @@ async function ps(e) {
9121
9187
  };
9122
9188
  }
9123
9189
  }
9124
- async function ms(e) {
9190
+ async function gs(e) {
9125
9191
  let { queue: t, stepContext: n, executionContext: r } = e, { jobId: i, step: a } = n, o = Date.now(), s = a.id, c = a.name;
9126
9192
  try {
9127
9193
  let e = await Cn.evaluateExpression(a.eval, r);
@@ -9167,12 +9233,12 @@ async function ms(e) {
9167
9233
  };
9168
9234
  }
9169
9235
  }
9170
- async function hs(e, t) {
9236
+ async function _s(e, t) {
9171
9237
  let n = {};
9172
9238
  if (e) for (let [r, i] of Object.entries(e)) n[r] = String(await Cn.evaluateValue(i, t));
9173
9239
  return n;
9174
9240
  }
9175
- async function gs(t) {
9241
+ async function vs(t) {
9176
9242
  let { workerId: n, jobId: r, stepContext: i, executionContext: a, driver: o, queue: s } = t, { step: c } = i, l = c.id, u = c.name, d;
9177
9243
  try {
9178
9244
  d = o.execute(i);
@@ -9187,11 +9253,11 @@ async function gs(t) {
9187
9253
  logFilePath: ""
9188
9254
  };
9189
9255
  }
9190
- es.add(d);
9256
+ ns.add(d);
9191
9257
  let f = !1, p = setInterval(async () => {
9192
9258
  await s.isCancelled(r) && (console.log(`[${n}] ๐Ÿ›‘ Job #${r} was cancelled! Halting execution.`), f = !0, clearInterval(p), await d.cancel());
9193
9259
  }, 3e3), m = await d.done;
9194
- if (clearInterval(p), es.delete(d), d.logFilePath && e.existsSync(d.logFilePath)) try {
9260
+ if (clearInterval(p), ns.delete(d), d.logFilePath && e.existsSync(d.logFilePath)) try {
9195
9261
  let e = await o.readLog(d.logFilePath);
9196
9262
  await s.saveStepLog(r, l, e);
9197
9263
  } catch (e) {
@@ -9218,7 +9284,7 @@ async function gs(t) {
9218
9284
  }
9219
9285
  };
9220
9286
  }
9221
- function _s(e, t, n) {
9287
+ function ys(e, t, n) {
9222
9288
  for (let r = t; r < e.length; r++) {
9223
9289
  let t = e[r], i = t.id || `step-${r}`;
9224
9290
  n[r] = {
@@ -9232,7 +9298,7 @@ function _s(e, t, n) {
9232
9298
  };
9233
9299
  }
9234
9300
  }
9235
- function vs(e, t, n, r, i, a, o) {
9301
+ function bs(e, t, n, r, i, a, o) {
9236
9302
  return {
9237
9303
  jobId: String(e.id),
9238
9304
  parentId: String(e.parentId || ""),
@@ -9253,7 +9319,7 @@ function vs(e, t, n, r, i, a, o) {
9253
9319
  }
9254
9320
  //#endregion
9255
9321
  //#region src/scheduler.ts
9256
- function ys(e, t, n, r) {
9322
+ function xs(e, t, n, r) {
9257
9323
  return e.split(",").some((e) => {
9258
9324
  let [i, a] = e.split("/"), o = a ? Number(a) : 1;
9259
9325
  if (!Number.isInteger(o) || o < 1) return !1;
@@ -9261,7 +9327,7 @@ function ys(e, t, n, r) {
9261
9327
  return Number.isInteger(l) && Number.isInteger(u) && t >= l && t <= u && (t - l) % o === 0;
9262
9328
  });
9263
9329
  }
9264
- function bs(e, t, n = "UTC") {
9330
+ function Ss(e, t, n = "UTC") {
9265
9331
  let r = e.trim().split(/\s+/);
9266
9332
  if (r.length !== 5) return !1;
9267
9333
  let i = new Intl.DateTimeFormat("en-US", {
@@ -9283,16 +9349,16 @@ function bs(e, t, n = "UTC") {
9283
9349
  "Thu",
9284
9350
  "Fri",
9285
9351
  "Sat"
9286
- ].indexOf(i.weekday), o = ys(r[2], Number(i.day), 1, 31), s = ys(r[4].replace(/7/g, "0"), a, 0, 6);
9287
- return ys(r[0], Number(i.minute), 0, 59) && ys(r[1], Number(i.hour), 0, 23) && ys(r[3], Number(i.month), 1, 12) && (r[2] === "*" || r[4] === "*" ? o && s : o || s);
9352
+ ].indexOf(i.weekday), o = xs(r[2], Number(i.day), 1, 31), s = xs(r[4].replace(/7/g, "0"), a, 0, 6);
9353
+ return xs(r[0], Number(i.minute), 0, 59) && xs(r[1], Number(i.hour), 0, 23) && xs(r[3], Number(i.month), 1, 12) && (r[2] === "*" || r[4] === "*" ? o && s : o || s);
9288
9354
  }
9289
- function xs(e) {
9355
+ function Cs(e) {
9290
9356
  if (!e) return 0;
9291
9357
  let t = e.match(/^([+-]?)(\d+)(m|h)$/);
9292
9358
  if (!t) throw Error(`Invalid solar offset: ${e}`);
9293
9359
  return (t[1] === "-" ? -1 : 1) * Number(t[2]) * (t[3] === "h" ? 36e5 : 6e4);
9294
9360
  }
9295
- function Ss(e, t) {
9361
+ function ws(e, t) {
9296
9362
  let n = t.latitude, r = t.longitude, i = Date.UTC(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate()), a = Math.floor((i - Date.UTC(e.getUTCFullYear(), 0, 0)) / 864e5), o = r / 15, s = a + ((t.event === "sunrise" ? 6 : 18) - o) / 24, c = .9856 * s - 3.289, l = c + 1.916 * Math.sin(c * Math.PI / 180) + .02 * Math.sin(2 * c * Math.PI / 180) + 282.634;
9297
9363
  l = (l + 360) % 360;
9298
9364
  let u = Math.atan(.91764 * Math.tan(l * Math.PI / 180)) * 180 / Math.PI;
@@ -9300,9 +9366,9 @@ function Ss(e, t) {
9300
9366
  let d = .39782 * Math.sin(l * Math.PI / 180), f = Math.cos(Math.asin(d)), p = (Math.cos(90.833 * Math.PI / 180) - d * Math.sin(n * Math.PI / 180)) / (f * Math.cos(n * Math.PI / 180));
9301
9367
  if (p > 1 || p < -1) return null;
9302
9368
  let m = (t.event === "sunrise" ? 360 - Math.acos(p) * 180 / Math.PI : Math.acos(p) * 180 / Math.PI) / 15;
9303
- return m = (m + u - .06571 * s - 6.622 - o + 24) % 24, new Date(i + m * 36e5 + xs(t.offset));
9369
+ return m = (m + u - .06571 * s - 6.622 - o + 24) % 24, new Date(i + m * 36e5 + Cs(t.offset));
9304
9370
  }
9305
- var Cs = class {
9371
+ var Ts = class {
9306
9372
  queue;
9307
9373
  workflows;
9308
9374
  config;
@@ -9319,9 +9385,9 @@ var Cs = class {
9319
9385
  async tick(e = /* @__PURE__ */ new Date()) {
9320
9386
  let t = /* @__PURE__ */ new Date(Math.floor(e.getTime() / 6e4) * 6e4);
9321
9387
  for (let { definition: e, revision: n } of await this.workflows.published()) {
9322
- for (let [r, i] of (e.schedule || []).entries()) bs(i.cron, t, i.timezone || "UTC") && await this.enqueue(e, n, i, `cron-${r}`, t);
9388
+ for (let [r, i] of (e.schedule || []).entries()) Ss(i.cron, t, i.timezone || "UTC") && await this.enqueue(e, n, i, `cron-${r}`, t);
9323
9389
  for (let [r, i] of (e.solar || []).entries()) {
9324
- let a = Ss(t, i);
9390
+ let a = ws(t, i);
9325
9391
  a && Math.floor(a.getTime() / 6e4) === t.getTime() / 6e4 && await this.enqueue(e, n, i, `solar-${r}`, t);
9326
9392
  }
9327
9393
  }
@@ -9337,7 +9403,7 @@ var Cs = class {
9337
9403
  } } };
9338
9404
  await this.queue.enqueue(e.id, t, o, e.tags), console.log(`Scheduled ${e.id} via ${a}`);
9339
9405
  }
9340
- }, ws = class {
9406
+ }, Es = class {
9341
9407
  name = "github-commit-status";
9342
9408
  token;
9343
9409
  apiUrl;
@@ -9379,13 +9445,13 @@ var Cs = class {
9379
9445
  };
9380
9446
  //#endregion
9381
9447
  //#region src/index.ts
9382
- async function Ts() {
9448
+ async function Ds() {
9383
9449
  let { config: e, command: t } = await oe();
9384
9450
  e || process.exit(1);
9385
9451
  let n = new ce(), r = new se(process.env.WORKER_NAME || "cli");
9386
9452
  switch (t) {
9387
9453
  case "start-server":
9388
- console.log("๐ŸŒ Starting Ingress Gateway..."), await r.init(), await Go.withPort({
9454
+ console.log("๐ŸŒ Starting Ingress Gateway..."), await r.init(), await qo.withPort({
9389
9455
  config: e,
9390
9456
  queue: r,
9391
9457
  secrets: n,
@@ -9394,13 +9460,13 @@ async function Ts() {
9394
9460
  });
9395
9461
  break;
9396
9462
  case "start-workers":
9397
- console.log(`โš™๏ธ Starting worker scheduler with ${e.workers} concurrent slot(s)...`), await r.init(), is(e.workers, r, n, e);
9463
+ console.log(`โš™๏ธ Starting worker scheduler with ${e.workers} concurrent slot(s)...`), await r.init(), os(e.workers, r, n, e);
9398
9464
  break;
9399
9465
  case "start-scheduler": {
9400
9466
  console.log("Starting workflow scheduler..."), await r.init();
9401
9467
  let t = new Bo();
9402
9468
  await t.init();
9403
- let n = new Cs(r, t, e);
9469
+ let n = new Ts(r, t, e);
9404
9470
  n.start();
9405
9471
  let i = () => {
9406
9472
  n.stop(), process.exit(0);
@@ -9411,6 +9477,6 @@ async function Ts() {
9411
9477
  default: console.error(`โŒ Unknown command: '${t}'`), ae(), process.exit(1);
9412
9478
  }
9413
9479
  }
9414
- Ts().catch(console.error);
9480
+ Ds().catch(console.error);
9415
9481
  //#endregion
9416
- export { ws as GitHubStatusPlugin };
9482
+ export { Es as GitHubStatusPlugin };
package/dist/queue.d.ts CHANGED
@@ -19,6 +19,7 @@ export declare class QueueManager {
19
19
  */
20
20
  finishJob(jobId: string | number, status: JobStatus): Promise<void>;
21
21
  completeJob(jobId: string | number, status: JobStatus, report: WorkflowExecutionReport): Promise<void>;
22
+ cancelJob(jobId: string | number): Promise<'cancelled' | 'not_found' | 'not_active'>;
22
23
  restartJob(jobId: string | number): Promise<any>;
23
24
  /**
24
25
  * Checks if the current job has been marked for cancellation by another event
@@ -1 +1 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvF,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE9B,IAAI;IAKV;;;OAGG;IACG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,GAAE,MAAM,EAAO,EAAE,cAAc,CAAC,EAAE,MAAM;IAoBrI;;;OAGG;IACG,YAAY,CAAC,UAAU,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA6BlE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvD;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS;IAInD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAStG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAiBvC;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrD,cAAc;IAMd,YAAY;IAsClB;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIlD;;OAEG;IACG,QAAQ,CAAC,KAAK,SAAK,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAiB/E;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxF,2DAA2D;IACrD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5F;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAS1E"}
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvF,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE9B,IAAI;IAKV;;;OAGG;IACG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,GAAE,MAAM,EAAO,EAAE,cAAc,CAAC,EAAE,MAAM;IAoBrI;;;OAGG;IACG,YAAY,CAAC,UAAU,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA6BlE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvD;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS;IAInD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,WAAW,GAAG,YAAY,CAAC;IAapF,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAiBvC;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrD,cAAc;IAMd,YAAY;IAsClB;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIlD;;OAEG;IACG,QAAQ,CAAC,KAAK,SAAK,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAiB/E;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxF,2DAA2D;IACrD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5F;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAS1E"}
@@ -5,6 +5,7 @@ export declare class SecretRepository {
5
5
  set(name: string, value: string): Promise<void>;
6
6
  getAll(): Promise<Record<string, string>>;
7
7
  names(): Promise<string[]>;
8
+ delete(name: string): Promise<boolean>;
8
9
  private decrypt;
9
10
  }
10
11
  //# sourceMappingURL=secret-repository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"secret-repository.d.ts","sourceRoot":"","sources":["../src/secret-repository.ts"],"names":[],"mappings":"AAWA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAAC,CAAS;IAEf,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,CAAC,aAAa;IAIf,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAKzC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKhC,OAAO,CAAC,OAAO;CAMhB"}
1
+ {"version":3,"file":"secret-repository.d.ts","sourceRoot":"","sources":["../src/secret-repository.ts"],"names":[],"mappings":"AAWA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAAC,CAAS;IAEf,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,CAAC,aAAa;IAIf,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAKzC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAK1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5C,OAAO,CAAC,OAAO;CAMhB"}
package/dist/server.d.ts CHANGED
@@ -7,6 +7,7 @@ export declare class WebhookServer {
7
7
  private queue;
8
8
  private secrets;
9
9
  private adminToken;
10
+ private workerToken;
10
11
  private events;
11
12
  private workflowsLoaded;
12
13
  static withPort(options: WebhookServerOptions & {
@@ -23,15 +24,19 @@ export declare class WebhookServer {
23
24
  private preprocess;
24
25
  private matchWorkflows;
25
26
  private isAdmin;
27
+ private isWorker;
28
+ private matchesToken;
26
29
  private requireAdmin;
27
30
  private readJson;
28
31
  private handleWorkflowValidation;
29
32
  private handleWorkflowList;
30
33
  private handleWorkflowGet;
31
34
  private handleWorkflowSave;
35
+ private handleWorkflowDelete;
32
36
  private handleWorkflowPublish;
33
37
  private handleSecretList;
34
38
  private handleSecretSave;
39
+ private handleSecretDelete;
35
40
  private handleJobSecrets;
36
41
  /**
37
42
  * Handles Zero-Downtime Secret Reload
@@ -48,6 +53,7 @@ export declare class WebhookServer {
48
53
  */
49
54
  private renderRunDetails;
50
55
  private handleRestartJob;
56
+ private handleCancelJob;
51
57
  private currentSecrets;
52
58
  private redact;
53
59
  private redactText;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AASpB,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,eAAe,CAAgB;WAE1B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;gBAK1D,OAAO,EAAE,oBAAoB;IAWzC,oBAAoB,CAAC,YAAY,EAAE,mBAAmB;YAIxC,aAAa;IA+F3B;;OAEG;YACW,aAAa;YA0Bb,WAAW;YAwBX,UAAU;YAuBV,cAAc;IAuC5B,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,YAAY;YAON,QAAQ;YAYR,wBAAwB;YAcxB,kBAAkB;YAOlB,iBAAiB;YAWjB,kBAAkB;YAiBlB,qBAAqB;YAWrB,gBAAgB;YAMhB,gBAAgB;YAgBhB,gBAAgB;IAc9B;;OAEG;YACW,kBAAkB;YAelB,iBAAiB;IAuB/B;;OAEG;YACW,eAAe;YAQf,mBAAmB;IAWjC;;OAEG;YACW,gBAAgB;YAuBhB,gBAAgB;YAehB,cAAc;IAS5B,OAAO,CAAC,MAAM;YAMA,UAAU;IAIxB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAStC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAUpB,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,eAAe,CAAgB;WAE1B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;gBAK1D,OAAO,EAAE,oBAAoB;IAYzC,oBAAoB,CAAC,YAAY,EAAE,mBAAmB;YAIxC,aAAa;IAiH3B;;OAEG;YACW,aAAa;YA0Bb,WAAW;YAwBX,UAAU;YAuBV,cAAc;IAuC5B,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,YAAY;YAON,QAAQ;YAYR,wBAAwB;YAcxB,kBAAkB;YAOlB,iBAAiB;YAWjB,kBAAkB;YAiBlB,oBAAoB;YASpB,qBAAqB;YAWrB,gBAAgB;YAMhB,gBAAgB;YAgBhB,kBAAkB;YASlB,gBAAgB;IAc9B;;OAEG;YACW,kBAAkB;YAclB,iBAAiB;IAuB/B;;OAEG;YACW,eAAe;YAQf,mBAAmB;IAWjC;;OAEG;YACW,gBAAgB;YAuBhB,gBAAgB;YAehB,eAAe;YAkBf,cAAc;IAS5B,OAAO,CAAC,MAAM;YAMA,UAAU;IAIxB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAStC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
package/dist/types.d.ts CHANGED
@@ -5,6 +5,8 @@ export interface RunnerConfig {
5
5
  port: number;
6
6
  /** Admin Secret for API / webhook operations */
7
7
  adminToken: string;
8
+ /** Shared worker credential for job lifecycle and secret retrieval APIs */
9
+ workerToken: string;
8
10
  /** SQLite Database connection URL / path */
9
11
  database: string;
10
12
  /** Maximum number of jobs executed concurrently on this node */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAGL,YAAY,EAOZ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAQpB,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAMF;;GAEG;AACH,wBAAsB,qBAAqB,kBAK1C;AAED,wBAAgB,qBAAqB,SAIpC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,mBAK1G;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,YAAY,iBAoErB;AA+FD;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,WAAW,iBAsE9C"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAGL,YAAY,EAOZ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAQpB,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAMF;;GAEG;AACH,wBAAsB,qBAAqB,kBAK1C;AAED,wBAAgB,qBAAqB,SAIpC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,mBAK1G;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,YAAY,iBAsErB;AA+FD;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,WAAW,iBAsE9C"}
@@ -0,0 +1,2 @@
1
+ export declare function generateWorkflowManagementHtml(page: 'list' | 'editor', workflowId?: string): string;
2
+ //# sourceMappingURL=workflows-ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows-ui.d.ts","sourceRoot":"","sources":["../src/workflows-ui.ts"],"names":[],"mappings":"AAEA,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,UAAU,SAAK,GAAG,MAAM,CAI/F"}
@@ -15,6 +15,7 @@ export declare class WorkflowRepository {
15
15
  publish(id: string): Promise<StoredWorkflow | null>;
16
16
  list(): Promise<StoredWorkflow[]>;
17
17
  get(id: string): Promise<StoredWorkflow | null>;
18
+ delete(id: string): Promise<boolean>;
18
19
  published(): Promise<WorkflowRevision[]>;
19
20
  getRevision(workflowId: string, revision: number): Promise<WorkflowDefinition | null>;
20
21
  claimScheduledRun(workflowId: string, triggerId: string, scheduledFor: string): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../src/workflows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC;CAC5C;AAQD,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAuBtE;AAED,qBAAa,kBAAkB;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAa5C,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWlE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IASnD,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAKjC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAK/C,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAMxC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAKrF,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAKvG"}
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../src/workflows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC;CAC5C;AAQD,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAuBtE;AAED,qBAAa,kBAAkB;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAa5C,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWlE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IASnD,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAKjC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAK/C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASpC,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAMxC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAKrF,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAKvG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud-cli/on",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "CLI entry point for the on plugin ecosystem.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.3",