@rynfar/meridian 1.62.7 → 1.63.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.
Files changed (49) hide show
  1. package/bin/meridian-launchd.sh +128 -0
  2. package/dist/{cli-xmweegb1.js → cli-8yp89fan.js} +52 -0
  3. package/dist/{cli-21w6xm0d.js → cli-hdyptm7z.js} +4890 -766
  4. package/dist/cli.js +2 -2
  5. package/dist/{pluginPage-03q5j753.js → pluginPage-n3gdtbmj.js} +1 -1
  6. package/dist/{profilePage-gtazq15d.js → profilePage-vfj2dbhn.js} +1 -1
  7. package/dist/proxy/adapter.d.ts +13 -0
  8. package/dist/proxy/adapter.d.ts.map +1 -1
  9. package/dist/proxy/adapters/opencode.d.ts +7 -0
  10. package/dist/proxy/adapters/opencode.d.ts.map +1 -1
  11. package/dist/proxy/buildInfo.d.ts +94 -0
  12. package/dist/proxy/buildInfo.d.ts.map +1 -0
  13. package/dist/proxy/cwd.d.ts.map +1 -1
  14. package/dist/proxy/errors.d.ts.map +1 -1
  15. package/dist/proxy/passthroughDenial.d.ts +17 -0
  16. package/dist/proxy/passthroughDenial.d.ts.map +1 -0
  17. package/dist/proxy/passthroughEarlyStop.d.ts +52 -7
  18. package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -1
  19. package/dist/proxy/query.d.ts +8 -0
  20. package/dist/proxy/query.d.ts.map +1 -1
  21. package/dist/proxy/server.d.ts.map +1 -1
  22. package/dist/proxy/session/cache.d.ts +11 -2
  23. package/dist/proxy/session/cache.d.ts.map +1 -1
  24. package/dist/proxy/session/crossProcessTurnCoordinator.d.ts +40 -0
  25. package/dist/proxy/session/crossProcessTurnCoordinator.d.ts.map +1 -0
  26. package/dist/proxy/session/durableFileSystem.d.ts +21 -0
  27. package/dist/proxy/session/durableFileSystem.d.ts.map +1 -0
  28. package/dist/proxy/session/lineage.d.ts +20 -0
  29. package/dist/proxy/session/lineage.d.ts.map +1 -1
  30. package/dist/proxy/session/processIncarnation.d.ts +46 -0
  31. package/dist/proxy/session/processIncarnation.d.ts.map +1 -0
  32. package/dist/proxy/session/recoveryClaim.d.ts +19 -0
  33. package/dist/proxy/session/recoveryClaim.d.ts.map +1 -0
  34. package/dist/proxy/session/sdkProcessGate.d.ts +19 -0
  35. package/dist/proxy/session/sdkProcessGate.d.ts.map +1 -0
  36. package/dist/proxy/sessionLifecycle.d.ts +105 -0
  37. package/dist/proxy/sessionLifecycle.d.ts.map +1 -0
  38. package/dist/proxy/sessionStore.d.ts +53 -7
  39. package/dist/proxy/sessionStore.d.ts.map +1 -1
  40. package/dist/proxy/types.d.ts +4 -0
  41. package/dist/proxy/types.d.ts.map +1 -1
  42. package/dist/proxy/updateCheck.d.ts +31 -0
  43. package/dist/proxy/updateCheck.d.ts.map +1 -0
  44. package/dist/server.js +2 -2
  45. package/dist/telemetry/profileBar.d.ts +3 -3
  46. package/dist/telemetry/profileBar.d.ts.map +1 -1
  47. package/dist/telemetry/settingsPage.d.ts +1 -1
  48. package/dist/telemetry/settingsPage.d.ts.map +1 -1
  49. package/package.json +3 -2
@@ -0,0 +1,128 @@
1
+ #!/bin/sh
2
+ #
3
+ # Launch Meridian as a long-running service without drifting from the release.
4
+ #
5
+ # A service pointed straight at a checkout's `dist/cli.js` runs whatever was
6
+ # last built there. Build on a feature branch, and the next restart — a crash,
7
+ # a reboot, KeepAlive — silently serves unreleased code. `/health` cannot warn
8
+ # you, because the version string it reports comes from package.json and is
9
+ # identical on the branch and the tag.
10
+ #
11
+ # So this runs the *installed* package by default, and updates it when the
12
+ # registry is ahead. Development builds are still one env var away, and they
13
+ # announce themselves in `/health` and in the site header rather than passing
14
+ # as a release.
15
+ #
16
+ # Normal service use: bin/meridian-launchd.sh
17
+ # Test a local build: MERIDIAN_DEV_BUILD=1 MERIDIAN_PORT=3457 bin/meridian-launchd.sh
18
+ #
19
+ # Every exit path execs something. Under launchd's KeepAlive, a launcher that
20
+ # refuses to start is a proxy that is simply down, which is worse than one
21
+ # running a known-stale version.
22
+
23
+ set -u
24
+
25
+ PACKAGE="@rynfar/meridian"
26
+ CDPATH=""
27
+ REPO_DIR="$(cd -- "$(dirname -- "$0")/.." && pwd)"
28
+ CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/meridian"
29
+ UPDATE_STAMP="$CACHE_DIR/launcher-update-check"
30
+
31
+ # Bound how often a restart loop may talk to the registry. KeepAlive can
32
+ # restart this many times a minute; without a floor, a crash loop becomes a
33
+ # request flood.
34
+ MIN_CHECK_INTERVAL_SECONDS=3600
35
+
36
+ log() { echo "[meridian-launchd] $*"; }
37
+
38
+ # --- Development build: explicit, stamped, never mistaken for a release ---
39
+
40
+ if [ "${MERIDIAN_DEV_BUILD:-}" = "1" ]; then
41
+ if [ ! -f "$REPO_DIR/dist/cli.js" ]; then
42
+ log "MERIDIAN_DEV_BUILD=1 but $REPO_DIR/dist/cli.js is missing — run 'npm run build' first."
43
+ exit 1
44
+ fi
45
+ MERIDIAN_BUILD_SOURCE="dev"
46
+ MERIDIAN_BUILD_SHA="$(git -C "$REPO_DIR" rev-parse HEAD 2>/dev/null || echo "")"
47
+ MERIDIAN_BUILD_BRANCH="$(git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")"
48
+ if [ -n "$(git -C "$REPO_DIR" status --porcelain 2>/dev/null)" ]; then
49
+ MERIDIAN_BUILD_DIRTY="1"
50
+ else
51
+ MERIDIAN_BUILD_DIRTY="0"
52
+ fi
53
+ export MERIDIAN_BUILD_SOURCE MERIDIAN_BUILD_SHA MERIDIAN_BUILD_BRANCH MERIDIAN_BUILD_DIRTY
54
+ log "dev build: ${MERIDIAN_BUILD_BRANCH:-?} @ $(echo "$MERIDIAN_BUILD_SHA" | cut -c1-8)${MERIDIAN_BUILD_DIRTY:+ (dirty=$MERIDIAN_BUILD_DIRTY)}"
55
+ exec node "$REPO_DIR/dist/cli.js" "$@"
56
+ fi
57
+
58
+ # --- Release build: run what is installed, keep it current ---
59
+
60
+ CLI="$(command -v meridian 2>/dev/null || true)"
61
+
62
+ should_check() {
63
+ [ "${MERIDIAN_NO_SELF_UPDATE:-}" = "1" ] && return 1
64
+ [ -f "$UPDATE_STAMP" ] || return 0
65
+ last="$(cat "$UPDATE_STAMP" 2>/dev/null || echo "")"
66
+ # A truncated or garbage stamp would blow up the arithmetic below, and under
67
+ # `set -u` that aborts the function — permanently disabling the update check
68
+ # while the bad file sits there. Treat anything non-numeric as no stamp.
69
+ case "$last" in
70
+ '' | *[!0-9]*) return 0 ;;
71
+ esac
72
+ [ "$(( $(date +%s) - last ))" -ge "$MIN_CHECK_INTERVAL_SECONDS" ]
73
+ }
74
+
75
+ registry_latest() {
76
+ # Honours the same override as the in-process check (see updateCheck.ts), so
77
+ # a mirror configured for one applies to both.
78
+ node -e '
79
+ const url = process.env.MERIDIAN_UPDATE_CHECK_URL
80
+ || "https://registry.npmjs.org/-/package/'"$PACKAGE"'/dist-tags"
81
+ fetch(url, { signal: AbortSignal.timeout(5000) })
82
+ .then((r) => (r.ok ? r.json() : null))
83
+ .then((d) => process.stdout.write(typeof d?.latest === "string" ? d.latest : ""))
84
+ .catch(() => {})
85
+ ' 2>/dev/null
86
+ }
87
+
88
+ if [ -n "$CLI" ] && should_check; then
89
+ # Stamp BEFORE attempting anything network-bound. If the install below hangs
90
+ # or the process is killed mid-update, the next restart waits out the
91
+ # interval instead of retrying immediately, forever.
92
+ mkdir -p "$CACHE_DIR" 2>/dev/null
93
+ date +%s > "$UPDATE_STAMP" 2>/dev/null
94
+
95
+ INSTALLED="$("$CLI" --version 2>/dev/null || echo "")"
96
+ LATEST="$(registry_latest)"
97
+
98
+ if [ -n "$LATEST" ] && [ -n "$INSTALLED" ] && [ "$LATEST" != "$INSTALLED" ]; then
99
+ log "updating $PACKAGE: $INSTALLED -> $LATEST"
100
+ if command -v volta >/dev/null 2>&1 && [ -x "$HOME/.volta/bin/meridian" ]; then
101
+ volta install "$PACKAGE@$LATEST" || log "volta install failed — continuing on $INSTALLED"
102
+ else
103
+ npm install -g "$PACKAGE@$LATEST" || log "npm install failed — continuing on $INSTALLED"
104
+ fi
105
+ CLI="$(command -v meridian 2>/dev/null || echo "$CLI")"
106
+ fi
107
+ fi
108
+
109
+ if [ -n "$CLI" ]; then
110
+ MERIDIAN_BUILD_SOURCE="npm"
111
+ export MERIDIAN_BUILD_SOURCE
112
+ exec "$CLI" "$@"
113
+ fi
114
+
115
+ # No installed package. Fall back to the checkout so the service still comes
116
+ # up, but stamp it honestly — this is exactly the drift the launcher exists to
117
+ # make visible, so it must not be reported as a release.
118
+ log "no installed $PACKAGE found on PATH — falling back to the local build at $REPO_DIR/dist/cli.js"
119
+ log "install the release with: npm install -g $PACKAGE"
120
+ if [ ! -f "$REPO_DIR/dist/cli.js" ]; then
121
+ log "and $REPO_DIR/dist/cli.js does not exist either — nothing to run."
122
+ exit 1
123
+ fi
124
+ MERIDIAN_BUILD_SOURCE="local"
125
+ MERIDIAN_BUILD_SHA="$(git -C "$REPO_DIR" rev-parse HEAD 2>/dev/null || echo "")"
126
+ MERIDIAN_BUILD_BRANCH="$(git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")"
127
+ export MERIDIAN_BUILD_SOURCE MERIDIAN_BUILD_SHA MERIDIAN_BUILD_BRANCH
128
+ exec node "$REPO_DIR/dist/cli.js" "$@"
@@ -96,6 +96,29 @@ var themeCss = `
96
96
  .meridian-header .mh-profile .mh-profile-type {
97
97
  color: var(--muted, #8b949e); font-size: 10px;
98
98
  }
99
+ /* Build chip — two mutually exclusive states, and the colour is not a
100
+ style choice: "update available" is a link to the releases page, so it
101
+ is blue (interactive); "local/dev build" is a meta annotation with no
102
+ href, so it is violet. Swapping them would break the DESIGN.md rule. */
103
+ .meridian-header .mh-build {
104
+ display: none; align-items: center; gap: 6px;
105
+ font-size: 11px; font-weight: 500; white-space: nowrap;
106
+ padding: 3px 10px; border-radius: 20px; text-decoration: none;
107
+ transition: background 0.15s;
108
+ }
109
+ .meridian-header .mh-build.visible { display: inline-flex; }
110
+ .meridian-header .mh-build.update {
111
+ color: var(--accent, #58a6ff);
112
+ background: rgba(88,166,255,0.12);
113
+ border: 1px solid rgba(88,166,255,0.35);
114
+ }
115
+ .meridian-header .mh-build.update:hover { background: rgba(88,166,255,0.18); }
116
+ .meridian-header .mh-build.provenance {
117
+ color: var(--accent2, #bc8cff);
118
+ background: rgba(188,140,255,0.12);
119
+ border: 1px solid rgba(188,140,255,0.35);
120
+ cursor: default;
121
+ }
99
122
  .meridian-header .mh-status {
100
123
  display: inline-flex; align-items: center; gap: 6px;
101
124
  font-size: 11px; color: var(--muted, #8b949e); white-space: nowrap;
@@ -115,6 +138,7 @@ var themeCss = `
115
138
  `, profileBarHtml, profileBarJs = `
116
139
  (function() {
117
140
  var profileChip = document.getElementById('mhProfile');
141
+ var buildChip = document.getElementById('mhBuild');
118
142
  var statusDot = document.getElementById('mhDot');
119
143
  var statusText = document.getElementById('mhStatusText');
120
144
 
@@ -129,11 +153,38 @@ var themeCss = `
129
153
 
130
154
  function esc(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
131
155
 
156
+ // Build provenance chip. Hidden entirely for a current npm install, which
157
+ // is the case that needs no comment.
158
+ function renderBuild(build) {
159
+ if (!buildChip) return;
160
+ if (!build) { buildChip.className = 'mh-build'; return; }
161
+ if (build.source !== 'npm') {
162
+ buildChip.textContent = (build.source === 'dev' ? 'dev build' : 'local build') + (build.dirty ? ' *' : '');
163
+ buildChip.removeAttribute('href');
164
+ buildChip.title = 'Not an npm release — the reported version ' + build.version +
165
+ ' is the tree\\'s last release, not proof of what is running' +
166
+ (build.branch ? '\\nbranch: ' + build.branch : '') +
167
+ (build.sha ? '\\ncommit: ' + build.sha.slice(0, 8) : '') +
168
+ (build.dirty ? '\\nuncommitted changes present' : '');
169
+ buildChip.className = 'mh-build provenance visible';
170
+ return;
171
+ }
172
+ if (build.updateAvailable) {
173
+ buildChip.textContent = build.latest + ' available';
174
+ buildChip.href = 'https://github.com/rynfar/meridian/releases';
175
+ buildChip.title = 'Running ' + build.version + ' — update with:\\nnpm install -g @rynfar/meridian@latest';
176
+ buildChip.className = 'mh-build update visible';
177
+ return;
178
+ }
179
+ buildChip.className = 'mh-build';
180
+ }
181
+
132
182
  function loadHeader() {
133
183
  fetch('/health').then(function(r) { return r.json(); }).then(function(h) {
134
184
  var st = h.status === 'healthy' ? 'healthy' : h.status === 'degraded' ? 'degraded' : 'unhealthy';
135
185
  statusDot.className = 'mh-dot ' + st;
136
186
  statusText.textContent = st === 'healthy' ? 'Operational' : st === 'degraded' ? 'Degraded' : 'Offline';
187
+ renderBuild(h.build);
137
188
  }).catch(function() {
138
189
  statusDot.className = 'mh-dot unhealthy';
139
190
  statusText.textContent = 'Offline';
@@ -169,6 +220,7 @@ var init_profileBar = __esm(() => {
169
220
  <a href="/plugins" id="nav-plugins">Plugins</a>
170
221
  </nav>
171
222
  <div class="mh-right">
223
+ <a class="mh-build" id="mhBuild" target="_blank" rel="noopener"></a>
172
224
  <a class="mh-profile" id="mhProfile" href="/" title="Active profile — switch from the home page"></a>
173
225
  <span class="mh-status" id="mhStatus"><span class="mh-dot" id="mhDot"></span><span class="mh-status-text" id="mhStatusText"></span></span>
174
226
  </div>