@atolis-hq/wake 0.2.48 → 0.2.49

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.
@@ -38,6 +38,10 @@ export const indexHtml = `<!DOCTYPE html>
38
38
  .statusbar button { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.18); color: #fff; border-radius: 6px; padding: 0.22rem 0.55rem; cursor: pointer; font-size: 0.78rem; }
39
39
  .statusbar button:hover:not(:disabled) { border-color: var(--accent-light); background: rgba(45, 212, 191, 0.16); }
40
40
  .statusbar button:disabled { cursor: wait; opacity: 0.62; }
41
+ .statusbar .pause-control { background: #5c1f1a; border-color: #ff8f7f; font-weight: 700; }
42
+ .statusbar .pause-control:hover:not(:disabled) { background: #733027; border-color: #ffd0c8; }
43
+ .statusbar .pause-control.is-paused { background: #1f4b34; border-color: #7fe3a3; }
44
+ .statusbar .pause-control.is-paused:hover:not(:disabled) { background: #276340; border-color: #c3f3d2; }
41
45
  .pill { padding: 0.15rem 0.5rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; }
42
46
  .pill-idle { background: #1f3d2c; color: #7fe3a3; }
43
47
  .pill-polling { background: #1f3350; color: #7fb3ff; }
@@ -121,6 +125,7 @@ export const indexHtml = `<!DOCTYPE html>
121
125
  </header>
122
126
  <div class="statusbar">
123
127
  <span id="loop-pill" class="pill">…</span>
128
+ <button id="pause-toggle" type="button" class="pause-control">Pause</button>
124
129
  <button id="force-tick" type="button">Tick now</button>
125
130
  <span id="status-summary" class="meta"></span>
126
131
  </div>
@@ -184,6 +189,12 @@ async function postJson(path) {
184
189
  return res.json();
185
190
  }
186
191
 
192
+ async function deleteJson(path) {
193
+ const res = await fetch(API + path, { method: 'DELETE' });
194
+ if (!res.ok) throw new Error(path + ' -> ' + res.status);
195
+ return res.json();
196
+ }
197
+
187
198
  function fmtMs(ms) {
188
199
  if (ms === undefined || ms === null) return '—';
189
200
  const s = Math.floor(ms / 1000);
@@ -220,6 +231,10 @@ async function renderStatusBar() {
220
231
  const pill = document.getElementById('loop-pill');
221
232
  pill.textContent = status.loopState;
222
233
  pill.className = 'pill pill-' + status.loopState;
234
+ const pauseButton = document.getElementById('pause-toggle');
235
+ pauseButton.dataset.paused = String(status.paused);
236
+ pauseButton.textContent = status.paused ? 'Resume' : 'Pause';
237
+ pauseButton.classList.toggle('is-paused', status.paused);
223
238
  const freshness = status.sourceFreshness.level;
224
239
  const summary = document.getElementById('status-summary');
225
240
  summary.textContent =
@@ -232,6 +247,23 @@ async function renderStatusBar() {
232
247
  }
233
248
  }
234
249
 
250
+ async function togglePause() {
251
+ const button = document.getElementById('pause-toggle');
252
+ const paused = button.dataset.paused === 'true';
253
+ button.disabled = true;
254
+ button.textContent = paused ? 'Resuming...' : 'Pausing...';
255
+ try {
256
+ if (paused) await deleteJson('/pause');
257
+ else await postJson('/pause');
258
+ await renderStatusBar();
259
+ switchView(currentView, { showLoading: false });
260
+ } catch (err) {
261
+ document.getElementById('status-summary').textContent = 'pause toggle failed: ' + err.message;
262
+ } finally {
263
+ button.disabled = false;
264
+ }
265
+ }
266
+
235
267
  async function forceTickNow() {
236
268
  const button = document.getElementById('force-tick');
237
269
  button.disabled = true;
@@ -842,6 +874,7 @@ document.getElementById('modal-overlay').addEventListener('click', (event) => {
842
874
  }
843
875
  });
844
876
  document.getElementById('force-tick').addEventListener('click', forceTickNow);
877
+ document.getElementById('pause-toggle').addEventListener('click', togglePause);
845
878
 
846
879
  renderStatusBar();
847
880
  switchView('board');
@@ -1,5 +1,7 @@
1
1
  import { createServer } from 'node:http';
2
2
  import { randomUUID } from 'node:crypto';
3
+ import { mkdir, rm, writeFile } from 'node:fs/promises';
4
+ import { dirname } from 'node:path';
3
5
  import { createProjectionUpdater } from '../../core/projection-updater.js';
4
6
  import { configuredTicketSource } from '../../domain/sources.js';
5
7
  import { createEventEnvelope } from '../../lib/event-log.js';
@@ -155,6 +157,17 @@ async function handleRequest(req, res, options, now, projectionUpdater) {
155
157
  sendJson(res, 202, request);
156
158
  return;
157
159
  }
160
+ if (req.method === 'POST' && resource === 'pause' && segments.length === 1) {
161
+ await mkdir(dirname(stateStore.paths.pauseFile), { recursive: true });
162
+ await writeFile(stateStore.paths.pauseFile, `${now().toISOString()}\n`, 'utf8');
163
+ sendJson(res, 200, { paused: true });
164
+ return;
165
+ }
166
+ if (req.method === 'DELETE' && resource === 'pause' && segments.length === 1) {
167
+ await rm(stateStore.paths.pauseFile, { force: true });
168
+ sendJson(res, 200, { paused: false });
169
+ return;
170
+ }
158
171
  if (req.method === 'POST' &&
159
172
  resource === 'runners' &&
160
173
  segments.length === 3 &&
@@ -124,4 +124,4 @@ export function resolveWakeVersion(options = {}) {
124
124
  }
125
125
  return '0.1.0-dev';
126
126
  }
127
- export const wakeVersion = "g40a6bf0";
127
+ export const wakeVersion = "g1785fe4";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.2.48",
3
+ "version": "0.2.49",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {