@cloud-cli/on 1.58.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;
@@ -21951,14 +22057,14 @@ async function JC(e) {
21951
22057
  durationMs: 0,
21952
22058
  outputs: {},
21953
22059
  logContent: ""
21954
- })), b = cw(n, "running", p, f, _.env, y, s);
21955
- 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);
21956
22062
  try {
21957
- Object.assign(_.env, await QC(l.env, _)), Object.assign(_.env, {
22063
+ Object.assign(_.env, await ew(l.env, _)), Object.assign(_.env, {
21958
22064
  CI: "true",
21959
22065
  CI_JOB_ID: String(n.id),
21960
22066
  CI_JOB_NAME: l.name
21961
- }), 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);
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);
21962
22068
  } catch (e) {
21963
22069
  b.status = "failed", b.finishedAt = (/* @__PURE__ */ new Date()).toISOString(), b.durationMs = Date.now() - p;
21964
22070
  let r = {
@@ -21973,7 +22079,7 @@ async function JC(e) {
21973
22079
  }
21974
22080
  let x = [...r.plugins];
21975
22081
  for (let e of l.plugins || []) try {
21976
- let t = await QC(e.secrets, _);
22082
+ let t = await ew(e.secrets, _);
21977
22083
  x.push(FC({
21978
22084
  ...e,
21979
22085
  secrets: t
@@ -21988,24 +22094,24 @@ async function JC(e) {
21988
22094
  runUrl: new URL(`/runs/${n.id}`, r.serverUrl).toString()
21989
22095
  };
21990
22096
  await S.triggerWorkflowStart(ee);
21991
- let { cancelled: te, failed: ne } = await YC({
22097
+ let { cancelled: te, failed: ne } = await ZC({
21992
22098
  payload: s,
21993
22099
  steps: d,
21994
22100
  executionContext: _,
21995
22101
  ...u
21996
22102
  }, b), re = te ? "cancelled" : ne ? "failed" : "success";
21997
22103
  if (re === "success") try {
21998
- let e = l.artifacts ? await rw(l.artifacts.paths, g) : [];
22104
+ let e = l.artifacts ? await aw(l.artifacts.paths, g) : [];
21999
22105
  if (e.length && (await o.saveStoredFiles("artifact", String(n.id), e), b.artifacts = e.map((e) => e.path)), v && l.cache) {
22000
- let e = await rw(l.cache.paths, g);
22106
+ let e = await aw(l.cache.paths, g);
22001
22107
  e.length && await o.saveStoredFiles("cache", `${n.workflow_id}:${v}`, e);
22002
22108
  }
22003
22109
  } catch (e) {
22004
22110
  console.error(`[${t}] ⚠️ Failed to store workflow files:`, e), re = "failed";
22005
22111
  }
22006
- 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);
22007
22113
  }
22008
- async function YC(e, t) {
22114
+ async function ZC(e, t) {
22009
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;
22010
22116
  try {
22011
22117
  for (let s = 0; s < c.length; s++) {
@@ -22020,14 +22126,14 @@ async function YC(e, t) {
22020
22126
  logContent: "",
22021
22127
  startedAt: h,
22022
22128
  finishedAt: void 0
22023
- }, 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);
22024
22130
  let g = {
22025
22131
  failed: !0,
22026
22132
  skipped: !1,
22027
22133
  cancelled: !1,
22028
22134
  report: null
22029
22135
  }, _ = e.workflow?.retries ?? 0;
22030
- for (let e = 1; e <= _ + 1 && (g = await XC({
22136
+ for (let e = 1; e <= _ + 1 && (g = await QC({
22031
22137
  workerId: r,
22032
22138
  jobId: o.id,
22033
22139
  step: m,
@@ -22055,7 +22161,7 @@ async function YC(e, t) {
22055
22161
  exitCode: 1,
22056
22162
  error: "Step failed before execution started",
22057
22163
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
22058
- }, 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;
22059
22165
  if (g.cancelled) {
22060
22166
  f = !0, d = !0;
22061
22167
  break;
@@ -22068,13 +22174,13 @@ async function YC(e, t) {
22068
22174
  } catch (e) {
22069
22175
  console.log("🛑 Step failed", e), d = !0;
22070
22176
  }
22071
- 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)), {
22072
22178
  failed: d,
22073
22179
  cancelled: f,
22074
22180
  stepReports: u
22075
22181
  };
22076
22182
  }
22077
- async function XC(e) {
22183
+ async function QC(e) {
22078
22184
  let { step: t, stepIndex: n, executionContext: r } = e;
22079
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), {
22080
22186
  failed: !1,
@@ -22083,7 +22189,7 @@ async function XC(e) {
22083
22189
  report: null
22084
22190
  };
22085
22191
  try {
22086
- let i = await QC(t.env, r), a = {
22192
+ let i = await ew(t.env, r), a = {
22087
22193
  jobId: String(e.jobId),
22088
22194
  step: t,
22089
22195
  command: t.run,
@@ -22103,10 +22209,10 @@ async function XC(e) {
22103
22209
  CI_JOB_NAME: r.env.CI_JOB_NAME || t.name || t.id || `step-${n}`
22104
22210
  }
22105
22211
  };
22106
- return t.eval ? ZC({
22212
+ return t.eval ? $C({
22107
22213
  ...e,
22108
22214
  stepContext: a
22109
- }) : ow({
22215
+ }) : cw({
22110
22216
  ...e,
22111
22217
  stepContext: a
22112
22218
  });
@@ -22129,7 +22235,7 @@ async function XC(e) {
22129
22235
  };
22130
22236
  }
22131
22237
  }
22132
- async function ZC(e) {
22238
+ async function $C(e) {
22133
22239
  let { queue: t, stepContext: n, executionContext: r } = e, { jobId: i, step: a } = n, o = Date.now(), s = a.id, c = a.name, l;
22134
22240
  try {
22135
22241
  let e = new Promise((e, t) => {
@@ -22179,7 +22285,7 @@ async function ZC(e) {
22179
22285
  l && clearTimeout(l);
22180
22286
  }
22181
22287
  }
22182
- async function QC(e, t) {
22288
+ async function ew(e, t) {
22183
22289
  let n = {};
22184
22290
  if (e) for (let [r, i] of Object.entries(e)) n[r] = String(await mr.evaluateValue(i, {
22185
22291
  ...t,
@@ -22190,18 +22296,18 @@ async function QC(e, t) {
22190
22296
  }));
22191
22297
  return n;
22192
22298
  }
22193
- var $C = 52428800;
22194
- function ew(e, t) {
22299
+ var tw = 52428800;
22300
+ function nw(e, t) {
22195
22301
  let n = i.resolve(e), r = i.resolve(n, t);
22196
22302
  if (r !== n && !r.startsWith(`${n}${i.sep}`)) throw Error(`Stored file path escapes workspace: ${t}`);
22197
22303
  return r;
22198
22304
  }
22199
- function tw(e, t) {
22305
+ function rw(e, t) {
22200
22306
  let n = "^";
22201
22307
  for (let e = 0; e < t.length; e++) t[e] === "*" && t[e + 1] === "*" ? (n += ".*", e++) : t[e] === "*" ? n += "[^/]*" : n += t[e].replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
22202
22308
  return RegExp(`${n}$`).test(e);
22203
22309
  }
22204
- function nw(t, n) {
22310
+ function iw(t, n) {
22205
22311
  let r = i.resolve(n), a = [], o = (t) => {
22206
22312
  for (let n of e.readdirSync(t, { withFileTypes: !0 })) {
22207
22313
  let e = i.join(t, n.name);
@@ -22209,42 +22315,42 @@ function nw(t, n) {
22209
22315
  }
22210
22316
  };
22211
22317
  return o(r), a.filter((r) => t.some((t) => {
22212
- let i = ew(n, t);
22318
+ let i = nw(n, t);
22213
22319
  if (e.existsSync(i)) {
22214
22320
  let n = e.statSync(i);
22215
22321
  if (n.isFile()) return r === t;
22216
22322
  if (n.isDirectory()) return r === t || r.startsWith(`${t.replace(/\/$/, "")}/`);
22217
22323
  }
22218
- return tw(r, t);
22324
+ return rw(r, t);
22219
22325
  }));
22220
22326
  }
22221
- async function rw(t, n) {
22222
- let r = nw(t, n), i = 0;
22327
+ async function aw(t, n) {
22328
+ let r = iw(t, n), i = 0;
22223
22329
  return r.map((t) => {
22224
- let r = e.readFileSync(ew(n, t));
22225
- 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`);
22226
22332
  return {
22227
22333
  path: t,
22228
22334
  content: r.toString("base64")
22229
22335
  };
22230
22336
  });
22231
22337
  }
22232
- async function iw(t, n, r, a, o) {
22338
+ async function ow(t, n, r, a, o) {
22233
22339
  for (let s of await t.getStoredFiles(n, r)) {
22234
- if (!a.some((e) => s.path === e || s.path.startsWith(`${e.replace(/\/$/, "")}/`) || tw(s.path, e))) continue;
22235
- 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);
22236
22342
  e.mkdirSync(i.dirname(t), { recursive: !0 }), e.writeFileSync(t, Buffer.from(s.content, "base64"));
22237
22343
  }
22238
22344
  }
22239
- function aw(t, n, r) {
22345
+ function sw(t, n, r) {
22240
22346
  for (let [a, o] of Object.entries(t || {})) {
22241
22347
  let t = n.getValue(o);
22242
22348
  if (!t) throw Error(`Secret '${o}' is not available for file '${a}'`);
22243
- let s = ew(r, a);
22349
+ let s = nw(r, a);
22244
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);
22245
22351
  }
22246
22352
  }
22247
- async function ow(t) {
22353
+ async function cw(t) {
22248
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;
22249
22355
  try {
22250
22356
  d = o.execute(i);
@@ -22259,11 +22365,11 @@ async function ow(t) {
22259
22365
  logFilePath: ""
22260
22366
  };
22261
22367
  }
22262
- LC.add(d);
22368
+ RC.add(d);
22263
22369
  let f = !1, p = setInterval(async () => {
22264
22370
  await s.isCancelled(r) && (console.log(`[${n}] 🛑 Job #${r} was cancelled! Halting execution.`), f = !0, clearInterval(p), await d.cancel());
22265
22371
  }, 3e3), m = await d.done;
22266
- 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 {
22267
22373
  let e = await o.readLog(d.logFilePath);
22268
22374
  await s.saveStepLog(r, l, e);
22269
22375
  } catch (e) {
@@ -22290,7 +22396,7 @@ async function ow(t) {
22290
22396
  }
22291
22397
  };
22292
22398
  }
22293
- function sw(e, t, n) {
22399
+ function lw(e, t, n) {
22294
22400
  for (let r = t; r < e.length; r++) {
22295
22401
  let t = e[r], i = t.id || `step-${r}`;
22296
22402
  n[r] = {
@@ -22304,7 +22410,7 @@ function sw(e, t, n) {
22304
22410
  };
22305
22411
  }
22306
22412
  }
22307
- function cw(e, t, n, r, i, a, o) {
22413
+ function uw(e, t, n, r, i, a, o) {
22308
22414
  return {
22309
22415
  jobId: String(e.id),
22310
22416
  parentId: String(e.parentId || ""),
@@ -22325,7 +22431,7 @@ function cw(e, t, n, r, i, a, o) {
22325
22431
  }
22326
22432
  //#endregion
22327
22433
  //#region src/scheduler.ts
22328
- function lw(e, t, n, r) {
22434
+ function dw(e, t, n, r) {
22329
22435
  return e.split(",").some((e) => {
22330
22436
  let [i, a] = e.split("/"), o = a ? Number(a) : 1;
22331
22437
  if (!Number.isInteger(o) || o < 1) return !1;
@@ -22333,7 +22439,7 @@ function lw(e, t, n, r) {
22333
22439
  return Number.isInteger(l) && Number.isInteger(u) && t >= l && t <= u && (t - l) % o === 0;
22334
22440
  });
22335
22441
  }
22336
- function uw(e, t, n = "UTC") {
22442
+ function fw(e, t, n = "UTC") {
22337
22443
  let r = e.trim().split(/\s+/);
22338
22444
  if (r.length !== 5) return !1;
22339
22445
  let i = new Intl.DateTimeFormat("en-US", {
@@ -22355,16 +22461,16 @@ function uw(e, t, n = "UTC") {
22355
22461
  "Thu",
22356
22462
  "Fri",
22357
22463
  "Sat"
22358
- ].indexOf(i.weekday), o = lw(r[2], Number(i.day), 1, 31), s = lw(r[4].replace(/7/g, "0"), a, 0, 6);
22359
- 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);
22360
22466
  }
22361
- function dw(e) {
22467
+ function pw(e) {
22362
22468
  if (!e) return 0;
22363
22469
  let t = e.match(/^([+-]?)(\d+)(m|h)$/);
22364
22470
  if (!t) throw Error(`Invalid solar offset: ${e}`);
22365
22471
  return (t[1] === "-" ? -1 : 1) * Number(t[2]) * (t[3] === "h" ? 36e5 : 6e4);
22366
22472
  }
22367
- function fw(e, t) {
22473
+ function mw(e, t) {
22368
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;
22369
22475
  l = (l + 360) % 360;
22370
22476
  let u = Math.atan(.91764 * Math.tan(l * Math.PI / 180)) * 180 / Math.PI;
@@ -22372,9 +22478,9 @@ function fw(e, t) {
22372
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));
22373
22479
  if (p > 1 || p < -1) return null;
22374
22480
  let m = (t.event === "sunrise" ? 360 - Math.acos(p) * 180 / Math.PI : Math.acos(p) * 180 / Math.PI) / 15;
22375
- 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));
22376
22482
  }
22377
- var pw = class {
22483
+ var hw = class {
22378
22484
  queue;
22379
22485
  workflows;
22380
22486
  config;
@@ -22391,9 +22497,9 @@ var pw = class {
22391
22497
  async tick(e = /* @__PURE__ */ new Date()) {
22392
22498
  let t = /* @__PURE__ */ new Date(Math.floor(e.getTime() / 6e4) * 6e4);
22393
22499
  for (let { definition: e, revision: n } of await this.workflows.published()) {
22394
- 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);
22395
22501
  for (let [r, i] of (e.solar || []).entries()) {
22396
- let a = fw(t, i);
22502
+ let a = mw(t, i);
22397
22503
  a && Math.floor(a.getTime() / 6e4) === t.getTime() / 6e4 && await this.enqueue(e, n, i, `solar-${r}`, t);
22398
22504
  }
22399
22505
  }
@@ -22419,7 +22525,7 @@ var pw = class {
22419
22525
  };
22420
22526
  //#endregion
22421
22527
  //#region src/logger.ts
22422
- function mw() {
22528
+ function gw() {
22423
22529
  for (let e of [
22424
22530
  "log",
22425
22531
  "info",
@@ -22434,8 +22540,8 @@ function mw() {
22434
22540
  }
22435
22541
  //#endregion
22436
22542
  //#region src/index.ts
22437
- async function hw() {
22438
- mw();
22543
+ async function _w() {
22544
+ gw();
22439
22545
  let { config: e, command: t } = await ge();
22440
22546
  e || process.exit(1);
22441
22547
  let n = new Se(), r = new xe(process.env.WORKER_NAME || "cli");
@@ -22450,13 +22556,13 @@ async function hw() {
22450
22556
  });
22451
22557
  break;
22452
22558
  case "start-workers":
22453
- 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);
22454
22560
  break;
22455
22561
  case "start-scheduler": {
22456
22562
  console.log("Starting workflow scheduler..."), await r.init();
22457
22563
  let t = new SC();
22458
22564
  await t.init();
22459
- let n = new pw(r, t, e);
22565
+ let n = new hw(r, t, e);
22460
22566
  n.start();
22461
22567
  let i = () => {
22462
22568
  n.stop(), process.exit(0);
@@ -22467,6 +22573,6 @@ async function hw() {
22467
22573
  default: console.error(`❌ Unknown command: '${t}'`), he(), process.exit(1);
22468
22574
  }
22469
22575
  }
22470
- hw().catch(console.error);
22576
+ _w().catch(console.error);
22471
22577
  //#endregion
22472
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,iBAmI9C"}
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.58.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",