@cloud-cli/on 1.57.0 → 1.59.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.
@@ -1,4 +1,4 @@
1
- export declare const API_KEY_SCOPES: readonly ["workflows:read", "workflows:write", "logs:read", "artifacts:read", "runs:control", "runs:dispatch"];
1
+ export declare const API_KEY_SCOPES: readonly ["workflows:read", "workflows:write", "logs:read", "artifacts:read", "runs:control", "runs:dispatch", "workers:read"];
2
2
  export type ApiKeyScope = (typeof API_KEY_SCOPES)[number];
3
3
  export declare class ApiKeyRepository {
4
4
  init(): Promise<void>;
@@ -6,7 +6,7 @@ export declare class ApiKeyRepository {
6
6
  issue(name: string, scopes: string[]): Promise<{
7
7
  id: `${string}-${string}-${string}-${string}-${string}`;
8
8
  name: string;
9
- scopes: ("workflows:read" | "workflows:write" | "logs:read" | "artifacts:read" | "runs:control" | "runs:dispatch")[];
9
+ scopes: ("workflows:read" | "workflows:write" | "logs:read" | "artifacts:read" | "runs:control" | "runs:dispatch" | "workers:read")[];
10
10
  token: string;
11
11
  }>;
12
12
  scopesForToken(token: string): Promise<string[] | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"api-key-repository.d.ts","sourceRoot":"","sources":["../src/api-key-repository.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,gHAAiH,CAAC;AAC7I,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,qBAAa,gBAAgB;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAYrB,IAAI;IAKJ,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;;;;;;IAUpC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;IAQvD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAI3C"}
1
+ {"version":3,"file":"api-key-repository.d.ts","sourceRoot":"","sources":["../src/api-key-repository.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,gIAAiI,CAAC;AAC7J,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,qBAAa,gBAAgB;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAYrB,IAAI;IAKJ,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;;;;;;IAUpC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;IAQvD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAI3C"}
package/dist/on.js CHANGED
@@ -280,7 +280,7 @@ var ye = class extends l {
280
280
  return await C.run("UPDATE jobs SET status = 'pending', worker_id = NULL WHERE status = 'running' AND started_at < datetime('now', '-1 hour');");
281
281
  }
282
282
  async createTables() {
283
- await C.exec("\n CREATE TABLE IF NOT EXISTS jobs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parentId INTEGER,\n workflow_id TEXT NOT NULL,\n workflow_revision INTEGER NOT NULL,\n required_tags TEXT NOT NULL DEFAULT '[]',\n payload TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n concurrency_key TEXT,\n worker_id TEXT,\n report TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n started_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n finished_at DATETIME DEFAULT CURRENT_TIMESTAMP\n );\n\n CREATE TABLE IF NOT EXISTS step_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n job_id INTEGER NOT NULL,\n step_id TEXT NOT NULL,\n log_content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY(job_id) REFERENCES jobs(id) ON DELETE CASCADE\n );\n\n CREATE INDEX IF NOT EXISTS idx_step_logs_job ON step_logs(job_id);\n\n DELETE FROM step_logs\n WHERE id NOT IN (\n SELECT MAX(id) FROM step_logs GROUP BY job_id, step_id\n );\n CREATE UNIQUE INDEX IF NOT EXISTS idx_step_logs_job_step ON step_logs(job_id, step_id);\n\n CREATE TABLE IF NOT EXISTS stored_files (\n kind TEXT NOT NULL,\n owner_key TEXT NOT NULL,\n file_path TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (kind, owner_key, file_path)\n );\n CREATE INDEX IF NOT EXISTS idx_stored_files_owner ON stored_files(kind, owner_key);\n ");
283
+ await C.exec("\n CREATE TABLE IF NOT EXISTS jobs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parentId INTEGER,\n workflow_id TEXT NOT NULL,\n workflow_revision INTEGER NOT NULL,\n required_tags TEXT NOT NULL DEFAULT '[]',\n payload TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n concurrency_key TEXT,\n worker_id TEXT,\n report TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n started_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n finished_at DATETIME DEFAULT CURRENT_TIMESTAMP\n );\n\n CREATE TABLE IF NOT EXISTS step_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n job_id INTEGER NOT NULL,\n step_id TEXT NOT NULL,\n log_content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY(job_id) REFERENCES jobs(id) ON DELETE CASCADE\n );\n\n CREATE INDEX IF NOT EXISTS idx_step_logs_job ON step_logs(job_id);\n\n DELETE FROM step_logs\n WHERE id NOT IN (\n SELECT MAX(id) FROM step_logs GROUP BY job_id, step_id\n );\n CREATE UNIQUE INDEX IF NOT EXISTS idx_step_logs_job_step ON step_logs(job_id, step_id);\n\n CREATE TABLE IF NOT EXISTS stored_files (\n kind TEXT NOT NULL,\n owner_key TEXT NOT NULL,\n file_path TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (kind, owner_key, file_path)\n );\n CREATE INDEX IF NOT EXISTS idx_stored_files_owner ON stored_files(kind, owner_key);\n\n CREATE TABLE IF NOT EXISTS worker_presence (\n worker_id TEXT PRIMARY KEY,\n version TEXT NOT NULL,\n tags TEXT NOT NULL DEFAULT '[]',\n concurrency INTEGER NOT NULL DEFAULT 0,\n active_jobs INTEGER NOT NULL DEFAULT 0,\n last_seen DATETIME DEFAULT CURRENT_TIMESTAMP\n );\n ");
284
284
  }
285
285
  async getJob(e) {
286
286
  return C.get("SELECT * FROM jobs WHERE id = ?", [e]);
@@ -326,6 +326,26 @@ var ye = class extends l {
326
326
  async getStoredFiles(e, t) {
327
327
  return this.fileStorage.enabled ? this.fileStorage.load(`${e}/${t}`) : C.all("SELECT file_path AS path, content FROM stored_files WHERE kind = ? AND owner_key = ?", [e, t]);
328
328
  }
329
+ async updateWorkerPresence(e) {
330
+ await C.run("INSERT INTO worker_presence (worker_id, version, tags, concurrency, active_jobs, last_seen)\n VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)\n ON CONFLICT(worker_id) DO UPDATE SET version = excluded.version, tags = excluded.tags,\n concurrency = excluded.concurrency, active_jobs = excluded.active_jobs, last_seen = CURRENT_TIMESTAMP", [
331
+ e.id,
332
+ e.version,
333
+ JSON.stringify(e.tags),
334
+ e.concurrency,
335
+ e.activeJobs
336
+ ]);
337
+ }
338
+ async listWorkerPresence() {
339
+ return (await C.all("SELECT worker_id, version, tags, concurrency, active_jobs, last_seen FROM worker_presence ORDER BY worker_id")).map((e) => ({
340
+ workerId: e.worker_id,
341
+ version: e.version,
342
+ tags: JSON.parse(e.tags || "[]"),
343
+ concurrency: e.concurrency,
344
+ activeJobs: e.active_jobs,
345
+ lastSeen: e.last_seen,
346
+ online: Date.now() - Date.parse(`${e.last_seen}Z`) < 45e3
347
+ }));
348
+ }
329
349
  async saveAiRequest(e, t, n) {
330
350
  await C.run("INSERT INTO ai_requests (job_id, workflow_url, request_json) VALUES (?, ?, ?)", [
331
351
  e,
@@ -6340,7 +6360,8 @@ var oa = {
6340
6360
  "logs:read",
6341
6361
  "artifacts:read",
6342
6362
  "runs:control",
6343
- "runs:dispatch"
6363
+ "runs:dispatch",
6364
+ "workers:read"
6344
6365
  ], ca = class {
6345
6366
  async init() {
6346
6367
  await C.exec("CREATE TABLE IF NOT EXISTS api_keys (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n key_hash TEXT NOT NULL UNIQUE,\n scopes TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n last_used_at DATETIME,\n revoked_at DATETIME\n )");
@@ -6375,7 +6396,7 @@ var oa = {
6375
6396
  let t = await C.run("UPDATE api_keys SET revoked_at = CURRENT_TIMESTAMP WHERE id = ? AND revoked_at IS NULL", [e]);
6376
6397
  return Number(t?.changes || 0) > 0;
6377
6398
  }
6378
- }, la = "<!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\" />\n <title>Runner settings</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n <link rel=\"component\" href=\"https://sodium.static.apphor.de/lucide-icon.html\" />\n <link rel=\"component\" href=\"/app-header.html\" />\n </head>\n <body data-page=\"__SETTINGS_PAGE__\" class=\"min-h-screen bg-gray-950 p-4 font-sans text-gray-100 md:p-6\">\n <template app>\n <main class=\"mx-auto max-w-6xl space-y-5 py-6\">\n <app-header title=\"Settings\" subtitle=\"Human-admin controls and automation credentials\" back=\"/runs\" back-label=\"Back to jobs\"></app-header>\n <nav class=\"flex flex-wrap gap-1 rounded-xl border border-gray-800 bg-gray-900/70 p-1\" aria-label=\"Settings navigation\">\n <a href=\"/settings/workflows\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Workflows</a>\n <a href=\"/settings/secrets\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Secrets</a>\n <a href=\"/settings/tokens\" bind-class=\"page === 'tokens' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">API tokens</a>\n <a href=\"/settings/notifications\" bind-class=\"page === 'notifications' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Notifications</a>\n </nav>\n\n <template if=\"page === 'tokens'\">\n </template>\n <template if=\"page === 'notifications'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"notifications-title\">\n <h2 id=\"notifications-title\" class=\"text-lg font-semibold text-white\">Notifications</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Receive job completion notifications on this device.</p>\n <button type=\"button\" on-click=\"toggleNotifications()\" class=\"mt-5 inline-flex items-center gap-2 rounded-lg border border-indigo-500/60 px-4 py-2.5 text-sm font-medium text-indigo-200 outline-none hover:bg-indigo-500/10 focus-visible:ring-2 focus-visible:ring-indigo-400/60\">\n <lucide-icon bind-icon=\"notificationsEnabled ? 'bell-off' : 'bell-ring'\" size=\"16\"></lucide-icon>\n {{ notificationsEnabled ? 'Disable notifications' : 'Enable notifications' }}\n </button>\n <p class=\"mt-3 text-sm text-gray-400\" role=\"status\">{{ notificationMessage }}</p>\n </section>\n </template>\n\n <template if=\"page === 'tokens'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"keys-title\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <h2 id=\"keys-title\" class=\"text-lg font-semibold text-white\">API keys</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Issue narrowly scoped credentials for automation tools. Keys are shown only once.</p>\n </div>\n </div>\n <div class=\"mt-5 grid gap-3 rounded-xl border border-gray-800 bg-gray-950/50 p-4 md:grid-cols-[1fr_auto]\">\n <label class=\"sr-only\" for=\"key-name\">Key name</label>\n <input id=\"key-name\" bind-value=\"keyName\" on-input=\"setKeyName($event)\" placeholder=\"Documentation bot\" class=\"rounded-lg border border-gray-700 bg-gray-900 px-3 py-2.5 text-sm outline-none focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/30\" />\n <button type=\"button\" on-click=\"issueKey()\" class=\"inline-flex items-center justify-center gap-2 rounded-lg bg-indigo-500 px-4 py-2.5 text-sm font-semibold text-white outline-none hover:bg-indigo-400 focus-visible:ring-2 focus-visible:ring-indigo-400/60\"><lucide-icon icon=\"key-round\" size=\"16\"></lucide-icon>Issue key</button>\n <fieldset class=\"md:col-span-2\">\n <legend class=\"mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500\">Scopes</legend>\n <div class=\"space-y-2\">\n <template for=\"scope of scopeOptions\">\n <label class=\"group flex cursor-pointer items-center gap-3 text-sm text-gray-300\">\n <input type=\"checkbox\" bind-checked=\"scope.selected\" on-change=\"toggleScope(scope)\" class=\"peer sr-only\" />\n <span aria-hidden=\"true\" class=\"flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-gray-600 bg-gray-900 text-transparent transition peer-checked:border-indigo-400 peer-checked:bg-indigo-500 peer-checked:text-white peer-focus-visible:ring-2 peer-focus-visible:ring-indigo-400/70 peer-disabled:opacity-50\">\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m3 8 3 3 7-7\"></path></svg>\n </span>\n <span class=\"group-hover:text-white\">{{ scope.label }}</span>\n </label>\n </template>\n </div>\n </fieldset>\n </div>\n <template if=\"newToken\">\n <div class=\"mt-4 rounded-xl border border-amber-500/40 bg-amber-500/10 p-4\" role=\"alert\">\n <p class=\"text-sm font-semibold text-amber-200\">Copy this key now. It cannot be shown again.</p>\n <code class=\"mt-2 block select-all break-all rounded bg-gray-950 p-3 font-mono text-xs text-amber-100\">{{ newToken }}</code>\n </div>\n </template>\n <h3 class=\"mt-5 text-xs font-semibold uppercase tracking-wider text-gray-500\">Active tokens</h3>\n <ul class=\"mt-2 space-y-2\" aria-label=\"Active API keys\">\n <template for=\"key of keys\">\n <li class=\"flex items-center justify-between gap-3 rounded-xl border border-gray-800 bg-gray-950/60 px-4 py-3\">\n <div class=\"min-w-0\"><p class=\"truncate text-sm font-medium text-gray-200\">{{ key.name }}</p><p class=\"text-xs text-gray-500\">{{ key.scopes.join(', ') }} · created {{ key.created_at }}</p></div>\n <button type=\"button\" on-click=\"revokeKey(key)\" class=\"shrink-0 rounded-lg p-2 text-rose-300 outline-none hover:bg-rose-500/10 focus-visible:ring-2 focus-visible:ring-rose-400/60\" aria-label=\"Revoke {{ key.name }}\" title=\"Revoke key\"><lucide-icon icon=\"trash\" size=\"16\"></lucide-icon></button>\n </li>\n </template>\n </ul>\n </section>\n </template>\n <p class=\"text-sm text-rose-300\" role=\"alert\" class-hidden=\"!error\">{{ error }}</p>\n </main>\n <script setup>\n import { onInit, ref } from '@li3/web';\n export default function () {\n const page = document.body.dataset.page;\n const keys = ref([]);\n const keyName = ref('');\n const newToken = ref('');\n const error = ref('');\n const notificationsSupported = ref('Notification' in window && 'serviceWorker' in navigator);\n const notificationsEnabled = ref(notificationsSupported.value && Notification.permission === 'granted' && localStorage.getItem('runner-notifications') === 'enabled');\n const notificationMessage = ref('');\n const scopeOptions = ref([\n { name: 'workflows:read', label: 'Read workflows', selected: true },\n { name: 'workflows:write', label: 'Modify workflows', selected: false },\n { name: 'logs:read', label: 'Read logs', selected: false },\n { name: 'artifacts:read', label: 'Read artifacts', selected: false },\n { name: 'runs:control', label: 'Control runs', selected: false },\n { name: 'runs:dispatch', label: 'Dispatch runs', selected: false },\n ]);\n const api = async (url, options = {}) => { const response = await fetch(url, { headers: { accept: 'application/json', ...(options.body ? { 'content-type': 'application/json' } : {}) }, ...options }); const body = await response.json().catch(() => ({})); if (!response.ok) throw new Error(body.error || `Request failed: ${response.status}`); return body; };\n const load = async () => { keys.value = (await api('/api/api-keys')).keys; };\n const issueKey = async () => { try { error.value = ''; const result = await api('/api/api-keys', { method: 'POST', body: JSON.stringify({ name: keyName.value, scopes: scopeOptions.value.filter((scope) => scope.selected).map((scope) => scope.name) }) }); newToken.value = result.token; keyName.value = ''; await load(); } catch (reason) { error.value = reason.message; } };\n const revokeKey = async (key) => { if (!confirm(`Revoke ${key.name}?`)) return; try { await api(`/api/api-keys/${key.id}`, { method: 'DELETE' }); await load(); } catch (reason) { error.value = reason.message; } };\n const setKeyName = (event) => { keyName.value = event.target.value; };\n const toggleScope = (scope) => { scope.selected = !scope.selected; };\n const toggleNotifications = async () => {\n if (notificationsEnabled.value) {\n notificationsEnabled.value = false;\n localStorage.removeItem('runner-notifications');\n notificationMessage.value = 'Notifications disabled on this device.';\n return;\n }\n if (!notificationsSupported.value) { notificationMessage.value = 'Notifications are not supported by this browser.'; return; }\n const permission = await Notification.requestPermission();\n notificationsEnabled.value = permission === 'granted';\n if (notificationsEnabled.value) { localStorage.setItem('runner-notifications', 'enabled'); notificationMessage.value = 'Notifications enabled.'; }\n else notificationMessage.value = 'Notification permission was not granted.';\n };\n onInit(() => { if (page === 'tokens') load().catch((reason) => { error.value = reason.message; }); });\n return { page, keys, keyName, newToken, error, scopeOptions, issueKey, revokeKey, setKeyName, toggleScope, notificationsEnabled, notificationMessage, toggleNotifications };\n }\n <\/script>\n </template>\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n </body>\n</html>\n";
6399
+ }, la = "<!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\" />\n <title>Runner settings</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n <link rel=\"component\" href=\"https://sodium.static.apphor.de/lucide-icon.html\" />\n <link rel=\"component\" href=\"/app-header.html\" />\n </head>\n <body data-page=\"__SETTINGS_PAGE__\" class=\"min-h-screen bg-gray-950 p-4 font-sans text-gray-100 md:p-6\">\n <template app>\n <main class=\"mx-auto max-w-6xl space-y-5 py-6\">\n <app-header title=\"Settings\" subtitle=\"Human-admin controls and automation credentials\" back=\"/runs\" back-label=\"Back to jobs\"></app-header>\n <nav class=\"flex flex-wrap gap-1 rounded-xl border border-gray-800 bg-gray-900/70 p-1\" aria-label=\"Settings navigation\">\n <a href=\"/settings/workflows\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Workflows</a>\n <a href=\"/settings/secrets\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Secrets</a>\n <a href=\"/settings/tokens\" bind-class=\"page === 'tokens' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">API tokens</a>\n <a href=\"/settings/notifications\" bind-class=\"page === 'notifications' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Notifications</a>\n <a href=\"/settings/workers\" bind-class=\"page === 'workers' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Workers</a>\n </nav>\n\n <template if=\"page === 'tokens'\">\n </template>\n <template if=\"page === 'notifications'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"notifications-title\">\n <h2 id=\"notifications-title\" class=\"text-lg font-semibold text-white\">Notifications</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Receive job completion notifications on this device.</p>\n <button type=\"button\" on-click=\"toggleNotifications()\" class=\"mt-5 inline-flex items-center gap-2 rounded-lg border border-indigo-500/60 px-4 py-2.5 text-sm font-medium text-indigo-200 outline-none hover:bg-indigo-500/10 focus-visible:ring-2 focus-visible:ring-indigo-400/60\">\n <lucide-icon bind-icon=\"notificationsEnabled ? 'bell-off' : 'bell-ring'\" size=\"16\"></lucide-icon>\n {{ notificationsEnabled ? 'Disable notifications' : 'Enable notifications' }}\n </button>\n <p class=\"mt-3 text-sm text-gray-400\" role=\"status\">{{ notificationMessage }}</p>\n </section>\n </template>\n\n <template if=\"page === 'workers'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"workers-title\">\n <h2 id=\"workers-title\" class=\"text-lg font-semibold text-white\">Workers</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Connected runner status, versions, tags, and load.</p>\n <div class=\"mt-5 overflow-hidden rounded-xl border border-gray-800\"><table class=\"w-full text-left text-sm\"><thead class=\"bg-gray-950 text-xs uppercase text-gray-500\"><tr><th class=\"px-4 py-3\">Worker</th><th class=\"px-4 py-3\">Version</th><th class=\"px-4 py-3\">Tags</th><th class=\"px-4 py-3\">Load</th><th class=\"px-4 py-3\">Last seen</th></tr></thead><tbody><template for=\"worker of workers\"><tr class=\"border-t border-gray-800\"><td class=\"px-4 py-3 font-mono text-gray-200\">{{ worker.workerId }} <span class=\"ml-2 rounded-full px-2 py-0.5 text-xs\" bind-class=\"worker.online ? 'bg-emerald-500/10.text-emerald-300' : 'bg-gray-800.text-gray-500'\">{{ worker.online ? 'online' : 'offline' }}</span></td><td class=\"px-4 py-3 font-mono text-gray-400\">{{ worker.version }}</td><td class=\"px-4 py-3 text-gray-400\">{{ worker.tags.join(', ') }}</td><td class=\"px-4 py-3 text-gray-400\">{{ worker.activeJobs }} / {{ worker.concurrency }}</td><td class=\"px-4 py-3 text-gray-500\">{{ worker.lastSeen }}</td></tr></template></tbody></table><p class=\"p-5 text-sm text-gray-500\" class-hidden=\"workers.length > 0\">No worker heartbeats received yet.</p></div>\n </section>\n </template>\n\n <template if=\"page === 'tokens'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"keys-title\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <h2 id=\"keys-title\" class=\"text-lg font-semibold text-white\">API keys</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Issue narrowly scoped credentials for automation tools. Keys are shown only once.</p>\n </div>\n </div>\n <div class=\"mt-5 grid gap-3 rounded-xl border border-gray-800 bg-gray-950/50 p-4 md:grid-cols-[1fr_auto]\">\n <label class=\"sr-only\" for=\"key-name\">Key name</label>\n <input id=\"key-name\" bind-value=\"keyName\" on-input=\"setKeyName($event)\" placeholder=\"Documentation bot\" class=\"rounded-lg border border-gray-700 bg-gray-900 px-3 py-2.5 text-sm outline-none focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/30\" />\n <button type=\"button\" on-click=\"issueKey()\" class=\"inline-flex items-center justify-center gap-2 rounded-lg bg-indigo-500 px-4 py-2.5 text-sm font-semibold text-white outline-none hover:bg-indigo-400 focus-visible:ring-2 focus-visible:ring-indigo-400/60\"><lucide-icon icon=\"key-round\" size=\"16\"></lucide-icon>Issue key</button>\n <fieldset class=\"md:col-span-2\">\n <legend class=\"mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500\">Scopes</legend>\n <div class=\"space-y-2\">\n <template for=\"scope of scopeOptions\">\n <label class=\"group flex cursor-pointer items-center gap-3 text-sm text-gray-300\">\n <input type=\"checkbox\" bind-checked=\"scope.selected\" on-change=\"toggleScope(scope)\" class=\"peer sr-only\" />\n <span aria-hidden=\"true\" class=\"flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-gray-600 bg-gray-900 text-transparent transition peer-checked:border-indigo-400 peer-checked:bg-indigo-500 peer-checked:text-white peer-focus-visible:ring-2 peer-focus-visible:ring-indigo-400/70 peer-disabled:opacity-50\">\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m3 8 3 3 7-7\"></path></svg>\n </span>\n <span class=\"group-hover:text-white\">{{ scope.label }}</span>\n </label>\n </template>\n </div>\n </fieldset>\n </div>\n <template if=\"newToken\">\n <div class=\"mt-4 rounded-xl border border-amber-500/40 bg-amber-500/10 p-4\" role=\"alert\">\n <p class=\"text-sm font-semibold text-amber-200\">Copy this key now. It cannot be shown again.</p>\n <code class=\"mt-2 block select-all break-all rounded bg-gray-950 p-3 font-mono text-xs text-amber-100\">{{ newToken }}</code>\n </div>\n </template>\n <h3 class=\"mt-5 text-xs font-semibold uppercase tracking-wider text-gray-500\">Active tokens</h3>\n <ul class=\"mt-2 space-y-2\" aria-label=\"Active API keys\">\n <template for=\"key of keys\">\n <li class=\"flex items-center justify-between gap-3 rounded-xl border border-gray-800 bg-gray-950/60 px-4 py-3\">\n <div class=\"min-w-0\"><p class=\"truncate text-sm font-medium text-gray-200\">{{ key.name }}</p><p class=\"text-xs text-gray-500\">{{ key.scopes.join(', ') }} · created {{ key.created_at }}</p></div>\n <button type=\"button\" on-click=\"revokeKey(key)\" class=\"shrink-0 rounded-lg p-2 text-rose-300 outline-none hover:bg-rose-500/10 focus-visible:ring-2 focus-visible:ring-rose-400/60\" aria-label=\"Revoke {{ key.name }}\" title=\"Revoke key\"><lucide-icon icon=\"trash\" size=\"16\"></lucide-icon></button>\n </li>\n </template>\n </ul>\n </section>\n </template>\n <p class=\"text-sm text-rose-300\" role=\"alert\" class-hidden=\"!error\">{{ error }}</p>\n </main>\n <script setup>\n import { onInit, ref } from '@li3/web';\n export default function () {\n const page = document.body.dataset.page;\n const keys = ref([]);\n const workers = ref([]);\n const keyName = ref('');\n const newToken = ref('');\n const error = ref('');\n const notificationsSupported = ref('Notification' in window && 'serviceWorker' in navigator);\n const notificationsEnabled = ref(notificationsSupported.value && Notification.permission === 'granted' && localStorage.getItem('runner-notifications') === 'enabled');\n const notificationMessage = ref('');\n const scopeOptions = ref([\n { name: 'workflows:read', label: 'Read workflows', selected: true },\n { name: 'workflows:write', label: 'Modify workflows', selected: false },\n { name: 'logs:read', label: 'Read logs', selected: false },\n { name: 'artifacts:read', label: 'Read artifacts', selected: false },\n { name: 'runs:control', label: 'Control runs', selected: false },\n { name: 'runs:dispatch', label: 'Dispatch runs', selected: false },\n ]);\n const api = async (url, options = {}) => { const response = await fetch(url, { headers: { accept: 'application/json', ...(options.body ? { 'content-type': 'application/json' } : {}) }, ...options }); const body = await response.json().catch(() => ({})); if (!response.ok) throw new Error(body.error || `Request failed: ${response.status}`); return body; };\n const load = async () => { keys.value = (await api('/api/api-keys')).keys; };\n const loadWorkers = async () => { workers.value = (await api('/api/workers')).workers; };\n const issueKey = async () => { try { error.value = ''; const result = await api('/api/api-keys', { method: 'POST', body: JSON.stringify({ name: keyName.value, scopes: scopeOptions.value.filter((scope) => scope.selected).map((scope) => scope.name) }) }); newToken.value = result.token; keyName.value = ''; await load(); } catch (reason) { error.value = reason.message; } };\n const revokeKey = async (key) => { if (!confirm(`Revoke ${key.name}?`)) return; try { await api(`/api/api-keys/${key.id}`, { method: 'DELETE' }); await load(); } catch (reason) { error.value = reason.message; } };\n const setKeyName = (event) => { keyName.value = event.target.value; };\n const toggleScope = (scope) => { scope.selected = !scope.selected; };\n const toggleNotifications = async () => {\n if (notificationsEnabled.value) {\n notificationsEnabled.value = false;\n localStorage.removeItem('runner-notifications');\n notificationMessage.value = 'Notifications disabled on this device.';\n return;\n }\n if (!notificationsSupported.value) { notificationMessage.value = 'Notifications are not supported by this browser.'; return; }\n const permission = await Notification.requestPermission();\n notificationsEnabled.value = permission === 'granted';\n if (notificationsEnabled.value) { localStorage.setItem('runner-notifications', 'enabled'); notificationMessage.value = 'Notifications enabled.'; }\n else notificationMessage.value = 'Notification permission was not granted.';\n };\n onInit(() => { if (page === 'tokens') load().catch((reason) => { error.value = reason.message; }); if (page === 'workers') loadWorkers().catch((reason) => { error.value = reason.message; }); });\n return { page, keys, workers, keyName, newToken, error, scopeOptions, issueKey, revokeKey, setKeyName, toggleScope, notificationsEnabled, notificationMessage, toggleNotifications };\n }\n <\/script>\n </template>\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n </body>\n</html>\n";
6379
6400
  //#endregion
6380
6401
  //#region src/settings-ui.ts
6381
6402
  function ua(e = "tokens") {
@@ -20852,6 +20873,26 @@ var SC = class {
20852
20873
  "Cache-Control": "no-store",
20853
20874
  "Content-Type": "application/json; charset=utf-8"
20854
20875
  }), t.end(JSON.stringify(oa));
20876
+ if (e.method === "POST" && n.pathname === "/api/workers/heartbeat") {
20877
+ if (!this.isWorker(e)) {
20878
+ t.writeHead(403, { "Content-Type": "application/json" }).end(JSON.stringify({ error: "Unauthorized" }));
20879
+ return;
20880
+ }
20881
+ let n = await this.readJson(e, t);
20882
+ if (!n || n.workerId !== e.headers["x-runner-worker-id"]) return;
20883
+ await this.queue.updateWorkerPresence({
20884
+ id: n.workerId,
20885
+ version: String(n.version || "unknown"),
20886
+ tags: Array.isArray(n.tags) ? n.tags : [],
20887
+ concurrency: Number(n.concurrency || 0),
20888
+ activeJobs: Number(n.activeJobs || 0)
20889
+ }), t.writeHead(204).end();
20890
+ return;
20891
+ }
20892
+ if (e.method === "GET" && n.pathname === "/api/workers") return await this.hasScope(e, "workers:read") ? (t.writeHead(200, {
20893
+ "Cache-Control": "no-store",
20894
+ "Content-Type": "application/json; charset=utf-8"
20895
+ }), t.end(JSON.stringify({ workers: await this.queue.listWorkerPresence() }))) : this.requireScope(e, t, "workers:read");
20855
20896
  if (e.method === "GET" && n.pathname === "/pages/dashboard.html") return this.renderPageComponent(t, "page-dashboard", Ce);
20856
20897
  if (e.method === "GET" && n.pathname === "/pages/run.html") return this.renderPageComponent(t, "page-run", Fe);
20857
20898
  if (e.method === "GET" && n.pathname === "/pages/help.html") return this.renderPageComponent(t, "page-help", aa(!1), !0);
@@ -20867,7 +20908,7 @@ var SC = class {
20867
20908
  }
20868
20909
  if (e.method === "GET" && n.pathname === "/workflows") return this.requireAdmin(e, t) ? (t.writeHead(302, { Location: "/settings/workflows" }), t.end()) : void 0;
20869
20910
  if (e.method === "GET" && n.pathname === "/settings") return this.isAdmin(e) ? (t.writeHead(302, { Location: "/settings/workflows" }), t.end()) : this.requireAdmin(e, t);
20870
- let r = n.pathname.match(/^\/settings\/(workflows|secrets|tokens|notifications)$/);
20911
+ let r = n.pathname.match(/^\/settings\/(workflows|secrets|tokens|notifications|workers)$/);
20871
20912
  if (e.method === "GET" && r) return this.requireAdmin(e, t) ? (r[1], this.renderAppShell(t)) : void 0;
20872
20913
  if (n.pathname === "/api/api-keys") {
20873
20914
  if (!this.isAdmin(e)) return this.requireAdmin(e, t);
@@ -21712,7 +21753,7 @@ async function AC(e) {
21712
21753
  if (!t) {
21713
21754
  t = !0, console.log(`\n🛑 Received ${n}. Initiating graceful shutdown...`);
21714
21755
  try {
21715
- BC(), 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);
21756
+ VC(), 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);
21716
21757
  } catch (e) {
21717
21758
  console.error("❌ Error during graceful shutdown:", e.message), process.exit(1);
21718
21759
  }
@@ -21803,59 +21844,102 @@ PC("github-status", (e) => {
21803
21844
  });
21804
21845
  });
21805
21846
  //#endregion
21806
- //#region src/worker.ts
21807
- var IC = { isStopping: !1 }, LC = /* @__PURE__ */ new Set(), RC = null, zC = null;
21808
- function BC() {
21809
- IC.isStopping = !0, RC?.abort(), zC?.();
21810
- }
21811
- function VC(e, t, n, r) {
21812
- IC.isStopping = !1;
21813
- let i = [HC(e, t, n, r)];
21847
+ //#region src/version.ts
21848
+ var IC = {
21849
+ name: "@cloud-cli/on",
21850
+ version: "0.0.0",
21851
+ description: "CLI entry point for the on plugin ecosystem.",
21852
+ type: "module",
21853
+ packageManager: "pnpm@12.3.4",
21854
+ license: "MIT",
21855
+ exports: { ".": {
21856
+ types: "./dist/index.d.ts",
21857
+ default: "./dist/on.js"
21858
+ } },
21859
+ files: ["dist"],
21860
+ main: "dist/on.js",
21861
+ bin: { on: "dist/on.js" },
21862
+ dependencies: {
21863
+ acorn: "^8.18.0",
21864
+ openai: "7.15.0",
21865
+ "web-push": "^3.6.7",
21866
+ yaml: "^2.9.0"
21867
+ },
21868
+ scripts: {
21869
+ ci: "pnpm build && pnpm lint && pnpm test",
21870
+ build: "vite build && tsc --emitDeclarationOnly --declaration",
21871
+ lint: "eslint .",
21872
+ test: "vitest run",
21873
+ "test:e2e": "docker build --no-cache -t on:e2e . && node tests/docker-smoke.mjs",
21874
+ release: "npx --yes semantic-release@24 -b main --no-ci"
21875
+ },
21876
+ devDependencies: {
21877
+ "@changesets/cli": "^2.31.1",
21878
+ "@eslint/js": "^10.0.1",
21879
+ "@types/node": "^26.5.1",
21880
+ "@types/web-push": "^3.6.4",
21881
+ "@typescript-eslint/eslint-plugin": "^8.70.0",
21882
+ "@typescript-eslint/parser": "^8.70.0",
21883
+ eslint: "10.8.0",
21884
+ marked: "^18.0.12",
21885
+ tsx: "4.23.13",
21886
+ typescript: "6.0.3",
21887
+ "typescript-eslint": "8.70.0",
21888
+ vite: "8.2.0",
21889
+ vitest: "4.1.11"
21890
+ }
21891
+ }.version, LC = { isStopping: !1 }, RC = /* @__PURE__ */ new Set(), zC = null, BC = null;
21892
+ function VC() {
21893
+ LC.isStopping = !0, zC?.abort(), BC?.();
21894
+ }
21895
+ function HC(e, t, n, r) {
21896
+ LC.isStopping = !1;
21897
+ let i = [UC(e, t, n, r)];
21814
21898
  return AC(i), i;
21815
21899
  }
21816
- async function HC(e, t, n, r) {
21900
+ async function UC(e, t, n, r) {
21817
21901
  let i = await kC(), a = new SC(), o = /* @__PURE__ */ new Set(), s = 0, c = null, l = () => {
21818
21902
  s++, c?.();
21819
- };
21820
- zC = l, RC = new AbortController();
21821
- let u = UC(r, RC.signal, l);
21822
- for (console.log(`🚀 Worker scheduler started. Driver: ${i.name}. Concurrency: ${e}. Tags: ${r.tags.join(", ") || "(none)"}`); !IC.isStopping;) {
21903
+ }, u = process.env.WORKER_NAME || "cli";
21904
+ BC = l, zC = new AbortController();
21905
+ let d = WC(r, zC.signal, l), f = setInterval(() => void JC(r, u, e, o.size), 15e3);
21906
+ for (f.unref(), JC(r, u, e, o.size), console.log(`🚀 Worker scheduler started. Driver: ${i.name}. Concurrency: ${e}. Tags: ${r.tags.join(", ") || "(none)"}`); !LC.isStopping;) {
21823
21907
  let n = s;
21824
21908
  try {
21825
- for (; o.size < e && !IC.isStopping;) {
21909
+ for (; o.size < e && !LC.isStopping;) {
21826
21910
  let e = await t.claimNextJob(r.tags);
21827
21911
  if (!e) break;
21828
- if (IC.isStopping) {
21912
+ if (LC.isStopping) {
21829
21913
  await t.releaseJob(e.id);
21830
21914
  break;
21831
21915
  }
21832
- let n = process.env.WORKER_NAME || "cli", s;
21833
- s = (async () => {
21834
- KC(r, e.id);
21835
- let o = await a.getRevision(e.workflow_id, e.workflow_revision);
21836
- if (!o) throw await t.finishJob(e.id, "failed"), Error(`Workflow ${e.workflow_id} revision ${e.workflow_revision} was not found`);
21837
- let s = new Se();
21838
- s.replace(await qC(r, n, e.id)), await JC({
21839
- workerId: n,
21916
+ let n;
21917
+ n = (async () => {
21918
+ qC(r, e.id);
21919
+ let n = await a.getRevision(e.workflow_id, e.workflow_revision);
21920
+ if (!n) throw await t.finishJob(e.id, "failed"), Error(`Workflow ${e.workflow_id} revision ${e.workflow_revision} was not found`);
21921
+ let o = new Se();
21922
+ o.replace(await YC(r, u, e.id)), await XC({
21923
+ workerId: u,
21840
21924
  job: e,
21841
21925
  queue: t,
21842
- secrets: s,
21926
+ secrets: o,
21843
21927
  config: r,
21844
21928
  driver: i,
21845
- workflow: o
21929
+ workflow: n
21846
21930
  });
21847
- })().catch((e) => console.error(`[${n}] ⚠️ Worker execution error:`, e)).finally(() => {
21848
- o.delete(s), KC(r, e.id), l();
21849
- }), o.add(s);
21931
+ })().catch((e) => console.error(`[${u}] ⚠️ Worker execution error:`, e)).finally(() => {
21932
+ o.delete(n), qC(r, e.id), l();
21933
+ }), o.add(n);
21850
21934
  }
21851
21935
  } catch (e) {
21852
21936
  console.error("⚠️ Worker scheduler claim error:", e), setTimeout(l, 5e3).unref();
21853
21937
  }
21854
- !IC.isStopping && s === n && (await WC(n, () => s, (e) => c = e), c = null);
21938
+ !LC.isStopping && s === n && (await GC(n, () => s, (e) => c = e), c = null);
21855
21939
  }
21856
- RC.abort(), await Promise.allSettled(o), await u, zC = null, console.log("🛑 Worker scheduler stopped cleanly.");
21940
+ zC.abort(), clearInterval(f), await Promise.allSettled(o), await d, BC = null, console.log("🛑 Worker scheduler stopped cleanly.");
21857
21941
  }
21858
- async function UC(e, t, n) {
21942
+ async function WC(e, t, n) {
21859
21943
  let r = 1e3;
21860
21944
  for (; !t.aborted;) {
21861
21945
  try {
@@ -21866,10 +21950,10 @@ async function UC(e, t, n) {
21866
21950
  if (t.aborted || e?.name === "AbortError") break;
21867
21951
  console.error(`⚠️ Worker event stream disconnected: ${e.message}`);
21868
21952
  }
21869
- await GC(r, t), r = Math.min(r * 2, 3e4);
21953
+ await KC(r, t), r = Math.min(r * 2, 3e4);
21870
21954
  }
21871
21955
  }
21872
- function WC(e, t, n) {
21956
+ function GC(e, t, n) {
21873
21957
  return new Promise((r) => {
21874
21958
  if (t() !== e) return r();
21875
21959
  let i = setTimeout(r, 6e4);
@@ -21878,7 +21962,7 @@ function WC(e, t, n) {
21878
21962
  });
21879
21963
  });
21880
21964
  }
21881
- function GC(e, t) {
21965
+ function KC(e, t) {
21882
21966
  return new Promise((n) => {
21883
21967
  if (t.aborted) return n();
21884
21968
  let r = () => {
@@ -21889,7 +21973,7 @@ function GC(e, t) {
21889
21973
  t.addEventListener("abort", r, { once: !0 });
21890
21974
  });
21891
21975
  }
21892
- async function KC(e, t) {
21976
+ async function qC(e, t) {
21893
21977
  if (e.workerToken) try {
21894
21978
  let n = await fetch(new URL("/api/events", e.serverUrl), {
21895
21979
  method: "POST",
@@ -21905,7 +21989,29 @@ async function KC(e, t) {
21905
21989
  dr("Failed to publish job status event:", e);
21906
21990
  }
21907
21991
  }
21908
- async function qC(e, t, n) {
21992
+ async function JC(e, t, n, r) {
21993
+ if (e.workerToken) try {
21994
+ await fetch(new URL("/api/workers/heartbeat", e.serverUrl), {
21995
+ method: "POST",
21996
+ headers: {
21997
+ Authorization: `Bearer ${e.workerToken}`,
21998
+ "Content-Type": "application/json",
21999
+ "X-Runner-Worker-Id": t
22000
+ },
22001
+ body: JSON.stringify({
22002
+ workerId: t,
22003
+ version: IC,
22004
+ tags: e.tags,
22005
+ concurrency: n,
22006
+ activeJobs: r
22007
+ }),
22008
+ signal: AbortSignal.timeout(5e3)
22009
+ });
22010
+ } catch (e) {
22011
+ dr("Failed to publish worker heartbeat:", e);
22012
+ }
22013
+ }
22014
+ async function YC(e, t, n) {
21909
22015
  if (!e.workerToken) return {};
21910
22016
  try {
21911
22017
  let r = await fetch(new URL(`/api/jobs/${n}/secrets`, e.serverUrl), {
@@ -21921,7 +22027,7 @@ async function qC(e, t, n) {
21921
22027
  throw console.error(`Unable to retrieve secrets for job ${n}:`, e), e;
21922
22028
  }
21923
22029
  }
21924
- async function JC(e) {
22030
+ async function XC(e) {
21925
22031
  let { workerId: t, job: n, config: r, secrets: a, queue: o } = e;
21926
22032
  console.log(`\n[${t}] 📦 Claimed Job #${n.id} (Workflow: ${n.workflow_id})`);
21927
22033
  let s = typeof n.payload == "string" ? JSON.parse(n.payload) : n.payload;
@@ -21933,7 +22039,12 @@ async function JC(e) {
21933
22039
  workflow: l
21934
22040
  }, d = l.steps, f = s.inputs || {}, p = Date.now(), m = i.join(r.storagePath, `job-${n.id}`), h = i.join(m, "logs"), g = i.join(m, "wd"), _ = {
21935
22041
  inputs: f,
21936
- env: { ...r.env },
22042
+ env: {
22043
+ ...r.env,
22044
+ CI: "true",
22045
+ CI_JOB_ID: String(n.id),
22046
+ CI_JOB_NAME: l.name
22047
+ },
21937
22048
  secrets: a.getAll(),
21938
22049
  steps: {},
21939
22050
  logsDir: h,
@@ -21946,10 +22057,14 @@ async function JC(e) {
21946
22057
  durationMs: 0,
21947
22058
  outputs: {},
21948
22059
  logContent: ""
21949
- })), b = cw(n, "running", p, f, _.env, y, s);
21950
- await o.saveReport(n.id, b), KC(r, n.id);
22060
+ })), b = uw(n, "running", p, f, _.env, y, s);
22061
+ await o.saveReport(n.id, b), qC(r, n.id);
21951
22062
  try {
21952
- Object.assign(_.env, await QC(l.env, _)), aw(l.secretFiles, a, g), v = l.cache ? String(await mr.evaluateValue(l.cache.key, _)) : "", v && l.cache && await iw(o, "cache", `${n.workflow_id}:${v}`, l.cache.paths, g), await o.saveReport(n.id, b);
22063
+ Object.assign(_.env, await ew(l.env, _)), Object.assign(_.env, {
22064
+ CI: "true",
22065
+ CI_JOB_ID: String(n.id),
22066
+ CI_JOB_NAME: l.name
22067
+ }), sw(l.secretFiles, a, g), v = l.cache ? String(await mr.evaluateValue(l.cache.key, _)) : "", v && l.cache && await ow(o, "cache", `${n.workflow_id}:${v}`, l.cache.paths, g), await o.saveReport(n.id, b);
21953
22068
  } catch (e) {
21954
22069
  b.status = "failed", b.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), b.durationMs = Date.now() - p;
21955
22070
  let r = {
@@ -21964,7 +22079,7 @@ async function JC(e) {
21964
22079
  }
21965
22080
  let x = [...r.plugins];
21966
22081
  for (let e of l.plugins || []) try {
21967
- let t = await QC(e.secrets, _);
22082
+ let t = await ew(e.secrets, _);
21968
22083
  x.push(FC({
21969
22084
  ...e,
21970
22085
  secrets: t
@@ -21979,24 +22094,24 @@ async function JC(e) {
21979
22094
  runUrl: new URL(`/runs/${n.id}`, r.serverUrl).toString()
21980
22095
  };
21981
22096
  await S.triggerWorkflowStart(ee);
21982
- let { cancelled: te, failed: ne } = await YC({
22097
+ let { cancelled: te, failed: ne } = await ZC({
21983
22098
  payload: s,
21984
22099
  steps: d,
21985
22100
  executionContext: _,
21986
22101
  ...u
21987
22102
  }, b), re = te ? "cancelled" : ne ? "failed" : "success";
21988
22103
  if (re === "success") try {
21989
- let e = l.artifacts ? await rw(l.artifacts.paths, g) : [];
22104
+ let e = l.artifacts ? await aw(l.artifacts.paths, g) : [];
21990
22105
  if (e.length && (await o.saveStoredFiles("artifact", String(n.id), e), b.artifacts = e.map((e) => e.path)), v && l.cache) {
21991
- let e = await rw(l.cache.paths, g);
22106
+ let e = await aw(l.cache.paths, g);
21992
22107
  e.length && await o.saveStoredFiles("cache", `${n.workflow_id}:${v}`, e);
21993
22108
  }
21994
22109
  } catch (e) {
21995
22110
  console.error(`[${t}] ⚠️ Failed to store workflow files:`, e), re = "failed";
21996
22111
  }
21997
- b.status = re, b.durationMs = Date.now() - p, b.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), await o.completeJob(n.id, re, b), KC(r, n.id), console.log(`[${t}] ✅ Job #${n.id} completed as: ${re}`), await S.triggerWorkflowFinish(ee, re);
22112
+ b.status = re, b.durationMs = Date.now() - p, b.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), await o.completeJob(n.id, re, b), qC(r, n.id), console.log(`[${t}] ✅ Job #${n.id} completed as: ${re}`), await S.triggerWorkflowFinish(ee, re);
21998
22113
  }
21999
- async function YC(e, t) {
22114
+ async function ZC(e, t) {
22000
22115
  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;
22001
22116
  try {
22002
22117
  for (let s = 0; s < c.length; s++) {
@@ -22011,14 +22126,14 @@ async function YC(e, t) {
22011
22126
  logContent: "",
22012
22127
  startedAt: h,
22013
22128
  finishedAt: void 0
22014
- }, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), KC(a, o.id);
22129
+ }, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), qC(a, o.id);
22015
22130
  let g = {
22016
22131
  failed: !0,
22017
22132
  skipped: !1,
22018
22133
  cancelled: !1,
22019
22134
  report: null
22020
22135
  }, _ = e.workflow?.retries ?? 0;
22021
- for (let e = 1; e <= _ + 1 && (g = await XC({
22136
+ for (let e = 1; e <= _ + 1 && (g = await QC({
22022
22137
  workerId: r,
22023
22138
  jobId: o.id,
22024
22139
  step: m,
@@ -22046,7 +22161,7 @@ async function YC(e, t) {
22046
22161
  exitCode: 1,
22047
22162
  error: "Step failed before execution started",
22048
22163
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
22049
- }, p = s + 1, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), KC(a, o.id), g.skipped) break;
22164
+ }, p = s + 1, t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), qC(a, o.id), g.skipped) break;
22050
22165
  if (g.cancelled) {
22051
22166
  f = !0, d = !0;
22052
22167
  break;
@@ -22059,13 +22174,13 @@ async function YC(e, t) {
22059
22174
  } catch (e) {
22060
22175
  console.log("🛑 Step failed", e), d = !0;
22061
22176
  }
22062
- return p < c.length && (sw(c, p, u), t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), KC(a, o.id)), {
22177
+ return p < c.length && (lw(c, p, u), t.durationMs = Date.now() - Date.parse(t.startedAt), await i.saveReport(o.id, t), qC(a, o.id)), {
22063
22178
  failed: d,
22064
22179
  cancelled: f,
22065
22180
  stepReports: u
22066
22181
  };
22067
22182
  }
22068
- async function XC(e) {
22183
+ async function QC(e) {
22069
22184
  let { step: t, stepIndex: n, executionContext: r } = e;
22070
22185
  if (t.id ||= `step-${n}`, t.name ||= t.id, t.if && !await mr.evaluateConditions(t.if, r)) return dr(`⏩ Skipped step ${t.id} based on condition: ${t.if}`, r), {
22071
22186
  failed: !1,
@@ -22074,7 +22189,7 @@ async function XC(e) {
22074
22189
  report: null
22075
22190
  };
22076
22191
  try {
22077
- let n = await QC(t.env, r), i = {
22192
+ let i = await ew(t.env, r), a = {
22078
22193
  jobId: String(e.jobId),
22079
22194
  step: t,
22080
22195
  command: t.run,
@@ -22087,16 +22202,19 @@ async function XC(e) {
22087
22202
  logsDir: r.logsDir,
22088
22203
  env: {
22089
22204
  ...r.env,
22090
- ...n,
22091
- WORKING_DIR: r.workingDir
22205
+ ...i,
22206
+ WORKING_DIR: r.workingDir,
22207
+ CI: "true",
22208
+ CI_JOB_ID: String(e.jobId),
22209
+ CI_JOB_NAME: r.env.CI_JOB_NAME || t.name || t.id || `step-${n}`
22092
22210
  }
22093
22211
  };
22094
- return t.eval ? ZC({
22212
+ return t.eval ? $C({
22095
22213
  ...e,
22096
- stepContext: i
22097
- }) : ow({
22214
+ stepContext: a
22215
+ }) : cw({
22098
22216
  ...e,
22099
- stepContext: i
22217
+ stepContext: a
22100
22218
  });
22101
22219
  } catch (n) {
22102
22220
  let i = n?.message || String(n);
@@ -22117,7 +22235,7 @@ async function XC(e) {
22117
22235
  };
22118
22236
  }
22119
22237
  }
22120
- async function ZC(e) {
22238
+ async function $C(e) {
22121
22239
  let { queue: t, stepContext: n, executionContext: r } = e, { jobId: i, step: a } = n, o = Date.now(), s = a.id, c = a.name, l;
22122
22240
  try {
22123
22241
  let e = new Promise((e, t) => {
@@ -22167,7 +22285,7 @@ async function ZC(e) {
22167
22285
  l && clearTimeout(l);
22168
22286
  }
22169
22287
  }
22170
- async function QC(e, t) {
22288
+ async function ew(e, t) {
22171
22289
  let n = {};
22172
22290
  if (e) for (let [r, i] of Object.entries(e)) n[r] = String(await mr.evaluateValue(i, {
22173
22291
  ...t,
@@ -22178,18 +22296,18 @@ async function QC(e, t) {
22178
22296
  }));
22179
22297
  return n;
22180
22298
  }
22181
- var $C = 52428800;
22182
- function ew(e, t) {
22299
+ var tw = 52428800;
22300
+ function nw(e, t) {
22183
22301
  let n = i.resolve(e), r = i.resolve(n, t);
22184
22302
  if (r !== n && !r.startsWith(`${n}${i.sep}`)) throw Error(`Stored file path escapes workspace: ${t}`);
22185
22303
  return r;
22186
22304
  }
22187
- function tw(e, t) {
22305
+ function rw(e, t) {
22188
22306
  let n = "^";
22189
22307
  for (let e = 0; e < t.length; e++) t[e] === "*" && t[e + 1] === "*" ? (n += ".*", e++) : t[e] === "*" ? n += "[^/]*" : n += t[e].replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
22190
22308
  return RegExp(`${n}$`).test(e);
22191
22309
  }
22192
- function nw(t, n) {
22310
+ function iw(t, n) {
22193
22311
  let r = i.resolve(n), a = [], o = (t) => {
22194
22312
  for (let n of e.readdirSync(t, { withFileTypes: !0 })) {
22195
22313
  let e = i.join(t, n.name);
@@ -22197,42 +22315,42 @@ function nw(t, n) {
22197
22315
  }
22198
22316
  };
22199
22317
  return o(r), a.filter((r) => t.some((t) => {
22200
- let i = ew(n, t);
22318
+ let i = nw(n, t);
22201
22319
  if (e.existsSync(i)) {
22202
22320
  let n = e.statSync(i);
22203
22321
  if (n.isFile()) return r === t;
22204
22322
  if (n.isDirectory()) return r === t || r.startsWith(`${t.replace(/\/$/, "")}/`);
22205
22323
  }
22206
- return tw(r, t);
22324
+ return rw(r, t);
22207
22325
  }));
22208
22326
  }
22209
- async function rw(t, n) {
22210
- let r = nw(t, n), i = 0;
22327
+ async function aw(t, n) {
22328
+ let r = iw(t, n), i = 0;
22211
22329
  return r.map((t) => {
22212
- let r = e.readFileSync(ew(n, t));
22213
- if (r.byteLength > $C || (i += r.byteLength) > $C) throw Error(`Stored files exceed ${$C} bytes`);
22330
+ let r = e.readFileSync(nw(n, t));
22331
+ if (r.byteLength > tw || (i += r.byteLength) > tw) throw Error(`Stored files exceed ${tw} bytes`);
22214
22332
  return {
22215
22333
  path: t,
22216
22334
  content: r.toString("base64")
22217
22335
  };
22218
22336
  });
22219
22337
  }
22220
- async function iw(t, n, r, a, o) {
22338
+ async function ow(t, n, r, a, o) {
22221
22339
  for (let s of await t.getStoredFiles(n, r)) {
22222
- if (!a.some((e) => s.path === e || s.path.startsWith(`${e.replace(/\/$/, "")}/`) || tw(s.path, e))) continue;
22223
- let t = ew(o, s.path);
22340
+ if (!a.some((e) => s.path === e || s.path.startsWith(`${e.replace(/\/$/, "")}/`) || rw(s.path, e))) continue;
22341
+ let t = nw(o, s.path);
22224
22342
  e.mkdirSync(i.dirname(t), { recursive: !0 }), e.writeFileSync(t, Buffer.from(s.content, "base64"));
22225
22343
  }
22226
22344
  }
22227
- function aw(t, n, r) {
22345
+ function sw(t, n, r) {
22228
22346
  for (let [a, o] of Object.entries(t || {})) {
22229
22347
  let t = n.getValue(o);
22230
22348
  if (!t) throw Error(`Secret '${o}' is not available for file '${a}'`);
22231
- let s = ew(r, a);
22349
+ let s = nw(r, a);
22232
22350
  e.mkdirSync(i.dirname(s), { recursive: !0 }), e.writeFileSync(s, t.encoding === "base64" ? Buffer.from(t.value, "base64") : t.value, { mode: 384 }), e.chmodSync(s, 384);
22233
22351
  }
22234
22352
  }
22235
- async function ow(t) {
22353
+ async function cw(t) {
22236
22354
  let { workerId: n, jobId: r, stepContext: i, executionContext: a, driver: o, queue: s } = t, { step: c } = i, l = c.id, u = c.name, d;
22237
22355
  try {
22238
22356
  d = o.execute(i);
@@ -22247,11 +22365,11 @@ async function ow(t) {
22247
22365
  logFilePath: ""
22248
22366
  };
22249
22367
  }
22250
- LC.add(d);
22368
+ RC.add(d);
22251
22369
  let f = !1, p = setInterval(async () => {
22252
22370
  await s.isCancelled(r) && (console.log(`[${n}] 🛑 Job #${r} was cancelled! Halting execution.`), f = !0, clearInterval(p), await d.cancel());
22253
22371
  }, 3e3), m = await d.done;
22254
- if (clearInterval(p), LC.delete(d), d.logFilePath && e.existsSync(d.logFilePath)) try {
22372
+ if (clearInterval(p), RC.delete(d), d.logFilePath && e.existsSync(d.logFilePath)) try {
22255
22373
  let e = await o.readLog(d.logFilePath);
22256
22374
  await s.saveStepLog(r, l, e);
22257
22375
  } catch (e) {
@@ -22278,7 +22396,7 @@ async function ow(t) {
22278
22396
  }
22279
22397
  };
22280
22398
  }
22281
- function sw(e, t, n) {
22399
+ function lw(e, t, n) {
22282
22400
  for (let r = t; r < e.length; r++) {
22283
22401
  let t = e[r], i = t.id || `step-${r}`;
22284
22402
  n[r] = {
@@ -22292,7 +22410,7 @@ function sw(e, t, n) {
22292
22410
  };
22293
22411
  }
22294
22412
  }
22295
- function cw(e, t, n, r, i, a, o) {
22413
+ function uw(e, t, n, r, i, a, o) {
22296
22414
  return {
22297
22415
  jobId: String(e.id),
22298
22416
  parentId: String(e.parentId || ""),
@@ -22313,7 +22431,7 @@ function cw(e, t, n, r, i, a, o) {
22313
22431
  }
22314
22432
  //#endregion
22315
22433
  //#region src/scheduler.ts
22316
- function lw(e, t, n, r) {
22434
+ function dw(e, t, n, r) {
22317
22435
  return e.split(",").some((e) => {
22318
22436
  let [i, a] = e.split("/"), o = a ? Number(a) : 1;
22319
22437
  if (!Number.isInteger(o) || o < 1) return !1;
@@ -22321,7 +22439,7 @@ function lw(e, t, n, r) {
22321
22439
  return Number.isInteger(l) && Number.isInteger(u) && t >= l && t <= u && (t - l) % o === 0;
22322
22440
  });
22323
22441
  }
22324
- function uw(e, t, n = "UTC") {
22442
+ function fw(e, t, n = "UTC") {
22325
22443
  let r = e.trim().split(/\s+/);
22326
22444
  if (r.length !== 5) return !1;
22327
22445
  let i = new Intl.DateTimeFormat("en-US", {
@@ -22343,16 +22461,16 @@ function uw(e, t, n = "UTC") {
22343
22461
  "Thu",
22344
22462
  "Fri",
22345
22463
  "Sat"
22346
- ].indexOf(i.weekday), o = lw(r[2], Number(i.day), 1, 31), s = lw(r[4].replace(/7/g, "0"), a, 0, 6);
22347
- return lw(r[0], Number(i.minute), 0, 59) && lw(r[1], Number(i.hour), 0, 23) && lw(r[3], Number(i.month), 1, 12) && (r[2] === "*" || r[4] === "*" ? o && s : o || s);
22464
+ ].indexOf(i.weekday), o = dw(r[2], Number(i.day), 1, 31), s = dw(r[4].replace(/7/g, "0"), a, 0, 6);
22465
+ return dw(r[0], Number(i.minute), 0, 59) && dw(r[1], Number(i.hour), 0, 23) && dw(r[3], Number(i.month), 1, 12) && (r[2] === "*" || r[4] === "*" ? o && s : o || s);
22348
22466
  }
22349
- function dw(e) {
22467
+ function pw(e) {
22350
22468
  if (!e) return 0;
22351
22469
  let t = e.match(/^([+-]?)(\d+)(m|h)$/);
22352
22470
  if (!t) throw Error(`Invalid solar offset: ${e}`);
22353
22471
  return (t[1] === "-" ? -1 : 1) * Number(t[2]) * (t[3] === "h" ? 36e5 : 6e4);
22354
22472
  }
22355
- function fw(e, t) {
22473
+ function mw(e, t) {
22356
22474
  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;
22357
22475
  l = (l + 360) % 360;
22358
22476
  let u = Math.atan(.91764 * Math.tan(l * Math.PI / 180)) * 180 / Math.PI;
@@ -22360,9 +22478,9 @@ function fw(e, t) {
22360
22478
  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));
22361
22479
  if (p > 1 || p < -1) return null;
22362
22480
  let m = (t.event === "sunrise" ? 360 - Math.acos(p) * 180 / Math.PI : Math.acos(p) * 180 / Math.PI) / 15;
22363
- return m = (m + u - .06571 * s - 6.622 - o + 24) % 24, new Date(i + m * 36e5 + dw(t.offset));
22481
+ return m = (m + u - .06571 * s - 6.622 - o + 24) % 24, new Date(i + m * 36e5 + pw(t.offset));
22364
22482
  }
22365
- var pw = class {
22483
+ var hw = class {
22366
22484
  queue;
22367
22485
  workflows;
22368
22486
  config;
@@ -22379,9 +22497,9 @@ var pw = class {
22379
22497
  async tick(e = /* @__PURE__ */ new Date()) {
22380
22498
  let t = /* @__PURE__ */ new Date(Math.floor(e.getTime() / 6e4) * 6e4);
22381
22499
  for (let { definition: e, revision: n } of await this.workflows.published()) {
22382
- for (let [r, i] of (e.schedule || []).entries()) uw(i.cron, t, i.timezone || "UTC") && await this.enqueue(e, n, i, `cron-${r}`, t);
22500
+ for (let [r, i] of (e.schedule || []).entries()) fw(i.cron, t, i.timezone || "UTC") && await this.enqueue(e, n, i, `cron-${r}`, t);
22383
22501
  for (let [r, i] of (e.solar || []).entries()) {
22384
- let a = fw(t, i);
22502
+ let a = mw(t, i);
22385
22503
  a && Math.floor(a.getTime() / 6e4) === t.getTime() / 6e4 && await this.enqueue(e, n, i, `solar-${r}`, t);
22386
22504
  }
22387
22505
  }
@@ -22407,7 +22525,7 @@ var pw = class {
22407
22525
  };
22408
22526
  //#endregion
22409
22527
  //#region src/logger.ts
22410
- function mw() {
22528
+ function gw() {
22411
22529
  for (let e of [
22412
22530
  "log",
22413
22531
  "info",
@@ -22422,8 +22540,8 @@ function mw() {
22422
22540
  }
22423
22541
  //#endregion
22424
22542
  //#region src/index.ts
22425
- async function hw() {
22426
- mw();
22543
+ async function _w() {
22544
+ gw();
22427
22545
  let { config: e, command: t } = await ge();
22428
22546
  e || process.exit(1);
22429
22547
  let n = new Se(), r = new xe(process.env.WORKER_NAME || "cli");
@@ -22438,13 +22556,13 @@ async function hw() {
22438
22556
  });
22439
22557
  break;
22440
22558
  case "start-workers":
22441
- console.log(`⚙️ Starting worker scheduler with ${e.workers} concurrent slot(s)...`), await r.init(), VC(e.workers, r, n, e);
22559
+ console.log(`⚙️ Starting worker scheduler with ${e.workers} concurrent slot(s)...`), await r.init(), HC(e.workers, r, n, e);
22442
22560
  break;
22443
22561
  case "start-scheduler": {
22444
22562
  console.log("Starting workflow scheduler..."), await r.init();
22445
22563
  let t = new SC();
22446
22564
  await t.init();
22447
- let n = new pw(r, t, e);
22565
+ let n = new hw(r, t, e);
22448
22566
  n.start();
22449
22567
  let i = () => {
22450
22568
  n.stop(), process.exit(0);
@@ -22455,6 +22573,6 @@ async function hw() {
22455
22573
  default: console.error(`❌ Unknown command: '${t}'`), he(), process.exit(1);
22456
22574
  }
22457
22575
  }
22458
- hw().catch(console.error);
22576
+ _w().catch(console.error);
22459
22577
  //#endregion
22460
22578
  export { MC as GitHubStatusPlugin, FC as createWorkflowPlugin, PC as registerWorkflowPlugin };
package/dist/queue.d.ts CHANGED
@@ -54,6 +54,14 @@ export declare class QueueManager {
54
54
  path: string;
55
55
  content: string;
56
56
  }>>;
57
+ updateWorkerPresence(worker: {
58
+ id: string;
59
+ version: string;
60
+ tags: string[];
61
+ concurrency: number;
62
+ activeJobs: number;
63
+ }): Promise<void>;
64
+ listWorkerPresence(): Promise<any[]>;
57
65
  saveAiRequest(jobId: string | number, workflowUrl: string, request: unknown): Promise<void>;
58
66
  }
59
67
  //# sourceMappingURL=queue.d.ts.map
@@ -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;AAIvF,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;gBAE7B,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,EAAE,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAiCnF;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrD,cAAc;IAMd,YAAY;IAgDlB;;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,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAkCrH;;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;IAUnE,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAW7H,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAK/G,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAGlG"}
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;AAIvF,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;gBAE7B,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,EAAE,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAiCnF;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrD,cAAc;IAMd,YAAY;IAyDlB;;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,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAkCrH;;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;IAUnE,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAW7H,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAK/G,oBAAoB,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrI,kBAAkB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAapC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAGlG"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAc,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAOxF,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,IAAI,CAAiB;IAC7B,OAAO,CAAC,OAAO,CAA0B;IACzC,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;IAazC,oBAAoB,CAAC,YAAY,EAAE,mBAAmB;YAIxC,aAAa;IAoP3B;;OAEG;YACW,aAAa;YA0Bb,cAAc;YASd,aAAa;YAiBb,iBAAiB;YA0BjB,WAAW;YAwBX,UAAU;YAyBV,cAAc;IA8C5B,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,QAAQ;YAIF,QAAQ;YAQR,YAAY;IAO1B,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,YAAY;YAUN,QAAQ;YAYR,wBAAwB;YAcxB,kBAAkB;YAOlB,iBAAiB;YAcjB,kBAAkB;YAoBlB,oBAAoB;YASpB,qBAAqB;YAWrB,gBAAgB;YAMhB,gBAAgB;YAiBhB,kBAAkB;YASlB,gBAAgB;IAc9B;;OAEG;YACW,kBAAkB;YAclB,iBAAiB;IA2B/B,OAAO,CAAC,mBAAmB;YASb,mBAAmB;YAWnB,qBAAqB;IAWnC;;OAEG;YACW,eAAe;IAK7B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,mBAAmB;YAcb,mBAAmB;IAwBjC;;OAEG;YACW,gBAAgB;YA+BhB,gBAAgB;YAiBhB,sBAAsB;YAetB,YAAY;YAsDZ,oBAAoB;YA4BpB,eAAe;YAkBf,cAAc;IAS5B,OAAO,CAAC,MAAM;YAMA,UAAU;IAIlB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAU5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAc,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAOxF,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,IAAI,CAAiB;IAC7B,OAAO,CAAC,OAAO,CAA0B;IACzC,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;IAazC,oBAAoB,CAAC,YAAY,EAAE,mBAAmB;YAIxC,aAAa;IAkQ3B;;OAEG;YACW,aAAa;YA0Bb,cAAc;YASd,aAAa;YAiBb,iBAAiB;YA0BjB,WAAW;YAwBX,UAAU;YAyBV,cAAc;IA8C5B,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,QAAQ;YAIF,QAAQ;YAQR,YAAY;IAO1B,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,YAAY;YAUN,QAAQ;YAYR,wBAAwB;YAcxB,kBAAkB;YAOlB,iBAAiB;YAcjB,kBAAkB;YAoBlB,oBAAoB;YASpB,qBAAqB;YAWrB,gBAAgB;YAMhB,gBAAgB;YAiBhB,kBAAkB;YASlB,gBAAgB;IAc9B;;OAEG;YACW,kBAAkB;YAclB,iBAAiB;IA2B/B,OAAO,CAAC,mBAAmB;YASb,mBAAmB;YAWnB,qBAAqB;IAWnC;;OAEG;YACW,eAAe;IAK7B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,mBAAmB;YAcb,mBAAmB;IAwBjC;;OAEG;YACW,gBAAgB;YA+BhB,gBAAgB;YAiBhB,sBAAsB;YAetB,YAAY;YAsDZ,oBAAoB;YA4BpB,eAAe;YAkBf,cAAc;IAS5B,OAAO,CAAC,MAAM;YAMA,UAAU;IAIlB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAU5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
@@ -1,2 +1,2 @@
1
- export declare function generateSettingsHtml(page?: 'tokens' | 'notifications'): string;
1
+ export declare function generateSettingsHtml(page?: 'tokens' | 'notifications' | 'workers'): string;
2
2
  //# sourceMappingURL=settings-ui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings-ui.d.ts","sourceRoot":"","sources":["../src/settings-ui.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,QAAQ,GAAG,eAA0B,GAAG,MAAM,CAExF"}
1
+ {"version":3,"file":"settings-ui.d.ts","sourceRoot":"","sources":["../src/settings-ui.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,QAAQ,GAAG,eAAe,GAAG,SAAoB,GAAG,MAAM,CAEpG"}
@@ -0,0 +1,2 @@
1
+ export declare const RUNNER_VERSION: string;
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,QAAsB,CAAC"}
@@ -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,EAKZ,MAAM,YAAY,CAAC;AASpB,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,iBA0ErB;AAmGD;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,WAAW,iBAyH9C"}
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,EAKZ,MAAM,YAAY,CAAC;AAUpB,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,iBA8ErB;AAqHD;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,WAAW,iBAmI9C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud-cli/on",
3
- "version": "1.57.0",
3
+ "version": "1.59.0",
4
4
  "description": "CLI entry point for the on plugin ecosystem.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@12.3.4",