bridge-agent 0.4.5 → 0.4.7
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/bridge-mcp.cjs +43 -1
- package/dist/index.js +1 -1
- package/dist/scripts/install-sim-prereqs.sh +0 -0
- package/package.json +10 -9
package/dist/bridge-mcp.cjs
CHANGED
|
@@ -22387,6 +22387,21 @@ async function sendAgentInput(ctx, agentId, text) {
|
|
|
22387
22387
|
async function getAgentIdle(ctx, agentId) {
|
|
22388
22388
|
return request(ctx, "GET", projectPath(ctx, `/agents/${agentId}/idle`));
|
|
22389
22389
|
}
|
|
22390
|
+
async function recordProjectEvent(ctx, params) {
|
|
22391
|
+
return request(ctx, "POST", projectPath(ctx, "/events"), { ...params, agentId: ctx.agentId });
|
|
22392
|
+
}
|
|
22393
|
+
async function getProjectEvents(ctx, opts) {
|
|
22394
|
+
const params = new URLSearchParams();
|
|
22395
|
+
if (opts?.role) params.set("role", opts.role);
|
|
22396
|
+
if (opts?.eventType) params.set("eventType", opts.eventType);
|
|
22397
|
+
if (opts?.tags) params.set("tags", opts.tags);
|
|
22398
|
+
if (opts?.since) params.set("since", opts.since);
|
|
22399
|
+
if (opts?.search) params.set("search", opts.search);
|
|
22400
|
+
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
22401
|
+
if (opts?.includeArchived) params.set("includeArchived", "true");
|
|
22402
|
+
const qs = params.toString();
|
|
22403
|
+
return request(ctx, "GET", projectPath(ctx, `/events${qs ? "?" + qs : ""}`));
|
|
22404
|
+
}
|
|
22390
22405
|
|
|
22391
22406
|
// ../mcp-server/src/tools/plan.ts
|
|
22392
22407
|
function registerPlanTools(server, ctx) {
|
|
@@ -22607,7 +22622,7 @@ function registerOrchestrationTools(server, ctx) {
|
|
|
22607
22622
|
);
|
|
22608
22623
|
server.tool(
|
|
22609
22624
|
"bridge_send_input",
|
|
22610
|
-
`Send text input to a panel's PTY. The daemon appends the correct line terminator automatically (sh \u2192 \\n, claude/qwen \u2192 \\r) \u2014 do NOT add \\n or \\r yourself. Use to: run shell commands, trigger hot reload ("r" in Flutter), send prompts to AI panels, interact with CLIs.`,
|
|
22625
|
+
`Send text input to a panel's PTY. The daemon appends the correct line terminator automatically (sh \u2192 \\n, claude/qwen \u2192 \\r) \u2014 do NOT add \\n or \\r yourself. Use to: run shell commands, trigger hot reload ("r" in Flutter), send prompts to AI panels, interact with CLIs. If the agent is mid-output, returns { ok: false, error: "agent_not_idle", lastOutputAgeMs } with 409 \u2014 poll bridge_agent_is_idle before retrying.`,
|
|
22611
22626
|
{
|
|
22612
22627
|
agentId: external_exports.string().describe("The agent ID to send to"),
|
|
22613
22628
|
text: external_exports.string().min(1).max(4096).describe("Text to send. No line terminator needed \u2014 daemon adds it.")
|
|
@@ -22637,6 +22652,33 @@ function registerOrchestrationTools(server, ctx) {
|
|
|
22637
22652
|
{ agentId: external_exports.string().describe("The agent ID to inspect") },
|
|
22638
22653
|
({ agentId }) => safe(() => getAgentIdle(ctx, agentId))
|
|
22639
22654
|
);
|
|
22655
|
+
server.tool(
|
|
22656
|
+
"bridge_record_event",
|
|
22657
|
+
"Append an event to the project event log. Use to record decisions, discoveries, phase completions, or blockers so future agents and runs have durable context. Events are separate from run history \u2014 they persist across runs and are queryable by role/type/tag. Suggested eventTypes: decision, discovery, blocker, phase_complete, note, warning.",
|
|
22658
|
+
{
|
|
22659
|
+
eventType: external_exports.string().min(1).max(64).describe("Free-form event type slug (e.g. decision, blocker, phase_complete)"),
|
|
22660
|
+
summary: external_exports.string().min(1).max(512).describe("Human-readable event summary (max 512 chars)"),
|
|
22661
|
+
sessionId: external_exports.string().optional().describe("Orchestration session ID this event belongs to, if any"),
|
|
22662
|
+
payload: external_exports.record(external_exports.unknown()).optional().describe("Optional structured data attached to the event"),
|
|
22663
|
+
tags: external_exports.array(external_exports.string()).optional().describe('Free-form tags for filtering (e.g. ["auth", "security"])'),
|
|
22664
|
+
permanent: external_exports.boolean().optional().describe("Mark event as permanent \u2014 excluded from future archiving sweeps")
|
|
22665
|
+
},
|
|
22666
|
+
(params) => safe(() => recordProjectEvent(ctx, params))
|
|
22667
|
+
);
|
|
22668
|
+
server.tool(
|
|
22669
|
+
"bridge_get_project_events",
|
|
22670
|
+
"Query the project event log. Returns events newest-first. Use to recall decisions, discoveries, and blockers recorded by prior agents before starting new work. Filter by role or eventType to narrow results; use search for keyword lookup in summaries.",
|
|
22671
|
+
{
|
|
22672
|
+
role: external_exports.string().optional().describe("Filter by role (e.g. reviewer, developer)"),
|
|
22673
|
+
eventType: external_exports.string().optional().describe("Filter by eventType slug"),
|
|
22674
|
+
tags: external_exports.string().optional().describe('Comma-separated tag list \u2014 only events containing ALL listed tags (e.g. "auth,security")'),
|
|
22675
|
+
since: external_exports.string().optional().describe("ISO 8601 timestamp \u2014 only events after this date"),
|
|
22676
|
+
search: external_exports.string().optional().describe("Keyword search in event summaries (case-insensitive)"),
|
|
22677
|
+
limit: external_exports.number().int().min(1).max(200).optional().describe("Max events to return (default 50, max 200)"),
|
|
22678
|
+
includeArchived: external_exports.boolean().optional().describe("Include soft-archived events (default false)")
|
|
22679
|
+
},
|
|
22680
|
+
(opts) => safe(() => getProjectEvents(ctx, opts))
|
|
22681
|
+
);
|
|
22640
22682
|
}
|
|
22641
22683
|
|
|
22642
22684
|
// ../mcp-server/src/tools/messaging.ts
|
package/dist/index.js
CHANGED
|
@@ -419,4 +419,4 @@ ${a} </dict>
|
|
|
419
419
|
</plist>
|
|
420
420
|
`;try{return(0,T.writeFileSync)(t,f,"utf-8"),!0}catch(p){return console.warn("[bridge] launchd.plist.write.failed",{error:String(p)}),!1}}function mc(){let r=ke(),e=j.default.join(Nt,r);try{return(0,ue.execSync)(`launchctl kickstart -kp gui/$(id -u)/${r} 2>/dev/null; launchctl unload "${e}" 2>/dev/null; launchctl load "${e}"`,{stdio:"pipe"}),{ok:!0,permissionDenied:!1}}catch(t){let n=String(t);return{ok:!1,permissionDenied:n.includes("Permission denied")||n.includes("not allowed")||n.includes("bootstrap")}}}function _c(r){let{out:e,err:t}=It();try{let n=(0,ue.spawn)(r,["start"],{detached:!0,stdio:"ignore",env:{...process.env,PATH:ni(),BRIDGE_DAEMON:"1"}});n.unref(),setTimeout(()=>{n.pid&&process.kill(n.pid,0)?(console.log("[bridge] daemon.pid",{pid:n.pid}),console.log("[bridge] background.ok",{log:e})):console.error("[bridge] background.failed \u2014 check: tail -f",{log:t})},2e3)}catch(n){console.error("[bridge] background.spawn.failed",{error:String(n)})}}function yc(){let r=parseInt(process.env.HEALTH_PORT??"3101",10),e=Date.now()+6e3,t=()=>{if(Date.now()>e){console.error("[bridge] health.verify.timeout \u2014 daemon may have crashed immediately");return}try{let s=require("node:http").get(`http://127.0.0.1:${r}/health`,i=>{i.statusCode===200?console.log("[bridge] health.verify.ok"):setTimeout(t,500)});s.on("error",()=>{setTimeout(t,500)}),s.setTimeout(1e3,()=>{s.destroy(),setTimeout(t,500)})}catch{setTimeout(t,500)}};setTimeout(t,1e3)}function bc(){ri();let r=new at;ei(r),r.startLivenessCheck(6e4);let e=parseInt(process.env.HEALTH_PORT??"3101",10),t=(0,ti.createServer)((n,s)=>{let i=Zs(),o=JSON.stringify({status:"ok",connected:i,uptime:process.uptime()});s.writeHead(i?200:503,{"Content-Type":"application/json"}),s.end(o)});t.listen(e,"127.0.0.1",()=>{console.log(`[bridge] health. listening on 127.0.0.1:${e}`)}),t.on("error",n=>{console.error("[bridge] health.error",{error:n.message})})}function si(){let r=process.env.BRIDGE_DAEMON==="1"||process.argv.includes("--daemon");if(!r&&!process.env.BRIDGE_PROFILE){let a=process.argv[1]??"";(a.includes("packages/daemon/dist")||a.includes("packages/daemon/src"))&&(console.warn("[bridge] WARNING: running monorepo daemon without --profile \u2014 will use prod config (~/.jerico/settings.json)."),console.warn("[bridge] If this is unintentional, stop and rerun with: node packages/daemon/dist/index.js --profile dev start"))}if(console.log("[bridge] Starting bridge-agent daemon..."),r){bc();return}fc()||(console.warn("[bridge] start.aborted.already.running"),process.exit(1));let e=pc(),t=gc(e),{ok:n,permissionDenied:s}=t?mc():{ok:!1,permissionDenied:!1},i=j.default.join(Nt,ke()),{out:o,err:c}=It();if(n){console.log("[bridge] launchd.ok \u2014 managed, auto-restart enabled"),console.log("[bridge] logs: tail -f",{out:o,err:c}),yc(),process.exit(0);return}s&&(console.warn("[bridge] launchd.permission.denied"),console.warn("[bridge] \u2192 Auto-start on login requires:"),console.warn(`[bridge] sudo launchctl bootstrap gui/$(id -u) "${i}"`),console.warn(`[bridge] Falling back to background process...
|
|
421
421
|
`)),_c(e),process.exit(0)}var ii=y(require("https")),oi=y(require("http"));xe();var wc="https://lcars.jerico.appnova.io";function Sc(r){return(r??"").trim()}async function ai(r,e=!1,t){let n=!(r&&r.trim()),s=n?wc:r.trim();console.log("[bridge] Starting auth flow..."),console.log(`[bridge] Server: ${s}${n?" (default)":""}`),console.log("[bridge] Open this URL to generate a daemon token:"),console.log(` ${s}/connect`);let i=Sc(t);i&&console.log("[bridge] Using token from --token"),e&&(i?console.log("[bridge] --no-browser ignored because --token is provided."):(console.log("[bridge] --no-browser: exiting after printing URL."),process.exit(0)));let o=i;o||(console.log(),console.log("[bridge] After authenticating, paste your token here:"),o=await vc()),o||(console.error("[bridge] No token provided. Exiting."),process.exit(1)),await Ec(s,o)||(console.error("[bridge] Token validation failed. Please try again."),process.exit(1));let l=s.replace(/^https?:\/\//,d=>d.startsWith("https")?"wss://":"ws://").replace(/\/?$/,"/ws/daemon");le({server:l,token:o,name:process.env.HOSTNAME??"My Machine"}),console.log("[bridge] Auth successful! Config saved to ~/.bridge/config.json"),console.log("[bridge] Run: bridge-agent start"),process.exit(0)}async function vc(){return new Promise(r=>{process.stdout.write("Token: ");let e="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",t=>{e+=t,e.includes(`
|
|
422
|
-
`)&&(process.stdin.pause(),r(e.trim()))}),process.stdin.resume()})}async function Ec(r,e){return new Promise(t=>{let n=new URL("/api/tokens/validate",r),s=n.protocol==="https:",i=s?ii.default:oi.default,o={hostname:n.hostname,port:n.port||(s?443:80),path:n.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}},c=i.request(o,a=>{t(a.statusCode===200)});c.on("error",()=>t(!1)),c.end()})}var ci=y(require("https")),li=y(require("http")),Lr=y(require("fs")),Mr=y(require("path")),di=require("node:crypto");xe();function kc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function ui(r,e,t){let n=ce(),s=(0,di.createHash)("sha256").update(n.token).digest("hex"),i=kc(n.server),o=Mr.default.resolve(t);Mr.default.isAbsolute(o)||(console.error("[bridge] link-project: path must be absolute"),process.exit(1)),Lr.default.existsSync(o)||(console.error("[bridge] link-project: path does not exist:",o),process.exit(1)),Lr.default.statSync(o).isDirectory()||(console.error("[bridge] link-project: path must be a directory:",o),process.exit(1));let a=new URL(`/api/workspaces/${r}/projects/${e}/machine-paths`,i),l=a.protocol==="https:",d=l?ci.default:li.default;n.projectPaths={...n.projectPaths??{},[e]:o},le(n),console.log("[cli] link-project.local_json_written",{projectId:e,path:o});let u=JSON.stringify({daemonId:s,localPath:o,machineFingerprint:jr()}),f=await new Promise((p,g)=>{let h=d.request({hostname:a.hostname,port:a.port||(l?443:80),path:a.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"Content-Length":Buffer.byteLength(u)}},m=>{let k="";m.on("data",v=>{k+=v}),m.on("end",()=>{if(m.statusCode===200)p(200);else{try{let v=JSON.parse(k);console.error("[bridge] link-project failed:",v.error??`HTTP ${m.statusCode}`)}catch{console.error("[bridge] link-project failed:",`HTTP ${m.statusCode}`)}p(m.statusCode??0)}})});h.on("error",m=>{g(m)}),h.write(u),h.end()});f===200?(console.log("[cli] link-project.server_success",{projectId:e}),console.log("[cli] link-project.success (dual-write)"),console.log(` workspace: ${r}`),console.log(` project: ${e}`),console.log(` daemon: ${s.slice(0,16)}\u2026`),console.log(` path: ${o}`),console.log("[cli] Next spawn for this project will use the linked path."),process.exit(0)):(console.warn("[cli] link-project.server_fail",{projectId:e,statusCode:f}),console.log("[cli] Local override still active \u2014 path will work on this machine"),process.exit(0))}xe();function xc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function hi(){let r=ce(),e=xc(r.server),t=await fetch(`${e}/api/admin/cleanup-orphans`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:"{}"});t.ok||(console.error(`[cli] cleanup-orphans: HTTP ${t.status}`),process.exit(1));let{deleted:n}=await t.json();console.log(`[cli] cleanup-orphans: deleted ${n} orphaned path ${n===1?"entry":"entries"}`),process.exit(0)}var $r=require("node:child_process"),tt=require("node:fs"),Br=y(require("path"));qe();var pi=require("node:os"),Ic=Br.default.join((0,pi.homedir)(),"Library","LaunchAgents");function fi(){let r=ke(),e=r.replace(".plist",""),t=Br.default.join(Ic,r);try{(0,$r.execSync)(`launchctl bootout gui/$(id -u)/${e}`,{stdio:"pipe"}),console.log("[bridge] launchd.stopped \u2014 daemon unloaded")}catch{try{(0,tt.existsSync)(t)?((0,$r.execSync)(`launchctl unload "${t}"`,{stdio:"pipe"}),console.log("[bridge] launchd.unloaded \u2014 daemon stopped")):console.warn("[bridge] launchd.stop.failed \u2014 plist not found, daemon may not be running via launchd")}catch{console.warn("[bridge] launchd.stop.failed \u2014 daemon may not be running via launchd"),console.warn(`[bridge] Manual: launchctl bootout gui/$(id -u)/${e}`)}}let n=Ge();if((0,tt.existsSync)(n))try{(0,tt.unlinkSync)(n),console.log("[bridge] lock.cleaned")}catch{}}var ee=new tn;ee.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.4.
|
|
422
|
+
`)&&(process.stdin.pause(),r(e.trim()))}),process.stdin.resume()})}async function Ec(r,e){return new Promise(t=>{let n=new URL("/api/tokens/validate",r),s=n.protocol==="https:",i=s?ii.default:oi.default,o={hostname:n.hostname,port:n.port||(s?443:80),path:n.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}},c=i.request(o,a=>{t(a.statusCode===200)});c.on("error",()=>t(!1)),c.end()})}var ci=y(require("https")),li=y(require("http")),Lr=y(require("fs")),Mr=y(require("path")),di=require("node:crypto");xe();function kc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function ui(r,e,t){let n=ce(),s=(0,di.createHash)("sha256").update(n.token).digest("hex"),i=kc(n.server),o=Mr.default.resolve(t);Mr.default.isAbsolute(o)||(console.error("[bridge] link-project: path must be absolute"),process.exit(1)),Lr.default.existsSync(o)||(console.error("[bridge] link-project: path does not exist:",o),process.exit(1)),Lr.default.statSync(o).isDirectory()||(console.error("[bridge] link-project: path must be a directory:",o),process.exit(1));let a=new URL(`/api/workspaces/${r}/projects/${e}/machine-paths`,i),l=a.protocol==="https:",d=l?ci.default:li.default;n.projectPaths={...n.projectPaths??{},[e]:o},le(n),console.log("[cli] link-project.local_json_written",{projectId:e,path:o});let u=JSON.stringify({daemonId:s,localPath:o,machineFingerprint:jr()}),f=await new Promise((p,g)=>{let h=d.request({hostname:a.hostname,port:a.port||(l?443:80),path:a.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"Content-Length":Buffer.byteLength(u)}},m=>{let k="";m.on("data",v=>{k+=v}),m.on("end",()=>{if(m.statusCode===200)p(200);else{try{let v=JSON.parse(k);console.error("[bridge] link-project failed:",v.error??`HTTP ${m.statusCode}`)}catch{console.error("[bridge] link-project failed:",`HTTP ${m.statusCode}`)}p(m.statusCode??0)}})});h.on("error",m=>{g(m)}),h.write(u),h.end()});f===200?(console.log("[cli] link-project.server_success",{projectId:e}),console.log("[cli] link-project.success (dual-write)"),console.log(` workspace: ${r}`),console.log(` project: ${e}`),console.log(` daemon: ${s.slice(0,16)}\u2026`),console.log(` path: ${o}`),console.log("[cli] Next spawn for this project will use the linked path."),process.exit(0)):(console.warn("[cli] link-project.server_fail",{projectId:e,statusCode:f}),console.log("[cli] Local override still active \u2014 path will work on this machine"),process.exit(0))}xe();function xc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function hi(){let r=ce(),e=xc(r.server),t=await fetch(`${e}/api/admin/cleanup-orphans`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:"{}"});t.ok||(console.error(`[cli] cleanup-orphans: HTTP ${t.status}`),process.exit(1));let{deleted:n}=await t.json();console.log(`[cli] cleanup-orphans: deleted ${n} orphaned path ${n===1?"entry":"entries"}`),process.exit(0)}var $r=require("node:child_process"),tt=require("node:fs"),Br=y(require("path"));qe();var pi=require("node:os"),Ic=Br.default.join((0,pi.homedir)(),"Library","LaunchAgents");function fi(){let r=ke(),e=r.replace(".plist",""),t=Br.default.join(Ic,r);try{(0,$r.execSync)(`launchctl bootout gui/$(id -u)/${e}`,{stdio:"pipe"}),console.log("[bridge] launchd.stopped \u2014 daemon unloaded")}catch{try{(0,tt.existsSync)(t)?((0,$r.execSync)(`launchctl unload "${t}"`,{stdio:"pipe"}),console.log("[bridge] launchd.unloaded \u2014 daemon stopped")):console.warn("[bridge] launchd.stop.failed \u2014 plist not found, daemon may not be running via launchd")}catch{console.warn("[bridge] launchd.stop.failed \u2014 daemon may not be running via launchd"),console.warn(`[bridge] Manual: launchctl bootout gui/$(id -u)/${e}`)}}let n=Ge();if((0,tt.existsSync)(n))try{(0,tt.unlinkSync)(n),console.log("[bridge] lock.cleaned")}catch{}}var ee=new tn;ee.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.4.7").option("--profile <name>","Config profile name (e.g. dev). Isolates config, lock, and fingerprint from the default prod profile.").hook("preAction",r=>{let e=r.opts().profile;e&&(process.env.BRIDGE_PROFILE=e)});ee.command("start").description("Start the bridge-agent daemon").option("--health-port <port>","Health check HTTP port (default: 3101, or 3101+offset per profile)").action(r=>{r.healthPort&&(process.env.HEALTH_PORT=r.healthPort),si()});ee.command("auth").description("Authenticate with Bridge server").option("-s, --server <url>","Server URL (default: https://lcars.jerico.appnova.io)").option("-t, --token <token>","Use token non-interactively").option("--no-browser","Print auth URL without opening browser or interactive prompt").action(r=>{ai(r.server,!r.browser,r.token)});ee.command("link-project <workspace-id> <project-id> <local-path>").description("Link a local directory to a project for this machine (Issue #152)").action((r,e,t)=>{ui(r,e,t)});ee.command("cleanup-orphans").description("Remove orphaned daemon_project_paths rows for this user").action(()=>{hi()});ee.command("status").description("Show connection status").action(async()=>{try{let{loadConfig:r}=await Promise.resolve().then(()=>(xe(),Us)),e=r();console.log("[bridge] Config found"),console.log(" Server:",e.server),console.log(" Name:",e.name)}catch{console.log("[bridge] Not authenticated. Run: bridge-agent auth")}});ee.command("stop").description("Stop the bridge-agent daemon").action(()=>{fi()});ee.parse();
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bridge-agent",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "Bridge local agent — connects your AI tools to Jerico",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
"engines": {
|
|
20
20
|
"node": ">=20"
|
|
21
21
|
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc --noEmit && node scripts/build.mjs",
|
|
24
|
+
"dev": "tsc --watch",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"postinstall": "node scripts/postinstall.mjs"
|
|
28
|
+
},
|
|
22
29
|
"keywords": [
|
|
23
30
|
"jerico",
|
|
24
31
|
"bridge",
|
|
@@ -48,12 +55,6 @@
|
|
|
48
55
|
"typescript": "^5.4.0",
|
|
49
56
|
"which": "^4.0.0",
|
|
50
57
|
"ws": "^8.17.0",
|
|
51
|
-
"@jerico/shared": "
|
|
52
|
-
},
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build": "tsc --noEmit && node scripts/build.mjs",
|
|
55
|
-
"dev": "tsc --watch",
|
|
56
|
-
"typecheck": "tsc --noEmit",
|
|
57
|
-
"postinstall": "node scripts/postinstall.mjs"
|
|
58
|
+
"@jerico/shared": "workspace:*"
|
|
58
59
|
}
|
|
59
|
-
}
|
|
60
|
+
}
|