@xmarts/genius-setup 1.5.0 → 1.7.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.
@@ -61,9 +61,13 @@ function exchangeSetupToken(setupToken, cb) {
61
61
  try { url = new URL(BASE + '/xma/genius/v1/setup/exchange'); }
62
62
  catch (e) { return cb(e); }
63
63
  const mod = url.protocol === 'http:' ? require('http') : require('https');
64
+ // device_name labels this machine in the consultant's Devices tab (each
65
+ // machine gets its OWN revocable key). Best-effort; harmless if unavailable.
66
+ let deviceName = '';
67
+ try { deviceName = os.hostname() || ''; } catch (_) { deviceName = ''; }
64
68
  const payload = JSON.stringify({
65
69
  jsonrpc: '2.0', method: 'call', id: 1,
66
- params: { setup_token: setupToken },
70
+ params: { setup_token: setupToken, device_name: deviceName },
67
71
  });
68
72
  const req = mod.request({
69
73
  hostname: url.hostname,
@@ -74,7 +78,7 @@ function exchangeSetupToken(setupToken, cb) {
74
78
  'Content-Type': 'application/json',
75
79
  'Content-Length': Buffer.byteLength(payload),
76
80
  // Cloudflare in front of beesmart.digital 403s the default Node UA.
77
- 'User-Agent': 'XmartsGenius-Setup/1.5.0',
81
+ 'User-Agent': 'XmartsGenius-Setup/1.6.0',
78
82
  },
79
83
  timeout: 15000,
80
84
  }, (res) => {
@@ -251,6 +251,28 @@ def _deadletter(path):
251
251
  pass
252
252
 
253
253
 
254
+ def _local_tz():
255
+ """(iana_name_or_'', utc_offset_minutes) for THIS machine — the authoritative
256
+ signal for dating the work to the consultant's LOCAL day (beats IP geo, which
257
+ VPNs/Cloudflare defeat). The hook runs ON the consultant's machine, so it just
258
+ reads the machine's own timezone."""
259
+ iana = ""
260
+ try:
261
+ p = os.path.realpath("/etc/localtime")
262
+ if "/zoneinfo/" in p:
263
+ iana = p.split("/zoneinfo/", 1)[1]
264
+ elif os.environ.get("TZ"):
265
+ iana = os.environ.get("TZ", "")
266
+ except Exception:
267
+ iana = ""
268
+ off = None
269
+ try:
270
+ off = int(_dt.datetime.now().astimezone().utcoffset().total_seconds() // 60)
271
+ except Exception:
272
+ off = None
273
+ return iana, off
274
+
275
+
254
276
  def main():
255
277
  cfg = _load_cfg()
256
278
  endpoint = cfg.get("capture_endpoint")
@@ -272,13 +294,17 @@ def main():
272
294
  transcript = _redact(_read_transcript(tpath))
273
295
  session_ref = event.get("session_id") or event.get("session_ref") or ""
274
296
 
275
- # Off-platform / sensitive work keeps CONTENT out of the Brain entirely — only
276
- # the TIME (session metadata) is sent. Inferred from an explicit pii_safe flag
277
- # or a topic set with no Genius client (e.g. Ateneai insurance/medical work).
278
- offplatform = bool(cfg.get("pii_safe")) or (
279
- bool(cfg.get("topic")) and not cfg.get("target_client"))
280
-
281
- if transcript.strip() and not offplatform:
297
+ # CONTENT-OUT is decoupled from "off-platform". ONLY an explicit pii_safe flag
298
+ # keeps transcript content out of the Brain (e.g. Ateneai medical/insurance).
299
+ # Off-platform / no-client work STILL contributes learnings we nourish from
300
+ # ALL of a consultant's projects, not just registered clients (owner directive
301
+ # 2026-06-05, Brain #1403). Naming a tema NO LONGER suppresses content.
302
+ content_out = bool(cfg.get("pii_safe"))
303
+ # The session METADATA still carries an off-platform LABEL (no Genius client);
304
+ # the server derives the same. It does NOT gate transcript content.
305
+ is_offplatform = content_out or not cfg.get("target_client")
306
+
307
+ if transcript.strip() and not content_out:
282
308
  payload = {
283
309
  "transcript": transcript,
284
310
  "session_ref": session_ref,
@@ -295,10 +321,11 @@ def main():
295
321
  if session_endpoint and session_ref:
296
322
  metrics = _session_metrics(tpath)
297
323
  if metrics and metrics.get("active_minutes", 0) > 0:
324
+ tz_iana, tz_off = _local_tz()
298
325
  meta = {
299
326
  "session_ref": session_ref,
300
327
  "source": "transcript_hook",
301
- "is_offplatform": offplatform,
328
+ "is_offplatform": is_offplatform,
302
329
  "_endpoint": session_endpoint,
303
330
  }
304
331
  meta.update(metrics)
@@ -309,6 +336,10 @@ def main():
309
336
  meta["workspace"] = ws
310
337
  if cfg.get("topic"):
311
338
  meta["topic"] = cfg["topic"]
339
+ if tz_iana:
340
+ meta["tz_iana"] = tz_iana
341
+ if tz_off is not None:
342
+ meta["utc_offset_minutes"] = tz_off
312
343
  _spool(meta, prefix="meta")
313
344
 
314
345
  # Always attempt to flush the spool (delivers this + any backlog)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmarts/genius-setup",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "One-command, self-updating onboarding for Xmarts Genius (Brain MCP + per-turn injection + automatic session/time capture + CLAUDE.md protocol). Secret-free onboarding via single-use setup-token exchange (no Bearer in the GET-able bootstrap). Installs once; self-updates daily so new tools/skills/features arrive with zero action.",
5
5
  "bin": {
6
6
  "genius-setup": "bin/genius-setup.js"