@xmarts/genius-setup 1.7.0 → 1.7.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/hooks/genius_inject.py +31 -7
- package/package.json +1 -1
package/hooks/genius_inject.py
CHANGED
|
@@ -24,6 +24,7 @@ CFG_PATH = os.path.join(HOME, ".genius", "config.json")
|
|
|
24
24
|
TIMEOUT = 3.5
|
|
25
25
|
SELF_UPDATE_TTL = 86400 # at most once/day
|
|
26
26
|
SELF_UPDATE_STAMP = os.path.join(HOME, ".genius", ".last_selfupdate")
|
|
27
|
+
FORCE_STAMP = os.path.join(HOME, ".genius", ".last_forced_epoch")
|
|
27
28
|
|
|
28
29
|
SESSION_PRIMER = (
|
|
29
30
|
"[Xmarts Genius — Brain connected]\n"
|
|
@@ -73,17 +74,22 @@ def _inject(cfg, prompt):
|
|
|
73
74
|
try:
|
|
74
75
|
resp = urllib.request.urlopen(req, timeout=TIMEOUT)
|
|
75
76
|
data = json.loads(resp.read())
|
|
76
|
-
result = data.get("result", data)
|
|
77
|
-
return (result
|
|
77
|
+
result = data.get("result", data) or {}
|
|
78
|
+
return (result.get("context", "") or ""), result.get("hook_force_epoch")
|
|
78
79
|
except Exception:
|
|
79
|
-
return ""
|
|
80
|
+
return "", None
|
|
80
81
|
|
|
81
82
|
|
|
82
|
-
def _maybe_self_update(cfg):
|
|
83
|
+
def _maybe_self_update(cfg, force_epoch=None):
|
|
83
84
|
"""Keep the consultant on the LATEST Genius package with ZERO action: at most
|
|
84
85
|
once/day, silently re-run the installer in the background. New hooks, MCP
|
|
85
86
|
tools, settings and the CLAUDE.md protocol then flow automatically — the
|
|
86
87
|
consultant never re-onboards. Detached + fully guarded; never blocks a turn.
|
|
88
|
+
|
|
89
|
+
force_epoch (from the server's inject response) is the admin "push now" lever:
|
|
90
|
+
when the server epoch is newer than the one we last acted on, we upgrade
|
|
91
|
+
IMMEDIATELY, bypassing the daily TTL — and record the epoch so we force at most
|
|
92
|
+
once per bump (never a loop).
|
|
87
93
|
"""
|
|
88
94
|
import time
|
|
89
95
|
import subprocess
|
|
@@ -91,7 +97,18 @@ def _maybe_self_update(cfg):
|
|
|
91
97
|
token = cfg.get("token")
|
|
92
98
|
if not token:
|
|
93
99
|
return
|
|
94
|
-
|
|
100
|
+
forced = False
|
|
101
|
+
if force_epoch:
|
|
102
|
+
try:
|
|
103
|
+
fe = int(force_epoch)
|
|
104
|
+
last = 0
|
|
105
|
+
if os.path.exists(FORCE_STAMP):
|
|
106
|
+
with open(FORCE_STAMP) as fh:
|
|
107
|
+
last = int((fh.read() or "0").strip() or 0)
|
|
108
|
+
forced = fe > last
|
|
109
|
+
except Exception:
|
|
110
|
+
forced = False
|
|
111
|
+
if not forced and os.path.exists(SELF_UPDATE_STAMP) and (
|
|
95
112
|
time.time() - os.path.getmtime(SELF_UPDATE_STAMP)) < SELF_UPDATE_TTL:
|
|
96
113
|
return
|
|
97
114
|
# Stamp FIRST so a failing/slow npx never causes a retry storm.
|
|
@@ -99,6 +116,9 @@ def _maybe_self_update(cfg):
|
|
|
99
116
|
os.makedirs(os.path.dirname(SELF_UPDATE_STAMP), exist_ok=True)
|
|
100
117
|
with open(SELF_UPDATE_STAMP, "w") as fh:
|
|
101
118
|
fh.write(str(int(time.time())))
|
|
119
|
+
if force_epoch:
|
|
120
|
+
with open(FORCE_STAMP, "w") as fh:
|
|
121
|
+
fh.write(str(int(force_epoch)))
|
|
102
122
|
except Exception:
|
|
103
123
|
return
|
|
104
124
|
env = dict(os.environ)
|
|
@@ -125,14 +145,18 @@ def main():
|
|
|
125
145
|
cfg = _cfg()
|
|
126
146
|
if not cfg.get("token"):
|
|
127
147
|
return # not configured -> silent no-op
|
|
128
|
-
_maybe_self_update(cfg) # background, daily, zero-action upgrades
|
|
129
148
|
event = _event()
|
|
130
149
|
name = event.get("hook_event_name") or (
|
|
131
150
|
"UserPromptSubmit" if event.get("prompt") else "SessionStart")
|
|
132
151
|
if name == "SessionStart":
|
|
152
|
+
_maybe_self_update(cfg) # TTL-only on priming
|
|
133
153
|
_emit("SessionStart", SESSION_PRIMER)
|
|
134
154
|
else:
|
|
135
|
-
|
|
155
|
+
context, force_epoch = _inject(cfg, event.get("prompt") or "")
|
|
156
|
+
# The inject call already round-tripped the server, so honour any
|
|
157
|
+
# admin-pushed force-update epoch here (bypasses the daily TTL).
|
|
158
|
+
_maybe_self_update(cfg, force_epoch)
|
|
159
|
+
_emit("UserPromptSubmit", context)
|
|
136
160
|
|
|
137
161
|
|
|
138
162
|
if __name__ == "__main__":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmarts/genius-setup",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
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"
|