@getrift/rift 0.1.0-beta.19 → 0.1.0-beta.20
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/dist/src/cli/commands/status.d.ts.map +1 -1
- package/dist/src/cli/commands/status.js +38 -2
- package/dist/src/cli/commands/status.js.map +1 -1
- package/dist/src/cli/commands/update.d.ts +56 -5
- package/dist/src/cli/commands/update.d.ts.map +1 -1
- package/dist/src/cli/commands/update.js +250 -21
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/http-client.d.ts +25 -1
- package/dist/src/cli/http-client.d.ts.map +1 -1
- package/dist/src/cli/http-client.js +82 -0
- package/dist/src/cli/http-client.js.map +1 -1
- package/dist/src/cli/status/friend-header.d.ts.map +1 -1
- package/dist/src/cli/status/friend-header.js +3 -0
- package/dist/src/cli/status/friend-header.js.map +1 -1
- package/dist/src/diagnostics/codex-preflight.d.ts +1 -1
- package/dist/src/diagnostics/codex-preflight.d.ts.map +1 -1
- package/dist/src/diagnostics/codex-preflight.js +12 -0
- package/dist/src/diagnostics/codex-preflight.js.map +1 -1
- package/dist/src/diagnostics/doctor.d.ts.map +1 -1
- package/dist/src/diagnostics/doctor.js +2 -0
- package/dist/src/diagnostics/doctor.js.map +1 -1
- package/dist/src/observability/tool-usage-stats.d.ts.map +1 -1
- package/dist/src/observability/tool-usage-stats.js +14 -1
- package/dist/src/observability/tool-usage-stats.js.map +1 -1
- package/dist/src/providers/codex-cli-runner.d.ts.map +1 -1
- package/dist/src/providers/codex-cli-runner.js +43 -4
- package/dist/src/providers/codex-cli-runner.js.map +1 -1
- package/operator/swiftbar/render-menu.py +61 -18
- package/operator/swiftbar/rift.10s.sh +52 -28
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ deliberately absent.
|
|
|
14
14
|
Inputs (all via env, all optional — missing inputs degrade gracefully):
|
|
15
15
|
RIFT_DOCTOR_JSON `rift doctor --json` output (the verdict + one fix).
|
|
16
16
|
RIFT_STATUS_JSON `rift status --json` output (capture times, clients).
|
|
17
|
-
RIFT_MCP_JSON `/stats/mcp-usage` body (
|
|
17
|
+
RIFT_MCP_JSON `/stats/mcp-usage` body (Memory stats: today/month/all).
|
|
18
18
|
RIFT_HEALTH "up" | "down" — coarse /health probe, used only when
|
|
19
19
|
the doctor report is unavailable (CLI not resolvable).
|
|
20
20
|
RIFT_NODE_BIN absolute node binary, for menu actions.
|
|
@@ -121,21 +121,62 @@ def fmt_tokens(n):
|
|
|
121
121
|
return f"~{n} context tokens"
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
124
|
+
# Friendly labels for the three Memory windows, mapped to their keys in the
|
|
125
|
+
# /stats/mcp-usage payload. Order is the render order. We deliberately skip
|
|
126
|
+
# `week` — three periods stay glanceable; a fourth turns the menu into a
|
|
127
|
+
# dashboard. A period absent from the payload is simply not rendered (we never
|
|
128
|
+
# fabricate a number the backend didn't report), so an older daemon that only
|
|
129
|
+
# emits `today` still renders cleanly.
|
|
130
|
+
MEMORY_PERIODS = (("Today", "today"), ("This month", "month"), ("All time", "all_time"))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def memory_window_row(label, hits, tokens):
|
|
134
|
+
"""One '<Label>: N useful recalls · ~tokens' row, or a calm zero state."""
|
|
135
|
+
if hits <= 0:
|
|
136
|
+
return f"{label}: nothing yet"
|
|
137
|
+
parts = [f"{hits:,} useful recall" + ("" if hits == 1 else "s")]
|
|
138
|
+
if isinstance(tokens, int) and tokens > 0:
|
|
137
139
|
parts.append(fmt_tokens(tokens))
|
|
138
|
-
return " · ".join(parts)
|
|
140
|
+
return f"{label}: " + " · ".join(parts)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def memory_section(mcp):
|
|
144
|
+
"""Friendly 'Memory' section lines (header + period rows), or [].
|
|
145
|
+
|
|
146
|
+
Reads today / month / all-time recall + context-token counts straight
|
|
147
|
+
from /stats/mcp-usage and prints them in plain language. Returns [] when
|
|
148
|
+
the stats payload is missing or carries none of the expected windows, so
|
|
149
|
+
the menu degrades gracefully (section omitted, Rift still healthy) rather
|
|
150
|
+
than showing an error. A history with no recalls anywhere collapses to a
|
|
151
|
+
single calm line instead of three empty rows.
|
|
152
|
+
"""
|
|
153
|
+
if not isinstance(mcp, dict):
|
|
154
|
+
return []
|
|
155
|
+
present = []
|
|
156
|
+
any_activity = False
|
|
157
|
+
for label, key in MEMORY_PERIODS:
|
|
158
|
+
window = mcp.get(key)
|
|
159
|
+
if not isinstance(window, dict):
|
|
160
|
+
continue
|
|
161
|
+
hits = window.get("context_hits")
|
|
162
|
+
if not isinstance(hits, int):
|
|
163
|
+
continue
|
|
164
|
+
tokens = window.get("context_tokens_delivered_estimate")
|
|
165
|
+
present.append((label, hits, tokens))
|
|
166
|
+
if hits > 0:
|
|
167
|
+
any_activity = True
|
|
168
|
+
if not present:
|
|
169
|
+
return []
|
|
170
|
+
# Collapse to a single calm line ONLY when every period is present and all
|
|
171
|
+
# are zero — that genuinely is "nothing recalled, ever". A partial payload
|
|
172
|
+
# (e.g. a legacy daemon emitting only `today`) must not claim all-time
|
|
173
|
+
# emptiness it can't see, so it falls through to the per-period rows
|
|
174
|
+
# ("Today: nothing yet") instead.
|
|
175
|
+
if not any_activity and len(present) == len(MEMORY_PERIODS):
|
|
176
|
+
return ["Memory", "Nothing recalled yet — Rift learns as you use it"]
|
|
177
|
+
return ["Memory"] + [
|
|
178
|
+
memory_window_row(label, hits, tokens) for label, hits, tokens in present
|
|
179
|
+
]
|
|
139
180
|
|
|
140
181
|
|
|
141
182
|
# --- Menu-action line builders -------------------------------------------
|
|
@@ -443,9 +484,11 @@ def render(doctor, status, mcp, health, now):
|
|
|
443
484
|
# healthy or warning
|
|
444
485
|
lines.append("Rift is working")
|
|
445
486
|
lines += render_capture_rows(friend, now)
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
487
|
+
|
|
488
|
+
mem_rows = memory_section(mcp)
|
|
489
|
+
if mem_rows:
|
|
490
|
+
lines.append("---")
|
|
491
|
+
lines += mem_rows
|
|
449
492
|
|
|
450
493
|
client_rows = render_client_rows(status, doctor)
|
|
451
494
|
if client_rows:
|
|
@@ -36,27 +36,57 @@ while [[ -L "$SOURCE" ]]; do
|
|
|
36
36
|
done
|
|
37
37
|
SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
38
38
|
RIFT_HOME_DEFAULT="${HOME}/Library/Application Support/Rift"
|
|
39
|
-
|
|
39
|
+
|
|
40
|
+
# Packaged (.pkg) install layout — bundled Node + app tree under Rift home,
|
|
41
|
+
# a bash CLI shim at ~/.rift/bin/rift, daemon logs under ~/Library/Logs/Rift.
|
|
42
|
+
# Detect it so the menu bar works on a BARE Mac with NO env injection: the
|
|
43
|
+
# `rift menubar install` env (RIFT_BIN/NODE_BIN) does NOT persist into the
|
|
44
|
+
# installed plugin, so the plugin must self-resolve these paths every tick.
|
|
45
|
+
PACKAGED_NODE="${RIFT_HOME_DEFAULT}/node/bin/node"
|
|
46
|
+
PACKAGED_JS="${RIFT_HOME_DEFAULT}/app/dist/src/cli/index.js"
|
|
47
|
+
PACKAGED_SHIM="${HOME}/.rift/bin/rift"
|
|
48
|
+
if [[ -f "$PACKAGED_JS" && -x "$PACKAGED_NODE" ]]; then
|
|
49
|
+
PACKAGED_LOG_DIR="${HOME}/Library/Logs/Rift"
|
|
50
|
+
else
|
|
51
|
+
PACKAGED_LOG_DIR=""
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
LOG_DIR="${RIFT_LOG_DIR:-${PACKAGED_LOG_DIR:-${RIFT_HOME_DEFAULT}/logs}}"
|
|
40
55
|
DATA_DIR="${RIFT_DATA_DIR:-${RIFT_HOME_DEFAULT}/data}"
|
|
41
56
|
RENDERER="$SCRIPT_DIR/render-menu.py"
|
|
42
57
|
|
|
43
58
|
# Resolve the rift CLI. SwiftBar invokes shell commands with a stripped
|
|
44
|
-
# PATH, so menu actions need absolute paths end-to-end.
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
RIFT_BIN="${RIFT_BIN:-}"
|
|
59
|
+
# PATH, so menu actions need absolute paths end-to-end. We resolve:
|
|
60
|
+
# - NODE_BIN: an absolute node binary (bundled Node preferred), so actions
|
|
61
|
+
# don't depend on PATH and work on a Mac with no system Node.
|
|
62
|
+
# - RIFT_JS: the real JS entrypoint to pass as node's first arg. NEVER the
|
|
63
|
+
# bash shim — `node <bash-file>` fails — so we accept only a *.js target
|
|
64
|
+
# and prefer the packaged app entrypoint directly.
|
|
65
|
+
# - RIFT_BIN: an executable `rift` launcher (diagnostics + fallback). The
|
|
66
|
+
# packaged shim is a valid launcher when run DIRECTLY (it is not JS).
|
|
53
67
|
# REPO_ROOT only resolves to anything in a dev checkout; default it to empty
|
|
54
68
|
# so the dev-only candidate below is a harmless no-op under `set -u` on
|
|
55
|
-
# packaged
|
|
56
|
-
# candidate list fails to expand and the plugin crashes on every tick.)
|
|
69
|
+
# packaged/npm installs, where it is never set.
|
|
57
70
|
REPO_ROOT="${REPO_ROOT:-}"
|
|
71
|
+
|
|
72
|
+
NODE_BIN="${NODE_BIN:-}"
|
|
73
|
+
if [[ -z "$NODE_BIN" ]]; then
|
|
74
|
+
for candidate in \
|
|
75
|
+
"$PACKAGED_NODE" \
|
|
76
|
+
"/opt/homebrew/bin/node" \
|
|
77
|
+
"/usr/local/bin/node" \
|
|
78
|
+
"/usr/bin/node"; do
|
|
79
|
+
if [[ -x "$candidate" ]]; then
|
|
80
|
+
NODE_BIN="$candidate"
|
|
81
|
+
break
|
|
82
|
+
fi
|
|
83
|
+
done
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
RIFT_BIN="${RIFT_BIN:-}"
|
|
58
87
|
if [[ -z "$RIFT_BIN" ]]; then
|
|
59
88
|
for candidate in \
|
|
89
|
+
"$PACKAGED_SHIM" \
|
|
60
90
|
"/opt/homebrew/bin/rift" \
|
|
61
91
|
"/usr/local/bin/rift" \
|
|
62
92
|
"$HOME/.npm-global/bin/rift" \
|
|
@@ -69,8 +99,15 @@ if [[ -z "$RIFT_BIN" ]]; then
|
|
|
69
99
|
done
|
|
70
100
|
fi
|
|
71
101
|
|
|
72
|
-
RIFT_JS=""
|
|
73
|
-
|
|
102
|
+
RIFT_JS="${RIFT_JS:-}"
|
|
103
|
+
# Packaged app entrypoint is authoritative when present.
|
|
104
|
+
if [[ -z "$RIFT_JS" && -f "$PACKAGED_JS" ]]; then
|
|
105
|
+
RIFT_JS="$PACKAGED_JS"
|
|
106
|
+
fi
|
|
107
|
+
# Otherwise follow RIFT_BIN's symlink chain to the real entrypoint — but
|
|
108
|
+
# only accept a *.js target, so a bash launcher (the packaged shim, or an
|
|
109
|
+
# on-PATH wrapper) is never handed to `node` as a script.
|
|
110
|
+
if [[ -z "$RIFT_JS" && -n "$RIFT_BIN" ]]; then
|
|
74
111
|
target="$RIFT_BIN"
|
|
75
112
|
while [[ -L "$target" ]]; do
|
|
76
113
|
link_dir="$(cd -P "$(dirname "$target")" && pwd)"
|
|
@@ -81,24 +118,11 @@ if [[ -n "$RIFT_BIN" ]]; then
|
|
|
81
118
|
target="$link_dir/$link_target"
|
|
82
119
|
fi
|
|
83
120
|
done
|
|
84
|
-
if [[ -f "$target" ]]; then
|
|
121
|
+
if [[ -f "$target" && "$target" == *.js ]]; then
|
|
85
122
|
RIFT_JS="$target"
|
|
86
123
|
fi
|
|
87
124
|
fi
|
|
88
125
|
|
|
89
|
-
NODE_BIN="${NODE_BIN:-}"
|
|
90
|
-
if [[ -z "$NODE_BIN" ]]; then
|
|
91
|
-
for candidate in \
|
|
92
|
-
"/opt/homebrew/bin/node" \
|
|
93
|
-
"/usr/local/bin/node" \
|
|
94
|
-
"/usr/bin/node"; do
|
|
95
|
-
if [[ -x "$candidate" ]]; then
|
|
96
|
-
NODE_BIN="$candidate"
|
|
97
|
-
break
|
|
98
|
-
fi
|
|
99
|
-
done
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
126
|
# Run a rift subcommand, preferring node + JS entrypoint (PATH-independent),
|
|
103
127
|
# falling back to the launcher. Prints stdout; swallows stderr. Returns the
|
|
104
128
|
# command's exit code, or 127 when rift can't be resolved at all.
|
package/package.json
CHANGED