@venturewild/workspace 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@venturewild/workspace",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Claude Code Web — Replit/Lovable-style chat-first browser UI that wraps the AI agent already installed on your machine.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -89,9 +89,17 @@ import { nanoid } from 'nanoid';
89
89
  const __filename = url.fileURLToPath(import.meta.url);
90
90
  const __dirname = path.dirname(__filename);
91
91
 
92
- // How often an open /ws/activity session re-touches presence so peers keep seeing a
93
- // fresh "online" signal (must be comfortably under workspace-presence's window).
94
- const PRESENCE_HEARTBEAT_MS = 45 * 1000;
92
+ // Presence tuning knobs sensible defaults, env-overridable so they can be tuned from
93
+ // field feel without a code change (these are UX-feel, not benched). The heartbeat is how
94
+ // often an open /ws/activity session re-touches presence so peers keep seeing a fresh
95
+ // "online" signal; the window is how long a signal counts as "active now". Heartbeat must
96
+ // stay comfortably under the window — clamped to ≤ window/2 so a misconfig can't make
97
+ // everyone blink offline.
98
+ const PRESENCE_WINDOW_MS = Math.max(10_000, Number(process.env.WILD_WORKSPACE_PRESENCE_WINDOW_MS) || 2 * 60 * 1000);
99
+ const PRESENCE_HEARTBEAT_MS = Math.min(
100
+ Math.max(5_000, Number(process.env.WILD_WORKSPACE_PRESENCE_HEARTBEAT_MS) || 45 * 1000),
101
+ Math.floor(PRESENCE_WINDOW_MS / 2),
102
+ );
95
103
 
96
104
  // --- structured logging ---------------------------------------------------
97
105
  // Single helper used everywhere so log lines are uniformly tagged + timestamped.
@@ -175,7 +183,7 @@ export async function createServer(overrides = {}) {
175
183
  // email — the sync_credential bridge). Powers the lit/dim roster avatars. Honest:
176
184
  // only marks a member online on a real recent signal; otherwise dim.
177
185
  const workspacePresence =
178
- overrides.workspacePresence || createWorkspacePresence({ activityBus });
186
+ overrides.workspacePresence || createWorkspacePresence({ activityBus, windowMs: PRESENCE_WINDOW_MS });
179
187
  // Persist the revocation list so a revoked share token stays revoked across a
180
188
  // server restart (concern C8). Lives in the gitignored .wild-workspace dir.
181
189
  const tokenRegistry = new TokenRegistry({
@@ -2586,9 +2594,11 @@ export async function createServer(overrides = {}) {
2586
2594
  });
2587
2595
  return c.json(res);
2588
2596
  });
2589
- // Report a pool theme to the ops inbox (the GLM day-one must-have). Routes to the
2590
- // rails (bmo-sync /api/listings/report). chatWrite-gated. Degrade-never: with no
2591
- // rails / logged out it's a quiet no-op the UI treats as "thanks, noted".
2597
+ // Report a pool listing to the ops inbox (the GLM day-one must-have). Despite the
2598
+ // `/themes/` path (kept for back-compat), this is KIND-AGNOSTIC `listingsRails.report`
2599
+ // reports any listing id, so it's also the takedown lever for a cross-user RECIPE whose
2600
+ // intent a scan can't judge. Routes to the rails (bmo-sync /api/listings/report).
2601
+ // chatWrite-gated. Degrade-never: with no rails / logged out it's a quiet no-op.
2592
2602
  app.post('/api/bazaar/themes/:id/report', async (c) => {
2593
2603
  const forbidden = require(c, 'chatWrite');
2594
2604
  if (forbidden) return forbidden;