trybeacon 0.1.80 → 0.1.81
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/.claude-plugin/plugin.json +1 -1
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +18 -18
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +2 -2
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +26 -25
- package/.next/server/app/_not-found.segments/_full.segment.rsc +26 -25
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +15 -14
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/docs/page.js +2 -2
- package/.next/server/app/docs/page.js.nft.json +1 -1
- package/.next/server/app/docs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/docs.html +1 -1
- package/.next/server/app/docs.rsc +27 -26
- package/.next/server/app/docs.segments/_full.segment.rsc +27 -26
- package/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/docs.segments/_index.segment.rsc +15 -14
- package/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/.next/server/app/help/page.js +2 -2
- package/.next/server/app/help/page.js.nft.json +1 -1
- package/.next/server/app/help/page_client-reference-manifest.js +1 -1
- package/.next/server/app/help.html +1 -1
- package/.next/server/app/help.rsc +35 -34
- package/.next/server/app/help.segments/_full.segment.rsc +35 -34
- package/.next/server/app/help.segments/_head.segment.rsc +1 -1
- package/.next/server/app/help.segments/_index.segment.rsc +15 -14
- package/.next/server/app/help.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/help.segments/help/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/help.segments/help.segment.rsc +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +25 -24
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +25 -24
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +15 -14
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/learn/page.js +4 -4
- package/.next/server/app/learn/page.js.nft.json +1 -1
- package/.next/server/app/learn/page_client-reference-manifest.js +1 -1
- package/.next/server/app/map/page.js +2 -2
- package/.next/server/app/map/page.js.nft.json +1 -1
- package/.next/server/app/map/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +2 -2
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/plan/page.js +3 -3
- package/.next/server/app/plan/page.js.nft.json +1 -1
- package/.next/server/app/plan/page_client-reference-manifest.js +1 -1
- package/.next/server/app/s/[token]/page.js +2 -2
- package/.next/server/app/s/[token]/page.js.nft.json +1 -1
- package/.next/server/app/s/[token]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page.js +2 -2
- package/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +18 -18
- package/.next/server/chunks/{7720.js → 141.js} +4 -4
- package/.next/server/chunks/2025.js +1 -1
- package/.next/server/chunks/2455.js +1 -0
- package/.next/server/chunks/3174.js +1 -1
- package/.next/server/chunks/3179.js +1 -0
- package/.next/server/chunks/6469.js +2 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1909-0f500ebe4df09208.js +1 -0
- package/.next/static/chunks/{3908-80efc60050779adf.js → 3908-2ba88cd8ba5dfa2e.js} +1 -1
- package/.next/static/chunks/{2059-fba06ba63ba64522.js → 4674-31ad596c3e856647.js} +3 -3
- package/.next/static/chunks/4752-81a4fc25de32efa2.js +1 -0
- package/.next/static/chunks/4853-43350f60d0d9135b.js +1 -0
- package/.next/static/chunks/6639-f0b63e1e7d03a20a.js +1 -0
- package/.next/static/chunks/9784-880aab43467bf1e0.js +1 -0
- package/.next/static/chunks/app/layout-ef1edf5ed5839b01.js +1 -0
- package/.next/static/chunks/app/learn/page-6459c292421bec82.js +7 -0
- package/.next/static/chunks/app/map/page-602309791f192143.js +1 -0
- package/.next/static/chunks/app/page-32a051917fc57795.js +1 -0
- package/.next/static/chunks/app/plan/page-920d4fecdd6dde34.js +11 -0
- package/.next/static/chunks/app/s/[token]/page-1df7929974ceeb5a.js +1 -0
- package/.next/static/chunks/app/settings/page-f128ae102e013087.js +1 -0
- package/.next/static/css/9301599114d42898.css +1 -0
- package/.next/trace +47 -46
- package/.next/trace-build +1 -1
- package/dist/bin/beacon.js +16 -15
- package/dist/bin/doctor.js +61 -60
- package/dist/bin/hook.js +58 -57
- package/dist/bin/mcp.js +70 -69
- package/dist/bin/plan.js +61 -60
- package/dist/bin/uninstall.js +59 -58
- package/dist/lib/assets.js +55 -20
- package/dist/lib/codex-install.js +62 -61
- package/dist/lib/daemon-boot.js +37 -0
- package/dist/lib/global-install.js +62 -61
- package/package.json +1 -1
- package/.next/server/chunks/5295.js +0 -1
- package/.next/server/chunks/7652.js +0 -1
- package/.next/static/chunks/1909-98243a0473be2aae.js +0 -1
- package/.next/static/chunks/4477-cda153702c7812d2.js +0 -1
- package/.next/static/chunks/4607-a668ea431c41e60e.js +0 -1
- package/.next/static/chunks/4853-0082a1e1b820a293.js +0 -1
- package/.next/static/chunks/5520-32e29b8bbff59f44.js +0 -1
- package/.next/static/chunks/app/layout-e728d45f193e3b95.js +0 -1
- package/.next/static/chunks/app/learn/page-fc0bf8bce602526b.js +0 -7
- package/.next/static/chunks/app/map/page-847b374e7dfed924.js +0 -1
- package/.next/static/chunks/app/page-ec00130a7a249f14.js +0 -1
- package/.next/static/chunks/app/plan/page-1108bdf804b8a1bd.js +0 -11
- package/.next/static/chunks/app/s/[token]/page-2fc7806fc2f205a5.js +0 -1
- package/.next/static/chunks/app/settings/page-7e86fd456b92c248.js +0 -1
- package/.next/static/css/6eabb17c2a2081f2.css +0 -1
- /package/.next/static/{zI2f5SCpeUG4MfjJNbXnf → ms-hAcPFSz7LxuiDMzzcP}/_buildManifest.js +0 -0
- /package/.next/static/{zI2f5SCpeUG4MfjJNbXnf → ms-hAcPFSz7LxuiDMzzcP}/_ssgManifest.js +0 -0
package/.next/trace-build
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"run-webpack","duration":
|
|
1
|
+
[{"name":"run-webpack","duration":33072099,"timestamp":49201463,"id":14,"parentId":1,"tags":{},"startTime":1783379970314,"traceId":"7b58f1b50a253bd6"},{"name":"run-typescript","duration":12101312,"timestamp":82275791,"id":4957,"parentId":1,"tags":{},"startTime":1783380003389,"traceId":"7b58f1b50a253bd6"},{"name":"static-check","duration":829860,"timestamp":94392920,"id":4960,"parentId":1,"tags":{},"startTime":1783380015506,"traceId":"7b58f1b50a253bd6"},{"name":"static-generation","duration":4102808,"timestamp":95756366,"id":5152,"parentId":1,"tags":{},"startTime":1783380016869,"traceId":"7b58f1b50a253bd6"},{"name":"collect-build-traces","duration":11577582,"timestamp":95225443,"id":5149,"parentId":1,"tags":{},"startTime":1783380016338,"traceId":"7b58f1b50a253bd6"},{"name":"telemetry-flush","duration":65,"timestamp":106806849,"id":5161,"parentId":1,"tags":{},"startTime":1783380027920,"traceId":"7b58f1b50a253bd6"},{"name":"next-build","duration":57747826,"timestamp":49059100,"id":1,"tags":{"buildMode":"default","version":"16.2.7","bundler":"webpack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1783379970172,"traceId":"7b58f1b50a253bd6"}]
|
package/dist/bin/beacon.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{execSync as
|
|
4
|
-
\u25C9 Beacon setup \xB7 ${z}`),console.log(` \u2713 skill: ${
|
|
5
|
-
`)}return{initSkill:
|
|
6
|
-
`+" cd into a repo (or run `git init` there) and try again."),process.exit(1);let
|
|
7
|
-
`+"
|
|
3
|
+
import{execSync as V,spawn as c}from"child_process";import{existsSync as h,mkdirSync as d,openSync as p,readFileSync as m,writeFileSync as t}from"fs";import{homedir as l,platform as y}from"os";import{basename as a,dirname as v,join as N}from"path";import{fileURLToPath as n}from"url";var _=v(n(import.meta.url)),S=a(v(_))==="dist",F=S?v(v(_)):v(_),w=process.cwd(),D=process.env.BEACON_HOME||N(l(),".beacon"),L=N(D,"server.json"),R=process.env.PORT||"4319",s=/[\\/]\.claude[\\/]plugins[\\/]/.test(_);if(!process.env.CLAUDE_PLUGIN_ROOT&&s&&h(N(F,".claude-plugin","plugin.json")))process.env.CLAUDE_PLUGIN_ROOT=F;if(!process.env.BEACON_MIGRATIONS_DIR)process.env.BEACON_MIGRATIONS_DIR=N(F,"drizzle");function Q(z){if(!S)return N(F,z);return N(F,"dist",z.replace(/\.ts$/,".js"))}var q=process.argv[2];if(q==="mcp")await import(Q("bin/mcp.ts"));else if(q==="hook")await import(Q("bin/hook.ts"));else if(q==="guard")await import(Q("bin/guard.ts"));else if(q==="plan")await import(Q("bin/plan.ts"));else if(q==="ask")await import(Q("bin/ask.ts"));else if(q==="answer")await import(Q("bin/answer.ts"));else if(q==="prompt")await import(Q("bin/prompt.ts"));else if(q==="stop-hook")await import(Q("bin/stop-hook.ts"));else if(q==="stop")u();else if(q==="remove")await import(Q("bin/remove.ts"));else if(q==="setup")await f(A()||w);else if(q==="ensure")await Xz();else if(q==="init-persist")await i(process.argv[3]);else if(q==="doctor")await import(Q("bin/doctor.ts"));else if(q==="uninstall")await import(Q("bin/uninstall.ts"));else if(q==="update")await Qz(process.argv.includes("--force")||process.argv.includes("-f"));else if(q==="telemetry")await $z(process.argv[3]);else if(q==="version"||q==="--version"||q==="-v")console.log(b());else await Zz();async function f(z,X=!1){let{installInitSkill:Z,installRefreshSkill:G,installCodexRepoSkills:K,ensureMcp:Y,ensureWorkflowDoc:U}=await import(Q("lib/assets.ts")),{selfHealGlobal:M,isPluginManaged:J}=await import(Q("lib/global-install.ts")),{codexDetected:I}=await import(Q("lib/codex-install.ts")),$=await M();if(J())return{initSkill:"",refreshSkill:"",mcp:{path:"",added:!1,updated:!1},codexSkills:[],heal:$};let{isRegistrableWorkspacePath:W}=await import(Q("lib/workspaces.ts"));if(!W(z))return{initSkill:"",refreshSkill:"",mcp:{path:"",added:!1,updated:!1},codexSkills:[],heal:$};let j=Z(z),P=G(z);U(z);let B=Y(z),O=I()?K(z):[];if(X){if(B.added||B.updated)console.log(`[beacon] ${B.added?"registered":"updated"} Beacon MCP in ${B.path} \u2014 restart your agent CLI`+(B.updated?" to apply the longer plan-review timeout.":" to use @beacon mentions."))}else{console.log(`
|
|
4
|
+
\u25C9 Beacon setup \xB7 ${z}`),console.log(` \u2713 skill: ${j}`),console.log(` \u2713 skill: ${P}`);for(let x of O)console.log(` \u2713 skill: ${x}`);console.log(` ${B.added?"\u2713 added ":"\xB7 kept "} Beacon MCP in ${B.path}`),console.log(` \u2192 in this repo, run /beacon-init in your agent (Claude Code or Codex) to map the repo.
|
|
5
|
+
`)}return{initSkill:j,refreshSkill:P,mcp:B,codexSkills:O,heal:$}}async function i(z){let X=A()||w,{idForPath:Z,isRegistrableWorkspacePath:G,BEACON_WS_PATH_HEADER:K}=await import(Q("lib/workspaces.ts"));if(!G(X))console.error(`[beacon] refusing to init ${X} \u2014 that's your home directory, not a project.
|
|
6
|
+
`+" cd into a repo (or run `git init` there) and try again."),process.exit(1);let Y="";try{Y=m(z??0,"utf8").trim()}catch($){console.error(`[beacon] could not read the init analysis ${z?`from ${z}`:"from stdin"}: ${$ instanceof Error?$.message:$}`),process.exit(1)}if(!Y)console.error("[beacon] empty init analysis \u2014 pass the JSON as a file argument (`beacon init-persist analysis.json`) or on stdin."),process.exit(1);await f(X,!0);let U=await k(),M=Z(X),J;try{J=await fetch(`http://localhost:${U}/api/init`,{method:"POST",headers:{"content-type":"application/json","x-beacon-workspace":M,[K]:X},body:Y})}catch($){console.error(`[beacon] could not reach the Beacon daemon on port ${U}: ${$ instanceof Error?$.message:$}`),process.exit(1)}let I=await J.text();if(!J.ok)console.error(`[beacon] init failed (HTTP ${J.status}): ${I}`),process.exit(1);console.log(`[beacon] mapped ${X} into Beacon: ${I}`),console.log(`[beacon] open the panel \u2192 http://localhost:${U}/map`)}function A(){try{return V("git rev-parse --show-toplevel",{cwd:w,stdio:["ignore","pipe","ignore"]}).toString().trim()}catch{return""}}function E(z){try{return process.kill(z,0),!0}catch{return!1}}function T(z){try{return JSON.parse(m(z,"utf8"))}catch{return null}}async function C(z){try{return(await fetch(z)).ok}catch{return!1}}async function o(z,X=60){for(let Z=0;Z<X;Z++){if(await C(z))return!0;await new Promise((G)=>setTimeout(G,500))}return!1}function r(z){d(D,{recursive:!0});let X=p(N(D,"server.log"),"a"),Z={...process.env,PORT:z,BEACON_NO_OPEN:"1",BEACON_MIGRATIONS_DIR:N(F,"drizzle")};delete Z.BEACON_REPO,delete Z.BEACON_DATA_DIR,delete Z.DATABASE_URL;let K=c("bun",S?["run","start"]:["run","dev"],{cwd:F,env:Z,detached:!0,stdio:["ignore",X,X]});K.unref();let Y={pid:K.pid??0,port:z};return t(L,JSON.stringify(Y)),Y}async function k(){let z=T(L);if(z&&E(z.pid)&&await C(`http://localhost:${z.port}/api/workspace`))return z.port;let{desktopAppInstalled:X,decideDaemonBoot:Z,decideDaemonRecheck:G}=await import(Q("lib/daemon-boot.ts")),K=Z({healthy:!1,appInstalled:X()})==="app";if(K){let $=await e();if($)return $;console.log("[beacon] the Beacon app didn't come up in time \u2014 starting the bundled server\u2026")}let Y=T(L);if(Y&&G({present:!0,alive:E(Y.pid),healthy:await C(`http://localhost:${Y.port}/api/workspace`)})==="reuse")return Y.port;let{findAvailablePort:U}=await import(Q("lib/daemon-port.ts")),M=String(await U(Number(R)));console.log(M===R?"[beacon] starting the Beacon server\u2026":`[beacon] port ${R} is busy \u2014 starting the Beacon server on port ${M}\u2026`);let J=r(M);if(!await o(`http://localhost:${J.port}/api/workspace`))console.log("[beacon] (server is taking a while \u2014 it may still be compiling)");if(K){await new Promise((W)=>setTimeout(W,5000));let $=T(L);if($&&$.pid!==J.pid)console.log(`[beacon] the Beacon app came up after the bundled server started \u2014 two backends may be running.
|
|
7
|
+
`+" Run `beacon stop`, then relaunch, to leave just one.")}return J.port}async function e(){if(y()!=="darwin")return null;console.log("[beacon] launching the Beacon app to serve the backend\u2026");try{V("open -ga Beacon",{stdio:"ignore"})}catch{return null}for(let z=0;z<60;z++){let X=T(L);if(X?.port&&await C(`http://localhost:${X.port}/api/workspace`))return X.port;await new Promise((Z)=>setTimeout(Z,500))}return null}function zz(z){if(process.env.BEACON_NO_OPEN)return;let X=y()==="darwin"?"open":y()==="win32"?"start":"xdg-open";try{V(`${X} "${z}"`,{stdio:"ignore"})}catch{}}async function Xz(){let z=A()||w,{registerWorkspaceExplicit:X,idForPath:Z,ensureWorkspaceDb:G,isRegistrableWorkspacePath:K}=await import(Q("lib/workspaces.ts"));if(!K(z))return;let Y=Z(z);await G(Y),X(z);let U=await k();console.log(`[beacon] ready \u2192 http://localhost:${U}/map?ws=${Y}`)}async function Zz(){let z=A()||w,{registerWorkspaceExplicit:X,idForPath:Z,dataDirFor:G,ensureWorkspaceDb:K,isRegistrableWorkspacePath:Y}=await import(Q("lib/workspaces.ts"));if(!Y(z))console.error(`[beacon] refusing to open Beacon in ${z} \u2014 that's your home directory, not a project.
|
|
8
|
+
`+" cd into a repo (or run `git init` there) and try again."),process.exit(1);let U=Z(z),M=G(U),J=!h(N(M,"db.sqlite"));if(J)console.log(`[beacon] first run for ${z} \u2014 creating database\u2026`);let I=await K(U);if(!I.ok)console.error(`[beacon] failed to provision database: ${I.error}`);if(J)console.log("[beacon] tip: already have code here? run `/beacon-init` in your agent (Claude Code or Codex) to map the project.");let{heal:$}=await f(z,!0),W=[];if($.skillsAdded.length)W.push(`skills ${$.skillsAdded.join(", ")}`);if($.hooksAdded)W.push(`${$.hooksAdded} Claude Code hook${$.hooksAdded===1?"":"s"}`);if($.claudeMdBlockTouched)W.push("global CLAUDE.md block");if(W.length)console.log(`[beacon] wired into ~/.claude/: ${W.join(" + ")}.`);let j=$.codex;if(j){let H=[];if(j.skillsAdded.length)H.push(`skills ${j.skillsAdded.join(", ")}`);if(j.hooksAdded)H.push(`${j.hooksAdded} Codex hook${j.hooksAdded===1?"":"s"}`);if(j.agentsMdBlockTouched)H.push("global AGENTS.md block");if(j.mcp.added)H.push("MCP entry in config.toml");if(H.length)console.log(`[beacon] wired into ~/.codex/: ${H.join(" + ")}.`);if(j.mcp.error)console.log(`[beacon] codex MCP not wired: ${j.mcp.error}`)}try{let H=await import(Q("lib/telemetry.ts"));if(!H.telemetryStatus().machineId){let g=H.telemetryStatus().enabled;console.log(`[beacon] telemetry: Beacon sends an anonymous heartbeat (random machine id, version, OS,
|
|
8
9
|
`+` architecture \u2014 never repo names, paths, or code) at most every 12h to count
|
|
9
10
|
`+` active installs. Opt out: \`beacon telemetry off\`, BEACON_TELEMETRY_DISABLED=1,
|
|
10
|
-
or DO_NOT_TRACK=1. Details: beacon telemetry status.${g?"":" (currently disabled by your env)"}`),
|
|
11
|
+
or DO_NOT_TRACK=1. Details: beacon telemetry status.${g?"":" (currently disabled by your env)"}`),H.ensureTelemetryId()}}catch{}X(z);let B=`http://localhost:${await k()}`,O=`/map?ws=${U}`,x=`${B}/api/workspace/activate?id=${U}&redirect=${encodeURIComponent(O)}`;if(console.log(`
|
|
11
12
|
\u25C9 Beacon
|
|
12
13
|
repo: ${z}
|
|
13
14
|
data: ${M}
|
|
14
|
-
url: ${
|
|
15
|
-
`),console.log(" (the server keeps running in the background \u2014 `beacon stop` to stop it)\n"),await fetch(`${
|
|
16
|
-
`);else
|
|
17
|
-
\u25C9 Beacon telemetry: ${Z.enabled?"enabled":"disabled"}${
|
|
18
|
-
`+" toggle: `beacon telemetry on|off` \xB7 env: BEACON_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1\n")}async function
|
|
19
|
-
npm i -g trybeacon@latest`);return}let K=null;try{let
|
|
20
|
-
${Z}`),process.exitCode=1;return}try{
|
|
21
|
-
claude plugin update ${X.key}`);return}console.log(`[beacon] updating the Beacon Claude Code plugin (${X.key})\u2026`);try{if(X.marketplace)
|
|
22
|
-
claude plugin update ${X.key}`)}}function u(){let z=
|
|
15
|
+
url: ${B}
|
|
16
|
+
`),console.log(" (the server keeps running in the background \u2014 `beacon stop` to stop it)\n"),await fetch(`${B}/api/tab/presence`,{headers:{"x-beacon-workspace":U}}).then((H)=>H.json()).then((H)=>!!H?.live).catch(()=>!1))await fetch(`${B}/api/tab/nav`,{method:"POST",headers:{"content-type":"application/json","x-beacon-workspace":U},body:JSON.stringify({path:O})}).catch(()=>{}),console.log(` \u21BB reusing your open Beacon tab \u2014 switch to your browser.
|
|
17
|
+
`);else zz(x)}function b(){return T(N(F,"package.json"))?.version??"0.0.0"}async function $z(z){let X=await import(Q("lib/telemetry.ts"));if(z==="on"||z==="off"){X.setTelemetryEnabled(z==="on"),console.log(`[beacon] telemetry ${z==="on"?"enabled":"disabled"}.`);return}if(z&&z!=="status")console.error("usage: beacon telemetry [on|off|status]"),process.exit(1);let Z=X.telemetryStatus(),G=Z.reason==="env:BEACON_TELEMETRY_DISABLED"?" (BEACON_TELEMETRY_DISABLED=1)":Z.reason==="env:DO_NOT_TRACK"?" (DO_NOT_TRACK)":Z.reason==="preference"?" (beacon telemetry off)":"";if(console.log(`
|
|
18
|
+
\u25C9 Beacon telemetry: ${Z.enabled?"enabled":"disabled"}${G}`),console.log(` machine id: ${Z.machineId??"(not generated yet \u2014 created on first `beacon` run)"}`),Z.machineId)console.log(` payload: ${JSON.stringify(X.heartbeatPayload(b()))}`);console.log(` sent at most every 12h while the daemon runs \u2014 never repo names, paths, or code.
|
|
19
|
+
`+" toggle: `beacon telemetry on|off` \xB7 env: BEACON_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1\n")}async function Qz(z){let X=b(),{INSTALL_COMMAND:Z,NPM_LATEST_URL:G}=await import(Q("lib/release.ts"));if(y()==="win32"){console.log(`[beacon] current version v${X}.`),console.log(`[beacon] on Windows, update with your package manager:
|
|
20
|
+
npm i -g trybeacon@latest`);return}let K=null;try{let Y=await fetch(G);if(Y.ok)K=(await Y.json()).version??null}catch{}if(K&&!z){let{isNewerVersion:Y}=await import(Q("lib/semver.ts"));if(!Y(K,X)){console.log(`[beacon] already on the latest version (v${X}).`),console.log(" run `beacon update --force` to reinstall anyway.");return}}console.log(K?`[beacon] updating Beacon v${X} \u2192 v${K}\u2026`:`[beacon] reinstalling Beacon (current v${X})\u2026`);try{V(Z,{stdio:"inherit"})}catch{console.error(`[beacon] update failed. Run it manually:
|
|
21
|
+
${Z}`),process.exitCode=1;return}try{V("beacon setup",{stdio:"inherit"})}catch{}await Yz(),u(),console.log("[beacon] updated. Run `beacon` to relaunch on the new version.")}async function Yz(){let{installedBeaconPlugin:z}=await import(Q("lib/global-install.ts")),X=z();if(!X)return;try{V("command -v claude",{stdio:"ignore"})}catch{console.log(`[beacon] Beacon plugin detected \u2014 update it with:
|
|
22
|
+
claude plugin update ${X.key}`);return}console.log(`[beacon] updating the Beacon Claude Code plugin (${X.key})\u2026`);try{if(X.marketplace)V(`claude plugin marketplace update ${X.marketplace}`,{stdio:"inherit"});V(`claude plugin update ${X.key}`,{stdio:"inherit"}),console.log("[beacon] plugin updated \u2014 restart your agent to apply.")}catch{console.log(`[beacon] couldn't auto-update the plugin. Run:
|
|
23
|
+
claude plugin update ${X.key}`)}}function u(){let z=T(L);if(z&&E(z.pid))try{try{process.kill(-z.pid)}catch{process.kill(z.pid)}console.log(`[beacon] stopped the server (pid ${z.pid}).`)}catch{console.log("[beacon] could not stop the server.")}else console.log("[beacon] no server running.")}
|
package/dist/bin/doctor.js
CHANGED
|
@@ -1,22 +1,57 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var
|
|
3
|
+
var tZ=Object.defineProperty;var nZ=(Q)=>Q;function rZ(Q,Z){this[Q]=nZ.bind(null,Z)}var wQ=(Q,Z)=>{for(var $ in Z)tZ(Q,$,{get:Z[$],enumerable:!0,configurable:!0,set:rZ.bind(Z,$)})};var g=(Q,Z)=>()=>(Q&&(Z=Q(Q=0)),Z);import{existsSync as k,mkdirSync as RQ,readdirSync as dZ,readFileSync as E,rmSync as aZ,writeFileSync as r}from"fs";import{basename as oZ,dirname as iQ,join as R}from"path";function eQ(){return!!process.env.CLAUDE_PLUGIN_ROOT}function d(Q=process.env.HOME||process.env.USERPROFILE||""){if(!Q)return null;let Z=R(Q,".claude","plugins");if(!k(Z))return null;let $=[Z];for(let J=0;J<3&&$.length;J++){let Y=[];for(let V of $){let z=R(V,".claude-plugin","plugin.json");try{if(k(z)&&JSON.parse(E(z,"utf8")).name==="beacon")return V}catch{}try{for(let H of dZ(V,{withFileTypes:!0}))if(H.isDirectory())Y.push(R(V,H.name))}catch{}}$=Y}return null}function QZ(Q){return d(Q)!==null}function iZ(Q){return/[\\/]\.claude[\\/]plugins[\\/]/.test(Q)}function x(){let Q=process.env.BEACON_CLI_PATH;if(Q)return Q;if(k(n))return n;return"beacon"}function FQ(Q){let Z=Q.indexOf(" ");return Z===-1?Q:Q.slice(0,Z)}function a(Q){let Z=x();if(Z==="beacon")return Q;return Q.replace(/^beacon(\s|$)/,`${Z}$1`)}function F(Q){let Z=FQ(Q);return oZ(Z)+Q.slice(Z.length)}function eZ(Q=process.env.HOME||process.env.USERPROFILE||""){if(!Q)return null;try{let Z=JSON.parse(E(R(Q,".claude","plugins","installed_plugins.json"),"utf8"));for(let $ of Object.keys(Z.plugins??{}))if(/^beacon@/.test($))return{key:$,marketplace:$.split("@")[1]??""}}catch{}return null}function i(Q){try{return JSON.parse(E(Q,"utf8"))}catch{return{}}}function ZZ(Q,Z){RQ(iQ(Q),{recursive:!0}),r(Q,JSON.stringify(Z,null,2)+`
|
|
4
|
+
`)}function e(Q,Z){let $=i(Q);$.hooks=$.hooks??{},$.hooks[Z.event]=$.hooks[Z.event]??[];let J=$.hooks[Z.event];if(J.some((V)=>V.matcher===Z.matcher&&V.hooks?.some((z)=>F(z.command)===F(Z.command))))return!1;return J.push({matcher:Z.matcher,hooks:[{type:"command",command:Z.command}]}),ZZ(Q,$),!0}function QQ(Q,Z){return(i(Q).hooks?.[Z.event]??[]).some((Y)=>Y.hooks?.some((V)=>F(V.command)===F(Z.command)))}function $Z(Q,Z){let J=i(Q).hooks?.[Z.event]??[];for(let Y of J)for(let V of Y.hooks??[])if(F(V.command)===F(Z.command))return V.command;return null}function ZQ(Q,Z){let $=i(Q),J=$.hooks?.[Z.event];if(!J)return!1;let Y=!1,V=J.map((z)=>{let H=z.hooks?.length??0,q=(z.hooks??[]).filter((U)=>F(U.command)!==F(Z.command));if(q.length!==H)Y=!0;return{...z,hooks:q}}).filter((z)=>(z.hooks??[]).length>0);if(!Y)return!1;if(V.length)$.hooks[Z.event]=V;else delete $.hooks[Z.event];if($.hooks&&Object.keys($.hooks).length===0)delete $.hooks;return ZZ(Q,$),!0}function $Q(Q,Z,$,J){let Y=`${Z}
|
|
5
|
+
${J.trim()}
|
|
6
|
+
${$}`,V="";try{V=E(Q,"utf8")}catch{}let z=new RegExp(`${Z}[\\s\\S]*?${$}`);V=z.test(V)?V.replace(z,Y):V.trim()?`${V.trim()}
|
|
7
|
+
|
|
8
|
+
${Y}
|
|
9
|
+
`:`${Y}
|
|
10
|
+
`,RQ(iQ(Q),{recursive:!0}),r(Q,V.endsWith(`
|
|
11
|
+
`)?V:`${V}
|
|
12
|
+
`)}function _(Q,Z){try{return E(Q,"utf8").includes(Z)}catch{return!1}}function JQ(Q,Z,$){let J="";try{J=E(Q,"utf8")}catch{return!1}let Y=new RegExp(`${Z}[\\s\\S]*?${$}\\n?`);if(!Y.test(J))return!1;let V=J.replace(Y,"").replace(/\n{3,}/g,`
|
|
13
|
+
|
|
14
|
+
`).trimStart();return r(Q,V),!0}function YQ(Q,Z,$){let J=R(Q,Z);RQ(J,{recursive:!0});let Y=R(J,"SKILL.md");return r(Y,$),Y}function L(Q,Z){return k(R(Q,Z,"SKILL.md"))}function VQ(Q,Z){let $=R(Q,Z);if(!k($))return!1;return aZ($,{recursive:!0,force:!0}),!0}var N,n="/Applications/Beacon.app/Contents/Resources/bin/beacon",o=`## Beacon (visual planning panel)
|
|
15
|
+
|
|
16
|
+
This machine has Beacon installed \u2014 a local visual planning surface for the terminal-side
|
|
17
|
+
agent. Beacon proposes feature plans (roadmap features + DB schema + endpoints) via MCP,
|
|
18
|
+
the user reviews on a canvas at /plan, and feedback flows back as the next round.
|
|
19
|
+
|
|
20
|
+
**When to invoke**
|
|
21
|
+
- User asks to "plan a feature" / "design a schema" \u2192 if the \`beacon_propose_plan\`
|
|
22
|
+
MCP tool is available, design the plan and call it. If it is NOT available, the panel
|
|
23
|
+
isn't wired in this repo \u2014 run \`beacon\` here once, then retry.
|
|
24
|
+
- User asks to "set up Beacon" / "map this repo" \u2192 invoke the \`beacon-init\` skill.
|
|
25
|
+
- User asks to "refresh Beacon" / "update the map" / "bring Beacon up to date" \u2192 invoke
|
|
26
|
+
the \`beacon-refresh\` skill. Re-surveys the repo and updates init-derived nodes while
|
|
27
|
+
preserving anything the user added by hand.
|
|
28
|
+
- User asks to "explain" / "teach me" / "walk me through" / "how does X work" \u2192 if the
|
|
29
|
+
\`beacon_explain\` MCP tool is available, author an interactive Lesson (a concept map +
|
|
30
|
+
plain-English narrative on /learn the user questions back) via the \`beacon-explain\` skill.
|
|
31
|
+
- Run \`beacon doctor\` to audit what's wired (global hooks, repo's .mcp.json, AGENTS.md block).
|
|
32
|
+
|
|
33
|
+
**The plan feedback loop**
|
|
34
|
+
\`beacon_propose_plan\` BLOCKS until the user clicks Approve / Discard / submits feedback.
|
|
35
|
+
Feedback bundles inline annotations on the markdown PLUS any edits the user made directly
|
|
36
|
+
on the /map and /db boards (added features, attached subtasks, edited columns, new
|
|
37
|
+
endpoints). Treat board edits as the user's revision intent \u2014 re-propose matching them
|
|
38
|
+
verbatim. Do NOT implement until the tool returns approval.`;var S=g(()=>{N=["beacon-init","beacon-refresh","beacon-plan","beacon-explain"]});var P1=1500,x1=480000,M1=1800000,qQ=3600000,w1=3000;var JZ=()=>{};var gQ={};wQ(gQ,{stripAgentsPointer:()=>zZ,repoMcpCliTarget:()=>IQ,removeRepoAssets:()=>X0,installRefreshSkill:()=>Z0,installPlanSkill:()=>$0,installInitSkill:()=>Q0,installExplainSkill:()=>J0,installCodexRepoSkills:()=>V0,ensureWorkflowDoc:()=>q0,ensureMcp:()=>z0,contextDocTargets:()=>CQ,auditRepo:()=>OQ,REFRESH_SKILL:()=>uQ,PLAN_SKILL:()=>VZ,INIT_SKILL:()=>fQ,EXPLAIN_SKILL:()=>qZ});import{existsSync as M,mkdirSync as h,readFileSync as w,rmSync as zQ,writeFileSync as B}from"fs";import{join as X}from"path";function Q0(Q){let Z=X(Q,".claude","skills","beacon-init");h(Z,{recursive:!0});let $=X(Z,"SKILL.md");return B($,fQ),$}function Z0(Q){let Z=X(Q,".claude","skills","beacon-refresh");h(Z,{recursive:!0});let $=X(Z,"SKILL.md");return B($,uQ),$}function $0(Q){let Z=X(Q,".claude","skills","beacon-plan");h(Z,{recursive:!0});let $=X(Z,"SKILL.md");return B($,VZ),$}function J0(Q){let Z=X(Q,".claude","skills","beacon-explain");h(Z,{recursive:!0});let $=X(Z,"SKILL.md");return B($,qZ),$}function V0(Q){let Z=[];for(let $ of Y0){let J=X(Q,".agents","skills",$.name);h(J,{recursive:!0});let Y=X(J,"SKILL.md");B(Y,$.body()),Z.push(Y)}return Z}function CQ(Q){let Z=X(Q,"AGENTS.md"),$=X(Q,"CLAUDE.md"),J=M(Z),Y=M($);if(!J&&!Y)return[Z,$];let V=[];if(J)V.push(Z);if(Y)V.push($);return V}function zZ(Q){let Z=X(Q,"CLAUDE.md");if(!M(Z))return;let $=w(Z,"utf8"),J=$.split(`
|
|
4
39
|
`).filter((Y)=>!/^\s*@\.?\/?AGENTS\.md\s*$/.test(Y)).join(`
|
|
5
|
-
`).trim();if(J&&J!==$.trim())
|
|
6
|
-
`)}function
|
|
40
|
+
`).trim();if(J&&J!==$.trim())B(Z,`${J}
|
|
41
|
+
`)}function q0(Q){let Z=new RegExp(`${XQ}[\\s\\S]*?${TQ}`);for(let $ of CQ(Q)){let J="";try{J=w($,"utf8")}catch{}J=Z.test(J)?J.replace(Z,YZ):`${J.trim()}
|
|
7
42
|
|
|
8
|
-
${
|
|
9
|
-
`.trimStart(),
|
|
43
|
+
${YZ}
|
|
44
|
+
`.trimStart(),B($,J.endsWith(`
|
|
10
45
|
`)?J:`${J}
|
|
11
|
-
`)}
|
|
12
|
-
`),{path:Z,added:!1,updated:!0};return{path:Z,added:!1,updated:!1}}return $.mcpServers.beacon={command:
|
|
13
|
-
`),{path:Z,added:!0,updated:!1}}function
|
|
14
|
-
`)}}catch{}let Y=!1,V=new RegExp(`\\n?${
|
|
46
|
+
`)}zZ(Q)}function z0(Q){let Z=X(Q,".mcp.json"),$={};try{$=JSON.parse(w(Z,"utf8"))}catch{}$.mcpServers=$.mcpServers??{};let J=$.mcpServers.beacon;if(J){if(!J.timeout||J.timeout<qQ)return J.timeout=qQ,B(Z,JSON.stringify($,null,2)+`
|
|
47
|
+
`),{path:Z,added:!1,updated:!0};return{path:Z,added:!1,updated:!1}}return $.mcpServers.beacon={command:x(),args:["mcp"],timeout:qQ},B(Z,JSON.stringify($,null,2)+`
|
|
48
|
+
`),{path:Z,added:!0,updated:!1}}function IQ(Q){try{return JSON.parse(w(X(Q,".mcp.json"),"utf8")).mcpServers?.beacon?.command??null}catch{return null}}function OQ(Q){let Z=X(Q,".mcp.json"),$=!1;try{$=!!JSON.parse(w(Z,"utf8")).mcpServers?.beacon}catch{}let J=CQ(Q).some((Y)=>{try{return w(Y,"utf8").includes(XQ)}catch{return!1}});return{repo:Q,mcpRegistered:$,workflowBlock:J,skills:{"beacon-init":M(X(Q,".claude","skills","beacon-init","SKILL.md")),"beacon-refresh":M(X(Q,".claude","skills","beacon-refresh","SKILL.md"))},codexSkills:{"beacon-init":M(X(Q,".agents","skills","beacon-init","SKILL.md")),"beacon-refresh":M(X(Q,".agents","skills","beacon-refresh","SKILL.md"))}}}function X0(Q){let Z=[];for(let q of["beacon-init","beacon-refresh","beacon-db-design"]){let U=X(Q,".claude","skills",q);if(M(U))zQ(U,{recursive:!0,force:!0}),Z.push(q)}for(let q of["beacon-init","beacon-refresh"]){let U=X(Q,".agents","skills",q);if(M(U))zQ(U,{recursive:!0,force:!0}),Z.push(`codex:${q}`)}let $=!1,J=X(Q,".mcp.json");try{let q=JSON.parse(w(J,"utf8"));if(q.mcpServers?.beacon){if(delete q.mcpServers.beacon,$=!0,q.mcpServers&&Object.keys(q.mcpServers).length===0)delete q.mcpServers;if(Object.keys(q).length===0)zQ(J,{force:!0});else B(J,JSON.stringify(q,null,2)+`
|
|
49
|
+
`)}}catch{}let Y=!1,V=new RegExp(`\\n?${XQ}[\\s\\S]*?${TQ}\\n?`);for(let q of[X(Q,"AGENTS.md"),X(Q,"CLAUDE.md")])try{let U=w(q,"utf8");if(V.test(U)){let MQ=U.replace(V,`
|
|
15
50
|
`).replace(/\n{3,}/g,`
|
|
16
51
|
|
|
17
|
-
`).trimStart();
|
|
18
|
-
`)?
|
|
19
|
-
`),Y=!0}}catch{}let
|
|
52
|
+
`).trimStart();B(q,MQ.endsWith(`
|
|
53
|
+
`)?MQ:`${MQ}
|
|
54
|
+
`),Y=!0}}catch{}let z=!1,H=X(Q,"CLAUDE.md");try{let q=w(H,"utf8"),U=q.replace(/^[ \t]*@AGENTS\.md[ \t]*\n?/m,"");if(U!==q){if(!U.trim())zQ(H,{force:!0});else B(H,U);z=!0}}catch{}return{skillsRemoved:Z,mcpUnregistered:$,agentsBlockRemoved:Y,claudeImportRemoved:z}}var fQ=`---
|
|
20
55
|
name: beacon-init
|
|
21
56
|
description: Read this repository and map its architecture, schema, and roadmap into Beacon (the local visual planning panel). Use when the user runs /beacon-init, asks to "set up Beacon for this repo", or asks to initialize/bootstrap Beacon's map of this codebase.
|
|
22
57
|
---
|
|
@@ -63,7 +98,7 @@ beacon init-persist /tmp/beacon-init.json # or: beacon init-persist < /tmp/bea
|
|
|
63
98
|
That one command wires the repo (writes \`.mcp.json\` + skills so your NEXT session gets the \`beacon_*\` tools natively, heals the global install), starts the Beacon daemon if it isn't running, registers + provisions this workspace, and POSTs your analysis to the same \`/api/init\` endpoint the MCP tool uses \u2014 so init completes in THIS session. Read the counts it prints and report them.
|
|
64
99
|
|
|
65
100
|
After the tool (or \`beacon init-persist\`) returns, tell the user the counts (components / roadmap / tables / endpoints) and point them at the running Beacon panel.
|
|
66
|
-
`,
|
|
101
|
+
`,uQ=`---
|
|
67
102
|
name: beacon-refresh
|
|
68
103
|
description: Re-survey the repo and update Beacon's architecture / schema / endpoints map after /beacon-init was already run \u2014 picks up new components, removed ones, schema changes, and new routes. Use when the user runs /beacon-refresh or asks to "refresh", "update", "re-sync", or "bring Beacon up to date" with the current code.
|
|
69
104
|
---
|
|
@@ -110,7 +145,7 @@ The one caveat: if the user manually edited an INIT-source node on the canvas (e
|
|
|
110
145
|
If \`beacon_entities\` or \`beacon_init_persist\` isn't available, the Beacon panel isn't running in this repo. Tell the user to run \`beacon\` here first, then re-invoke /beacon-refresh.
|
|
111
146
|
|
|
112
147
|
After the tool returns, report the final counts plus a one-line summary of the diff you surfaced.
|
|
113
|
-
`,
|
|
148
|
+
`,VZ=`---
|
|
114
149
|
name: beacon-plan
|
|
115
150
|
description: Present your current plan or approach to the user on Beacon's /plan canvas for review \u2014 instead of asking for approval in prose. Use when the user says "present the plan", "show me the plan", "let me see it / the plan", or whenever you are about to end a turn asking whether to proceed with a plan, design, or approach.
|
|
116
151
|
---
|
|
@@ -159,7 +194,7 @@ If it returns feedback, revise and call it again.
|
|
|
159
194
|
If \`beacon_present_plan\` isn't available, the panel isn't wired here \u2014 fall back to ExitPlanMode
|
|
160
195
|
with the same \`\`\`beacon block (Claude Code only; Codex has no ExitPlanMode), or tell the user to
|
|
161
196
|
run \`beacon\` in this repo once.
|
|
162
|
-
`,
|
|
197
|
+
`,qZ=`---
|
|
163
198
|
name: beacon-explain
|
|
164
199
|
description: Teach the user part of THIS codebase as an interactive visual lesson on Beacon's /learn page \u2014 a concept map + plain-English narrative they can question \u2014 instead of a wall of text. Use when the user says "explain", "teach me", "walk me through", "how does X work", or "help me understand the Y category".
|
|
165
200
|
---
|
|
@@ -229,7 +264,7 @@ so the learner sees the table IN CONTEXT, wired to the code that uses it.
|
|
|
229
264
|
Every answer must ADD understanding (rationale, trade-off) \u2014 never just restate the question. Expand
|
|
230
265
|
the narrative or add nodes where it helps. Keep looping until the tool reports the user saved or closed
|
|
231
266
|
the lesson.
|
|
232
|
-
`,
|
|
267
|
+
`,Y0,XQ="<!-- beacon:workflow:start -->",TQ="<!-- beacon:workflow:end -->",YZ;var UQ=g(()=>{S();JZ();Y0=[{name:"beacon-init",body:()=>fQ},{name:"beacon-refresh",body:()=>uQ}];YZ=`${XQ}
|
|
233
268
|
## Beacon \u2014 feature workflow
|
|
234
269
|
|
|
235
270
|
This project uses Beacon (a local planning/visualization panel; run \`beacon\` to open it). When you start work on a FEATURE \u2014 whether referenced via an \`@beacon:feature://\u2026\` mention, an \`@beacon:note://\u2026\` note the user wrote in the Notes panel (treat its checkbox \`- [ ]\` todos as subtasks and order features by their dependencies), or just described in chat \u2014 follow these steps in order:
|
|
@@ -301,54 +336,20 @@ Register them all in that single batched call. If a plan added five features, th
|
|
|
301
336
|
If the feature added or materially changed a REAL architectural component (a subsystem \u2014 NOT a file), also pass \`architecture: [{ title, domain, role, \u2026 }]\` so the Architecture map stays accurate. It upserts curated components by title; never list files as components. If you found a bug or something worth investigating in a component's code, add \`bugs: [{ note }]\` to its architecture entry \u2014 it renders as a bug flag on the node (attributed to the agent); identical open flags are not duplicated. Only flag what you actually saw in the code.
|
|
302
337
|
|
|
303
338
|
Pull raw planning data anytime with \`beacon_entities\` (features / architecture / tables / endpoints).
|
|
304
|
-
${
|
|
305
|
-
`)
|
|
306
|
-
${J.trim()}
|
|
307
|
-
${$}`,V="";try{V=R(Q,"utf8")}catch{}let q=new RegExp(`${Z}[\\s\\S]*?${$}`);V=q.test(V)?V.replace(q,Y):V.trim()?`${V.trim()}
|
|
308
|
-
|
|
309
|
-
${Y}
|
|
310
|
-
`:`${Y}
|
|
311
|
-
`,MQ(aQ(Q),{recursive:!0}),n(Q,V.endsWith(`
|
|
312
|
-
`)?V:`${V}
|
|
313
|
-
`)}function O(Q,Z){try{return R(Q,"utf8").includes(Z)}catch{return!1}}function i(Q,Z,$){let J="";try{J=R(Q,"utf8")}catch{return!1}let Y=new RegExp(`${Z}[\\s\\S]*?${$}\\n?`);if(!Y.test(J))return!1;let V=J.replace(Y,"").replace(/\n{3,}/g,`
|
|
314
|
-
|
|
315
|
-
`).trimStart();return n(Q,V),!0}function e(Q,Z,$){let J=M(Q,Z);MQ(J,{recursive:!0});let Y=M(J,"SKILL.md");return n(Y,$),Y}function y(Q,Z){return l(M(Q,Z,"SKILL.md"))}function QQ(Q,Z){let $=M(Q,Z);if(!l($))return!1;return cZ($,{recursive:!0,force:!0}),!0}var v,t=`## Beacon (visual planning panel)
|
|
316
|
-
|
|
317
|
-
This machine has Beacon installed \u2014 a local visual planning surface for the terminal-side
|
|
318
|
-
agent. Beacon proposes feature plans (roadmap features + DB schema + endpoints) via MCP,
|
|
319
|
-
the user reviews on a canvas at /plan, and feedback flows back as the next round.
|
|
320
|
-
|
|
321
|
-
**When to invoke**
|
|
322
|
-
- User asks to "plan a feature" / "design a schema" \u2192 if the \`beacon_propose_plan\`
|
|
323
|
-
MCP tool is available, design the plan and call it. If it is NOT available, the panel
|
|
324
|
-
isn't wired in this repo \u2014 run \`beacon\` here once, then retry.
|
|
325
|
-
- User asks to "set up Beacon" / "map this repo" \u2192 invoke the \`beacon-init\` skill.
|
|
326
|
-
- User asks to "refresh Beacon" / "update the map" / "bring Beacon up to date" \u2192 invoke
|
|
327
|
-
the \`beacon-refresh\` skill. Re-surveys the repo and updates init-derived nodes while
|
|
328
|
-
preserving anything the user added by hand.
|
|
329
|
-
- User asks to "explain" / "teach me" / "walk me through" / "how does X work" \u2192 if the
|
|
330
|
-
\`beacon_explain\` MCP tool is available, author an interactive Lesson (a concept map +
|
|
331
|
-
plain-English narrative on /learn the user questions back) via the \`beacon-explain\` skill.
|
|
332
|
-
- Run \`beacon doctor\` to audit what's wired (global hooks, repo's .mcp.json, AGENTS.md block).
|
|
333
|
-
|
|
334
|
-
**The plan feedback loop**
|
|
335
|
-
\`beacon_propose_plan\` BLOCKS until the user clicks Approve / Discard / submits feedback.
|
|
336
|
-
Feedback bundles inline annotations on the markdown PLUS any edits the user made directly
|
|
337
|
-
on the /map and /db boards (added features, attached subtasks, edited columns, new
|
|
338
|
-
endpoints). Treat board edits as the user's revision intent \u2014 re-propose matching them
|
|
339
|
-
verbatim. Do NOT implement until the tool returns approval.`;var fQ=F(()=>{v=["beacon-init","beacon-refresh","beacon-plan","beacon-explain"]});import{mkdirSync as sZ,renameSync as tZ,rmSync as aZ,writeFileSync as dZ}from"fs";import{dirname as rZ}from"path";function ZQ(Q,Z){sZ(rZ(Q),{recursive:!0});let $=`${Q}.tmp`;try{dZ($,Z),tZ($,Q)}catch(J){throw aZ($,{force:!0}),J}}function q1(Q,Z,$=!1){ZQ(Q,JSON.stringify(Z,null,$?2:void 0))}var iQ=()=>{};var VZ={};BQ(VZ,{setupCodexAssets:()=>eZ,removeCodexMcp:()=>YZ,removeCodexArtifacts:()=>Q0,hasCodexMcp:()=>RQ,ensureCodexMcp:()=>JZ,codexMcpProblem:()=>gQ,codexDetected:()=>zQ,auditCodex:()=>EQ,CODEX_HOOKS:()=>T});import{readFileSync as VQ}from"fs";import{homedir as oZ}from"os";import{join as k}from"path";function eQ(){return process.env.HOME||process.env.USERPROFILE||oZ()}function zQ(){if(process.env.BEACON_CODEX==="1")return!0;if(process.env.BEACON_CODEX==="0")return!1;if(TQ===void 0)TQ=Bun.which("codex")!==null;return TQ}function b(Q){try{return Bun.TOML.parse(Q)}catch{return null}}function RQ(){try{return Boolean(b(VQ(g(),"utf8"))?.mcp_servers?.beacon)}catch{return!1}}function gQ(){let Q="";try{Q=VQ(g(),"utf8")}catch{return null}let Z=b(Q);if(!Z)return`~/.codex/config.toml does not parse \u2014 ${A}`;if(Z.mcp_servers?.beacon)return null;if(/^\s*mcp_servers\s*=/m.test(Q))return`mcp_servers is an inline table \u2014 ${A}`;return null}function JZ(){let Q="",Z=!1;try{Q=VQ(g(),"utf8"),Z=!0}catch{}if(Z){let V=b(Q);if(!V)return{added:!1,error:`~/.codex/config.toml does not parse \u2014 ${A}`};if(V.mcp_servers?.beacon)return{added:!1};if(/^\s*mcp_servers\s*=/m.test(Q))return{added:!1,error:`mcp_servers is an inline table \u2014 ${A}`}}let $=!Q?"":Q.endsWith(`
|
|
339
|
+
${TQ}`});import{mkdirSync as U0,renameSync as W0,rmSync as H0,writeFileSync as j0}from"fs";import{dirname as v0}from"path";function WQ(Q,Z){U0(v0(Q),{recursive:!0});let $=`${Q}.tmp`;try{j0($,Z),W0($,Q)}catch(J){throw H0($,{force:!0}),J}}function O1(Q,Z,$=!1){WQ(Q,JSON.stringify(Z,null,$?2:void 0))}var XZ=()=>{};var PZ={};wQ(PZ,{setupCodexAssets:()=>M0,removeCodexMcp:()=>KZ,removeCodexArtifacts:()=>w0,parseTomlBeacon:()=>GZ,nodeWhich:()=>HZ,hasCodexMcp:()=>yQ,ensureCodexMcp:()=>BZ,commandExists:()=>jZ,codexMcpProblem:()=>bQ,codexMcpCliTarget:()=>kQ,codexDetected:()=>c,auditCodex:()=>_Q,CODEX_HOOKS:()=>C});import{accessSync as N0,constants as G0,readFileSync as m}from"fs";import{homedir as B0}from"os";import{delimiter as K0,join as A}from"path";function UZ(){return process.env.HOME||process.env.USERPROFILE||B0()}function HZ(Q,Z=process.env.PATH||"",$=P0){if(!Q)return null;for(let J of Z.split(K0)){if(!J)continue;let Y=A(J,Q);if($(Y))return Y}return null}function P0(Q){try{return N0(Q,G0.X_OK),!0}catch{return!1}}function jZ(Q){if(typeof Bun<"u"&&typeof Bun.which==="function")return Bun.which(Q)!==null;return HZ(Q)!==null}function c(){if(process.env.BEACON_CODEX==="1")return!0;if(process.env.BEACON_CODEX==="0")return!1;if(EQ===void 0)EQ=jZ("codex");return EQ}function GZ(Q){let Z={},$=!1;for(let J of Q.split(`
|
|
340
|
+
`)){let Y=J.trim();if(!Y||Y.startsWith("#"))continue;let V=/^\[([^\]]+)\]/.exec(Y);if(V){if($=V[1].trim()==="mcp_servers.beacon",$)Z.mcp_servers=Z.mcp_servers??{},Z.mcp_servers.beacon=Z.mcp_servers.beacon??{};continue}if($){let z=/^command\s*=\s*["']([^"']*)["']/.exec(Y);if(z)Z.mcp_servers.beacon.command=z[1]}}return Z}function D(Q){try{if(typeof Bun<"u"&&Bun.TOML?.parse)return Bun.TOML.parse(Q);return GZ(Q)}catch{return null}}function yQ(){try{return Boolean(D(m(T(),"utf8"))?.mcp_servers?.beacon)}catch{return!1}}function bQ(){let Q="";try{Q=m(T(),"utf8")}catch{return null}let Z=D(Q);if(!Z)return`~/.codex/config.toml does not parse \u2014 ${p}`;if(Z.mcp_servers?.beacon)return null;if(/^\s*mcp_servers\s*=/m.test(Q))return`mcp_servers is an inline table \u2014 ${p}`;return null}function BZ(){let Q="",Z=!1;try{Q=m(T(),"utf8"),Z=!0}catch{}if(Z){let V=D(Q);if(!V)return{added:!1,error:`~/.codex/config.toml does not parse \u2014 ${p}`};if(V.mcp_servers?.beacon)return{added:!1};if(/^\s*mcp_servers\s*=/m.test(Q))return{added:!1,error:`mcp_servers is an inline table \u2014 ${p}`}}let $=!Q?"":Q.endsWith(`
|
|
340
341
|
`)?`
|
|
341
342
|
`:`
|
|
342
343
|
|
|
343
|
-
`,J=Q+$+
|
|
344
|
-
`),$=Z.indexOf(
|
|
344
|
+
`,J=Q+$+x0();if(D(J)?.mcp_servers?.beacon?.command!==x())return{added:!1,error:`could not safely append [mcp_servers.beacon] \u2014 ${p}`};return WQ(T(),J),{added:!0}}function kQ(){try{return D(m(T(),"utf8"))?.mcp_servers?.beacon?.command??null}catch{return null}}function KZ(){let Q="";try{Q=m(T(),"utf8")}catch{return{removed:!1}}let Z=Q.split(`
|
|
345
|
+
`),$=Z.indexOf(vZ);if($===-1)return{removed:!1,skipped:yQ()};let J=Z.indexOf(NZ,$);if(J===-1)return{removed:!1,skipped:!0};Z.splice($,J-$+1);let Y=Z.join(`
|
|
345
346
|
`).replace(/\n{3,}/g,`
|
|
346
347
|
|
|
347
|
-
`).replace(/^\n+/,"");if(
|
|
348
|
+
`).replace(/^\n+/,"");if(D(Y)===null)return{removed:!1,skipped:!0};return WQ(T(),Y),{removed:!0}}async function M0(){let{INIT_SKILL:Q,REFRESH_SKILL:Z,PLAN_SKILL:$,EXPLAIN_SKILL:J}=await Promise.resolve().then(() => (UQ(),gQ)),Y={"beacon-init":Q,"beacon-refresh":Z,"beacon-plan":$,"beacon-explain":J},V=[];for(let U of N){if(!L(jQ(),U))V.push(U);YQ(jQ(),U,Y[U])}let z=0;for(let U of C)if(e(AQ(),{event:U.event,matcher:U.matcher,command:a(U.command)}))z++;let H=_(HQ(),vQ);$Q(HQ(),vQ,WZ,o);let q=BZ();return{skillsAdded:V,hooksAdded:z,agentsMdBlockTouched:!H,mcp:q}}function _Q(){let Q={};for(let $ of N)Q[$]=L(jQ(),$);let Z={};for(let $ of C)Z[$.event]=QQ(AQ(),{event:$.event,command:$.command});return{detected:c(),skills:Q,hooks:Z,agentsMdBlock:_(HQ(),vQ),mcp:yQ()}}function w0(){let Q=[];for(let Y of N)if(VQ(jQ(),Y))Q.push(Y);let Z=0;for(let Y of C)if(ZQ(AQ(),{event:Y.event,command:Y.command}))Z++;let $=JQ(HQ(),vQ,WZ),J=KZ();return{skillsRemoved:Q,hooksRemoved:Z,agentsMdBlockRemoved:$,mcpRemoved:J.removed,mcpSkipped:J.skipped}}var DQ=()=>A(UZ(),".codex"),AQ=()=>A(DQ(),"hooks.json"),T=()=>A(DQ(),"config.toml"),HQ=()=>A(DQ(),"AGENTS.md"),jQ=()=>A(UZ(),".agents","skills"),vQ="<!-- beacon:global:start -->",WZ="<!-- beacon:global:end -->",C,EQ,vZ="# beacon:start (managed by Beacon \u2014 `beacon uninstall` removes this block)",NZ="# beacon:end",x0=()=>`${vZ}
|
|
348
349
|
[mcp_servers.beacon]
|
|
349
|
-
command = "
|
|
350
|
+
command = "${x()}"
|
|
350
351
|
args = ["mcp"]
|
|
351
|
-
${
|
|
352
|
-
`});var HZ={};BQ(HZ,{provisionDb:()=>u0});import{createClient as B0}from"@libsql/client";import{drizzle as N0}from"drizzle-orm/libsql";import{migrate as G0}from"drizzle-orm/libsql/migrator";import{readMigrationFiles as P0}from"drizzle-orm/migrator";import{dirname as bQ,join as K0}from"path";import{fileURLToPath as x0}from"url";async function UQ(Q,Z){return(await Q.execute({sql:"SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?",args:[Z]})).rows.length>0}async function f0(Q,Z){let $=await Q.execute(`PRAGMA table_info("${Z}")`);return new Set($.rows.map((J)=>String(J.name)))}async function WZ(Q){if(!await UQ(Q,"__drizzle_migrations"))return 0;let Z=await Q.execute('SELECT count(*) AS n FROM "__drizzle_migrations"');return Number(Z.rows[0]?.n??0)}async function T0(Q){for(let[Z,$]of Object.entries(w0)){if(!await UQ(Q,Z))continue;let J=await f0(Q,Z);for(let Y of $){if(!J.has(Y))continue;await Q.execute(`UPDATE "${Z}" SET "${Y}" = CAST((julianday("${Y}") - 2440587.5) * 86400000 AS INTEGER) WHERE typeof("${Y}") = 'text'`)}}}async function u0(Q,Z=M0){let $=B0({url:Q});try{await $.execute("PRAGMA journal_mode = WAL;"),await $.execute("PRAGMA foreign_keys = ON;"),await $.execute("PRAGMA busy_timeout = 5000;");let J=await UQ($,"__drizzle_migrations"),Y=await UQ($,"Node"),V=!1;if(Y&&!J){let H=P0({migrationsFolder:Z})[0];if(H)await $.execute('CREATE TABLE IF NOT EXISTS "__drizzle_migrations" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)'),await $.execute({sql:'INSERT INTO "__drizzle_migrations" ("hash", "created_at") VALUES (?, ?)',args:[H.hash,H.folderMillis]}),V=!0}let q=await WZ($);if(await G0(N0($),{migrationsFolder:Z}),await WZ($)>q)V=!0;return await T0($),{migrated:V}}finally{$.close()}}var C0,M0,w0;var jZ=F(async()=>{C0=bQ(bQ(bQ(x0(import.meta.url)))),M0=process.env.BEACON_MIGRATIONS_DIR||K0(C0,"drizzle"),w0={Node:["createdAt","updatedAt"],Note:["createdAt","updatedAt"],DbTable:["createdAt","updatedAt"],Endpoint:["createdAt","updatedAt"],DraftTable:["createdAt"],SyncState:["codeGraphSyncedAt","updatedAt"],AppSetting:["updatedAt"],ProjectMeta:["updatedAt"],CodeFile:["updatedAt"]}});fQ();import{existsSync as Z0}from"fs";import{homedir as $0}from"os";import{join as qQ}from"path";function J0(){return process.env.HOME||process.env.USERPROFILE||$0()}var XQ=()=>qQ(J0(),".claude"),DQ=()=>qQ(XQ(),"skills"),OQ=()=>qQ(XQ(),"settings.json"),yQ=()=>qQ(XQ(),"CLAUDE.md"),AQ="<!-- beacon:global:start -->",zZ="<!-- beacon:global:end -->";var Y0=t,E=[{event:"PreToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon guard",description:"Gate edits against the active plan's scope contract: in-scope \u2192 allow, off-scope \u2192 ask the user to authorize. Fail-open when there's no active contract."},{event:"PostToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"PermissionRequest",matcher:"ExitPlanMode",command:"beacon plan",description:"Pipe the agent's plan markdown into Beacon's /plan canvas for review."},{event:"PreToolUse",matcher:"AskUserQuestion",command:"beacon ask",description:"Surface the agent's AskUserQuestion in Beacon's modal; your pick flows back as the answer (falls through to the terminal if Beacon isn't open)."},{event:"PermissionRequest",matcher:"Edit|Write|MultiEdit|Bash|NotebookEdit",command:"beacon ask",description:"Surface edit/create/run approvals in Beacon's modal; your allow/deny flows back (falls through to the terminal prompt if Beacon isn't open)."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose (instead of presenting it), nudge it to present the plan on Beacon's /plan canvas. Bounded by stop_hook_active \u2014 at most one nudge."}];function V0(Q,Z){return e(DQ(),Q,Z)}function qZ(Q){return y(DQ(),Q)}function z0(Q){return QQ(DQ(),Q)}function q0(Q){return a(OQ(),Q)}function X0(Q){return d(OQ(),Q)}function U0(Q){return r(OQ(),Q)}function W0(Q){o(yQ(),AQ,zZ,Q)}function XZ(){return O(yQ(),AQ)}function H0(){return i(yQ(),AQ,zZ)}function UZ(){let Q={};for(let $ of v)Q[$]=qZ($);let Z={};for(let $ of E)Z[$.event]=X0({event:$.event,command:$.command});return{homeExists:Z0(XQ()),skills:Q,hooks:Z,claudeMdBlock:XZ()}}async function j0(){let{INIT_SKILL:Q,REFRESH_SKILL:Z,PLAN_SKILL:$,EXPLAIN_SKILL:J}=await Promise.resolve().then(() => (c(),CQ)),Y={"beacon-init":Q,"beacon-refresh":Z,"beacon-plan":$,"beacon-explain":J},V=[];for(let z of v){if(!qZ(z))V.push(z);V0(z,Y[z])}let q=0;for(let z of E)if(q0({event:z.event,matcher:z.matcher,command:z.command}))q++;let H=XZ();return W0(Y0),{skillsAdded:V,hooksAdded:q,claudeMdBlockTouched:!H}}async function K1(){if(dQ())return{ok:!0,skipped:"plugin",skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1};let Q;if(rQ()){try{v0()}catch{}Q={ok:!0,skipped:"plugin-present",skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}else try{Q={ok:!0,...await j0()}}catch(Z){Q={ok:!1,error:Z instanceof Error?Z.message:String(Z),skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}try{let Z=await Promise.resolve().then(() => (IQ(),VZ));if(Z.codexDetected())Q.codex={ok:!0,...await Z.setupCodexAssets()}}catch(Z){Q.codex={ok:!1,error:Z instanceof Error?Z.message:String(Z),skillsAdded:[],hooksAdded:0,agentsMdBlockTouched:!1,mcp:{added:!1}}}return Q}function v0(){let Q=[];for(let J of v)if(z0(J))Q.push(J);let Z=0;for(let J of E)if(U0(J))Z++;let $=H0();return{skillsRemoved:Q,hooksRemoved:Z,claudeMdBlockRemoved:$}}import{AsyncLocalStorage as F0}from"async_hooks";import{spawnSync as R0}from"child_process";import{createHash as g0}from"crypto";import{existsSync as BZ,mkdirSync as L,readFileSync as _Q,writeFileSync as LQ}from"fs";import{homedir as NZ}from"os";import{basename as E0,join as w,parse as I0,resolve as vZ}from"path";function P(){return process.env.BEACON_HOME||w(NZ(),".beacon")}function SQ(){return w(P(),"workspaces.json")}function _(Q){return g0("sha256").update(Q).digest("hex").slice(0,12)}function D0(Q=process.cwd()){let Z=R0("git",["rev-parse","--show-toplevel"],{cwd:Q,stdio:["ignore","pipe","ignore"]});if(Z.status===0){let $=Z.stdout?.toString().trim();if($)return $}return Q}function GZ(Q){let Z=vZ(Q);return Z!==vZ(NZ())&&Z!==I0(Z).root}function PZ(){return w(P(),"deleted.json")}function mQ(){try{let Q=JSON.parse(_Q(PZ(),"utf8"));return Array.isArray(Q)?Q:[]}catch{return[]}}function KZ(Q){L(P(),{recursive:!0}),LQ(PZ(),JSON.stringify(Q,null,2))}function xZ(Q){return mQ().includes(Q)}function O1(Q){let Z=mQ();if(!Z.includes(Q))KZ([...Z,Q])}function O0(Q){let Z=mQ();if(Z.includes(Q))KZ(Z.filter(($)=>$!==Q))}function WQ(Q){return w(P(),Q)}function y0(Q){return`file:${w(WQ(Q),"db.sqlite")}`}function S(){try{let Q=JSON.parse(_Q(SQ(),"utf8"));return Array.isArray(Q)?Q:[]}catch{return[]}}function hQ(Q){L(P(),{recursive:!0}),LQ(SQ(),JSON.stringify(Q,null,2))}function HQ(){return S().sort((Q,Z)=>Z.lastOpenedAt.localeCompare(Q.lastOpenedAt))}function u(Q){return S().find((Z)=>Z.id===Q)??null}function CZ(Q,Z,$=new Date().toISOString()){if(!GZ(Q))throw Error(`beacon: refusing to register a non-repo path as a workspace: ${Q}`);let J=_(Q);if(xZ(J))throw Error(`beacon: workspace ${J} (${Q}) was deleted \u2014 run \`beacon\` or /beacon-init to re-add it`);let Y=S(),V=Y.find((z)=>z.id===J),q={id:J,path:Q,name:Z||V?.name||E0(Q),lastOpenedAt:$},H=[q,...Y.filter((z)=>z.id!==J)];return L(WQ(J),{recursive:!0}),hQ(H),q}function y1(Q,Z){return O0(_(Q)),CZ(Q,Z)}function A1(Q,Z=new Date().toISOString()){let $=S(),J=$.find((Y)=>Y.id===Q);if(!J)return;J.lastOpenedAt=Z,hQ($)}function b1(Q){if(hQ(S().filter((Z)=>Z.id!==Q)),pQ()===Q)A0(HQ()[0]?.id??null)}function MZ(){return w(P(),"active")}function pQ(){try{return _Q(MZ(),"utf8").trim()||null}catch{return null}}function A0(Q){L(P(),{recursive:!0}),LQ(MZ(),Q??"")}function k1(){let Q=pQ();return Q?u(Q):null}function _1(){let Q=k0()??pQ();return Q?u(Q):null}function L1(Q){return u(Q)?.path??null}function S1(){return BZ(SQ())}var wZ="beacon_ws";function fZ(Q,Z){let $=Q.headers.get("cookie");if(!$)return null;for(let J of $.split(";")){let Y=J.indexOf("=");if(Y===-1)continue;if(J.slice(0,Y).trim()===Z)return decodeURIComponent(J.slice(Y+1).trim())}return null}function m1(Q){let Z=Q.headers.get("x-beacon-workspace");if(Z&&u(Z))return Z;let $=fZ(Q,wZ);if($&&u($))return $;return b0()}function b0(){let Q=HQ();return Q.length===1?Q[0].id:null}var TZ="x-beacon-workspace-path";function h1(Q=process.cwd()){let Z=D0(Q);return{"x-beacon-workspace":_(Z),[TZ]:Z}}async function p1(Q){let Z=Q.headers.get("x-beacon-workspace");if(Z&&u(Z))return Z;let $=Q.headers.get(TZ);if($&&GZ($)&&!xZ(_($))&&(!Z||_($)===Z)){let Y=CZ($);return await _0(Y.id),Y.id}let J=fZ(Q,wZ);if(J&&u(J))return J;return null}var uZ=new F0;function c1(Q,Z){return Q?uZ.run(Q,Z):Z()}function k0(){return uZ.getStore()??null}var kQ=new Set;function l1(Q){kQ.delete(w(WQ(Q),"db.sqlite"))}async function _0(Q){let Z=WQ(Q),$=w(Z,"db.sqlite"),J=BZ($);if(J&&kQ.has($))return{ok:!0,created:!1,migrated:!1};try{L(Z,{recursive:!0});let{provisionDb:Y}=await jZ().then(() => HZ),V=await Y(y0(Q));return kQ.add($),{ok:!0,created:!J,migrated:J&&V.migrated}}catch(Y){return{ok:!1,created:!1,migrated:!1,error:Y instanceof Error?Y.message:String(Y)}}}c();IQ();import{execSync as L0,spawnSync as RZ}from"child_process";import{existsSync as S0,readFileSync as m0}from"fs";import{join as gZ}from"path";var W=(Q)=>`\x1B[32m\u2713\x1B[0m ${Q}`,j=(Q)=>`\x1B[31m\u2717\x1B[0m ${Q}`,K=(Q)=>`\x1B[2m${Q}\x1B[0m`,I=(Q)=>`
|
|
353
|
-
\x1B[1m${Q}\x1B[0m`;function
|
|
354
|
-
${
|
|
352
|
+
${NZ}
|
|
353
|
+
`,p="add it manually: codex mcp add beacon -- beacon mcp";var LQ=g(()=>{S();XZ();C=[{event:"PostToolUse",matcher:"apply_patch",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose, nudge it to present the plan on Beacon's /plan canvas."}]});var uZ={};wQ(uZ,{provisionDb:()=>t0});import{createClient as b0}from"@libsql/client";import{drizzle as k0}from"drizzle-orm/libsql";import{migrate as _0}from"drizzle-orm/libsql/migrator";import{readMigrationFiles as L0}from"drizzle-orm/migrator";import{dirname as mQ,join as S0}from"path";import{fileURLToPath as h0}from"url";async function KQ(Q,Z){return(await Q.execute({sql:"SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?",args:[Z]})).rows.length>0}async function s0(Q,Z){let $=await Q.execute(`PRAGMA table_info("${Z}")`);return new Set($.rows.map((J)=>String(J.name)))}async function fZ(Q){if(!await KQ(Q,"__drizzle_migrations"))return 0;let Z=await Q.execute('SELECT count(*) AS n FROM "__drizzle_migrations"');return Number(Z.rows[0]?.n??0)}async function l0(Q){for(let[Z,$]of Object.entries(c0)){if(!await KQ(Q,Z))continue;let J=await s0(Q,Z);for(let Y of $){if(!J.has(Y))continue;await Q.execute(`UPDATE "${Z}" SET "${Y}" = CAST((julianday("${Y}") - 2440587.5) * 86400000 AS INTEGER) WHERE typeof("${Y}") = 'text'`)}}}async function t0(Q,Z=m0){let $=b0({url:Q});try{await $.execute("PRAGMA journal_mode = WAL;"),await $.execute("PRAGMA foreign_keys = ON;"),await $.execute("PRAGMA busy_timeout = 5000;");let J=await KQ($,"__drizzle_migrations"),Y=await KQ($,"Node"),V=!1;if(Y&&!J){let H=L0({migrationsFolder:Z})[0];if(H)await $.execute('CREATE TABLE IF NOT EXISTS "__drizzle_migrations" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)'),await $.execute({sql:'INSERT INTO "__drizzle_migrations" ("hash", "created_at") VALUES (?, ?)',args:[H.hash,H.folderMillis]}),V=!0}let z=await fZ($);if(await _0(k0($),{migrationsFolder:Z}),await fZ($)>z)V=!0;return await l0($),{migrated:V}}finally{$.close()}}var p0,m0,c0;var TZ=g(async()=>{p0=mQ(mQ(mQ(h0(import.meta.url)))),m0=process.env.BEACON_MIGRATIONS_DIR||S0(p0,"drizzle"),c0={Node:["createdAt","updatedAt"],Note:["createdAt","updatedAt"],DbTable:["createdAt","updatedAt"],Endpoint:["createdAt","updatedAt"],DraftTable:["createdAt"],SyncState:["codeGraphSyncedAt","updatedAt"],AppSetting:["updatedAt"],ProjectMeta:["updatedAt"],CodeFile:["updatedAt"]}});S();import{existsSync as R0}from"fs";import{homedir as F0}from"os";import{join as NQ}from"path";function f0(){return process.env.HOME||process.env.USERPROFILE||F0()}var GQ=()=>NQ(f0(),".claude"),SQ=()=>NQ(GQ(),"skills"),BQ=()=>NQ(GQ(),"settings.json"),hQ=()=>NQ(GQ(),"CLAUDE.md"),pQ="<!-- beacon:global:start -->",xZ="<!-- beacon:global:end -->";var u0=o,y=[{event:"PreToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon guard",description:"Gate edits against the active plan's scope contract: in-scope \u2192 allow, off-scope \u2192 ask the user to authorize. Fail-open when there's no active contract."},{event:"PostToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"PermissionRequest",matcher:"ExitPlanMode",command:"beacon plan",description:"Pipe the agent's plan markdown into Beacon's /plan canvas for review."},{event:"PreToolUse",matcher:"AskUserQuestion",command:"beacon ask",description:"Surface the agent's AskUserQuestion in Beacon's modal; your pick flows back as the answer (falls through to the terminal if Beacon isn't open)."},{event:"PermissionRequest",matcher:"Edit|Write|MultiEdit|Bash|NotebookEdit",command:"beacon ask",description:"Surface edit/create/run approvals in Beacon's modal; your allow/deny flows back (falls through to the terminal prompt if Beacon isn't open)."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose (instead of presenting it), nudge it to present the plan on Beacon's /plan canvas. Bounded by stop_hook_active \u2014 at most one nudge."}];function T0(Q,Z){return YQ(SQ(),Q,Z)}function MZ(Q){return L(SQ(),Q)}function C0(Q){return VQ(SQ(),Q)}function I0(Q){return e(BQ(),Q)}function O0(Q){return QQ(BQ(),Q)}function g0(Q){return ZQ(BQ(),Q)}function E0(Q){$Q(hQ(),pQ,xZ,Q)}function wZ(){return _(hQ(),pQ)}function D0(){return JQ(hQ(),pQ,xZ)}function RZ(){let Q={};for(let $ of N)Q[$]=MZ($);let Z={};for(let $ of y)Z[$.event]=O0({event:$.event,command:$.command});return{homeExists:R0(GQ()),skills:Q,hooks:Z,claudeMdBlock:wZ()}}function FZ(){let Q=$Z(BQ(),{event:"PostToolUse",command:"beacon hook"});return Q?FQ(Q):null}async function A0(){let{INIT_SKILL:Q,REFRESH_SKILL:Z,PLAN_SKILL:$,EXPLAIN_SKILL:J}=await Promise.resolve().then(() => (UQ(),gQ)),Y={"beacon-init":Q,"beacon-refresh":Z,"beacon-plan":$,"beacon-explain":J},V=[];for(let q of N){if(!MZ(q))V.push(q);T0(q,Y[q])}let z=0;for(let q of y)if(I0({event:q.event,matcher:q.matcher,command:a(q.command)}))z++;let H=wZ();return E0(u0),{skillsAdded:V,hooksAdded:z,claudeMdBlockTouched:!H}}async function h1(){if(eQ())return{ok:!0,skipped:"plugin",skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1};let Q;if(QZ()){try{y0()}catch{}Q={ok:!0,skipped:"plugin-present",skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}else try{Q={ok:!0,...await A0()}}catch(Z){Q={ok:!1,error:Z instanceof Error?Z.message:String(Z),skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}try{let Z=await Promise.resolve().then(() => (LQ(),PZ));if(Z.codexDetected())Q.codex={ok:!0,...await Z.setupCodexAssets()}}catch(Z){Q.codex={ok:!1,error:Z instanceof Error?Z.message:String(Z),skillsAdded:[],hooksAdded:0,agentsMdBlockTouched:!1,mcp:{added:!1}}}return Q}function y0(){let Q=[];for(let J of N)if(C0(J))Q.push(J);let Z=0;for(let J of y)if(g0(J))Z++;let $=D0();return{skillsRemoved:Q,hooksRemoved:Z,claudeMdBlockRemoved:$}}import{AsyncLocalStorage as n0}from"async_hooks";import{spawnSync as r0}from"child_process";import{createHash as d0}from"crypto";import{existsSync as IZ,mkdirSync as l,readFileSync as sQ,writeFileSync as lQ}from"fs";import{homedir as OZ}from"os";import{basename as a0,join as f,parse as o0,resolve as CZ}from"path";function P(){return process.env.BEACON_HOME||f(OZ(),".beacon")}function tQ(){return f(P(),"workspaces.json")}function s(Q){return d0("sha256").update(Q).digest("hex").slice(0,12)}function i0(Q=process.cwd()){let Z=r0("git",["rev-parse","--show-toplevel"],{cwd:Q,stdio:["ignore","pipe","ignore"]});if(Z.status===0){let $=Z.stdout?.toString().trim();if($)return $}return Q}function gZ(Q){let Z=CZ(Q);return Z!==CZ(OZ())&&Z!==o0(Z).root}function EZ(){return f(P(),"deleted.json")}function nQ(){try{let Q=JSON.parse(sQ(EZ(),"utf8"));return Array.isArray(Q)?Q:[]}catch{return[]}}function DZ(Q){l(P(),{recursive:!0}),lQ(EZ(),JSON.stringify(Q,null,2))}function AZ(Q){return nQ().includes(Q)}function Q2(Q){let Z=nQ();if(!Z.includes(Q))DZ([...Z,Q])}function e0(Q){let Z=nQ();if(Z.includes(Q))DZ(Z.filter(($)=>$!==Q))}function PQ(Q){return f(P(),Q)}function Q1(Q){return`file:${f(PQ(Q),"db.sqlite")}`}function t(){try{let Q=JSON.parse(sQ(tQ(),"utf8"));return Array.isArray(Q)?Q:[]}catch{return[]}}function rQ(Q){l(P(),{recursive:!0}),lQ(tQ(),JSON.stringify(Q,null,2))}function xQ(){return t().sort((Q,Z)=>Z.lastOpenedAt.localeCompare(Q.lastOpenedAt))}function I(Q){return t().find((Z)=>Z.id===Q)??null}function yZ(Q,Z,$=new Date().toISOString()){if(!gZ(Q))throw Error(`beacon: refusing to register a non-repo path as a workspace: ${Q}`);let J=s(Q);if(AZ(J))throw Error(`beacon: workspace ${J} (${Q}) was deleted \u2014 run \`beacon\` or /beacon-init to re-add it`);let Y=t(),V=Y.find((q)=>q.id===J),z={id:J,path:Q,name:Z||V?.name||a0(Q),lastOpenedAt:$},H=[z,...Y.filter((q)=>q.id!==J)];return l(PQ(J),{recursive:!0}),rQ(H),z}function Z2(Q,Z){return e0(s(Q)),yZ(Q,Z)}function $2(Q,Z=new Date().toISOString()){let $=t(),J=$.find((Y)=>Y.id===Q);if(!J)return;J.lastOpenedAt=Z,rQ($)}function J2(Q){if(rQ(t().filter((Z)=>Z.id!==Q)),dQ()===Q)Z1(xQ()[0]?.id??null)}function bZ(){return f(P(),"active")}function dQ(){try{return sQ(bZ(),"utf8").trim()||null}catch{return null}}function Z1(Q){l(P(),{recursive:!0}),lQ(bZ(),Q??"")}function Y2(){let Q=dQ();return Q?I(Q):null}function V2(){let Q=J1()??dQ();return Q?I(Q):null}function q2(Q){return I(Q)?.path??null}function z2(){return IZ(tQ())}var kZ="beacon_ws";function _Z(Q,Z){let $=Q.headers.get("cookie");if(!$)return null;for(let J of $.split(";")){let Y=J.indexOf("=");if(Y===-1)continue;if(J.slice(0,Y).trim()===Z)return decodeURIComponent(J.slice(Y+1).trim())}return null}function X2(Q){let Z=Q.headers.get("x-beacon-workspace");if(Z&&I(Z))return Z;let $=_Z(Q,kZ);if($&&I($))return $;return $1()}function $1(){let Q=xQ();return Q.length===1?Q[0].id:null}var LZ="x-beacon-workspace-path";function U2(Q=process.cwd()){let Z=i0(Q);return{"x-beacon-workspace":s(Z),[LZ]:Z}}async function W2(Q){let Z=Q.headers.get("x-beacon-workspace");if(Z&&I(Z))return Z;let $=Q.headers.get(LZ);if($&&gZ($)&&!AZ(s($))&&(!Z||s($)===Z)){let Y=yZ($);return await Y1(Y.id),Y.id}let J=_Z(Q,kZ);if(J&&I(J))return J;return null}var SZ=new n0;function H2(Q,Z){return Q?SZ.run(Q,Z):Z()}function J1(){return SZ.getStore()??null}var cQ=new Set;function j2(Q){cQ.delete(f(PQ(Q),"db.sqlite"))}async function Y1(Q){let Z=PQ(Q),$=f(Z,"db.sqlite"),J=IZ($);if(J&&cQ.has($))return{ok:!0,created:!1,migrated:!1};try{l(Z,{recursive:!0});let{provisionDb:Y}=await TZ().then(() => uZ),V=await Y(Q1(Q));return cQ.add($),{ok:!0,created:!J,migrated:J&&V.migrated}}catch(Y){return{ok:!1,created:!1,migrated:!1,error:Y instanceof Error?Y.message:String(Y)}}}S();UQ();LQ();import{execSync as V1,spawnSync as pZ}from"child_process";import{existsSync as mZ,readFileSync as q1}from"fs";import{join as cZ}from"path";var W=(Q)=>`\x1B[32m\u2713\x1B[0m ${Q}`,j=(Q)=>`\x1B[31m\u2717\x1B[0m ${Q}`,G=(Q)=>`\x1B[2m${Q}\x1B[0m`,O=(Q)=>`
|
|
354
|
+
\x1B[1m${Q}\x1B[0m`;function z1(){try{return V1("git rev-parse --show-toplevel",{cwd:process.cwd(),stdio:["ignore","pipe","ignore"]}).toString().trim()}catch{return""}}function X1(){let Q=cZ(P(),"server.json");try{let Z=JSON.parse(q1(Q,"utf8"));if(!Z.pid)return j("daemon: no server.json yet");try{return process.kill(Z.pid,0),W(`daemon running (pid ${Z.pid}, port ${Z.port??"?"})`)}catch{return j(`daemon NOT running (server.json stale: pid ${Z.pid})`)}}catch{return j("daemon: no server.json (never started)")}}function U1(){let Q=pZ("bun",["--version"],{stdio:["ignore","pipe","ignore"]});if(Q.status===0)return W(`bun ${Q.stdout.toString().trim()}`);return j("bun NOT found on PATH (required to run Beacon)")}function W1(){return z1()||process.cwd()}var b=W1(),u=RZ(),sZ=xQ(),H1=sZ.some((Q)=>Q.path===b),v=H1||mZ(cZ(b,".mcp.json"))?OQ(b):null;console.log(O("Beacon \xB7 doctor"));console.log(O("Runtime"));console.log(` ${U1()}`);console.log(` ${X1()}`);console.log(` ${W(`home: ${P()}`)}`);console.log(` ${W(`workspaces registered: ${sZ.length}`)}`);console.log(O("Global (~/.claude/)"));for(let Q of N)console.log(` ${u.skills[Q]?W(`skill ${Q}`):j(`skill ${Q} \u2014 missing`)}`);for(let Q of y)console.log(` ${u.hooks[Q.event]?W(`hook ${Q.event} \u2192 ${Q.command}`):j(`hook ${Q.event} \u2192 ${Q.command} \u2014 missing`)} ${G(Q.description)}`);console.log(` ${u.claudeMdBlock?W("global CLAUDE.md block"):j("global CLAUDE.md block \u2014 missing (every Claude session won't auto-discover Beacon)")}`);console.log(O("Plugin (Claude Code)"));var hZ=d();if(hZ)if(console.log(` ${W(`installed as a Claude Code plugin \u2192 ${hZ}`)}`),console.log(` ${G("the plugin owns the Claude-side skills/hooks/MCP")}`),u.hooks.PostToolUse||N.some((Q)=>u.skills[Q]))console.log(` ${G("npm-global ~/.claude entries still present \u2014 they'll be removed automatically on the next `beacon` run (run `beacon` once to deconflict now).")}`);else console.log(` ${W("npm-global ~/.claude layer stepped aside \u2014 no double-registration")}`);else console.log(` ${G("not installed as a Claude Code plugin (using the npm `trybeacon` CLI).")}`);console.log(O("Codex (~/.codex/ + ~/.agents/)"));var K=c()?_Q():null;if(!K)console.log(` ${G("codex not on PATH \u2014 Codex integration inactive (wires automatically once codex is installed)")}`);else{let Q=pZ("codex",["--version"],{stdio:["ignore","pipe","ignore"]});console.log(` ${Q.status===0?W(`codex ${Q.stdout.toString().trim()}`):G("codex version unavailable (BEACON_CODEX override?)")}`);for(let $ of N)console.log(` ${K.skills[$]?W(`skill ${$} (~/.agents/skills)`):j(`skill ${$} (~/.agents/skills) \u2014 missing`)}`);for(let $ of C)console.log(` ${K.hooks[$.event]?W(`hook ${$.event} \u2192 ${$.command}`):j(`hook ${$.event} \u2192 ${$.command} \u2014 missing`)} ${G($.description)}`);console.log(` ${K.agentsMdBlock?W("global ~/.codex/AGENTS.md block"):j("global ~/.codex/AGENTS.md block \u2014 missing")}`);let Z=bQ();console.log(` ${K.mcp?W("config.toml has [mcp_servers.beacon]"):j(`config.toml missing [mcp_servers.beacon]${Z?` \u2014 ${Z}`:""}`)}`)}console.log(O("CLI binding"));var aQ=x(),j1=mZ(n);console.log(` ${W(`fresh installs resolve to: ${aQ}`)} ${G(process.env.BEACON_CLI_PATH?"(BEACON_CLI_PATH override)":j1?"(Beacon.app installed)":"(npm PATH shim)")}`);var oQ=[["~/.claude/settings.json hooks",FZ()]];if(c())oQ.push(["~/.codex/config.toml MCP",kQ()]);if(v)oQ.push([`${b}/.mcp.json`,IQ(b)]);var lZ=!1;for(let[Q,Z]of oQ){if(!Z){console.log(` ${G(`${Q}: not wired`)}`);continue}if(Z===aQ)console.log(` ${W(`${Q} \u2192 ${Z}`)}`);else lZ=!0,console.log(` ${j(`${Q} \u2192 ${Z} \u2014 MISMATCH (fresh installs would use ${aQ})`)}`)}if(lZ)console.log(` ${G("re-point the configs with")} \x1B[1mbeacon uninstall && beacon\x1B[0m ${G("(uninstall clears the old entries regardless of binary; the next `beacon` rewrites them at the resolved path).")}`);console.log(O(`Current repo (${b})`));if(!v)console.log(` ${G("not registered with Beacon and no .mcp.json \u2014 run `beacon` here to wire it.")}`);else if(console.log(` ${v.mcpRegistered?W(".mcp.json has beacon entry"):j(".mcp.json missing beacon entry")}`),console.log(` ${v.workflowBlock?W("AGENTS.md / CLAUDE.md has Beacon workflow block"):j("AGENTS.md / CLAUDE.md missing Beacon workflow block")}`),console.log(` ${v.skills["beacon-init"]?W("skill beacon-init (repo)"):j("skill beacon-init (repo) \u2014 missing")}`),console.log(` ${v.skills["beacon-refresh"]?W("skill beacon-refresh (repo)"):j("skill beacon-refresh (repo) \u2014 missing")}`),K)console.log(` ${v.codexSkills["beacon-init"]?W("skill beacon-init (.agents/skills)"):j("skill beacon-init (.agents/skills) \u2014 missing")}`),console.log(` ${v.codexSkills["beacon-refresh"]?W("skill beacon-refresh (.agents/skills)"):j("skill beacon-refresh (.agents/skills) \u2014 missing")}`);var v1=N.some((Q)=>!u.skills[Q])||y.some((Q)=>!u.hooks[Q.event])||!u.claudeMdBlock||(K?N.some((Q)=>!K.skills[Q])||C.some((Q)=>!K.hooks[Q.event])||!K.agentsMdBlock||!K.mcp:!1)||(v?!v.mcpRegistered||!v.workflowBlock||!v.skills["beacon-init"]||!v.skills["beacon-refresh"]||(K?!v.codexSkills["beacon-init"]||!v.codexSkills["beacon-refresh"]:!1):!1);if(v1)console.log(`
|
|
355
|
+
${G("Fix everything marked \u2717 by running")} \x1B[1mbeacon\x1B[0m ${G("in this repo.")}`);console.log();
|