prjct-cli 3.83.0 → 3.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import{connect}from"node:net";import{existsSync}from"node:fs";import{createHash,randomUUID}from"node:crypto";import{homedir}from"node:os";import{join,resolve}from"node:path";
2
+ import{connect}from"node:net";import{existsSync}from"node:fs";import{createHash,randomUUID}from"node:crypto";import{homedir}from"node:os";import{join,resolve}from"node:path";import{spawn}from"node:child_process";
3
3
  const cliHome=process.env.PRJCT_CLI_HOME?resolve(process.env.PRJCT_CLI_HOME):join(homedir(),".prjct-cli");
4
4
  const namedPipe=process.platform==="win32";
5
5
  const sockPath=namedPipe?"\\.\pipe\prjct-"+createHash("sha1").update(resolve(cliHome)).digest("hex").slice(0,16)+"-daemon":join(cliHome,"run","daemon.sock");
6
6
  const hasEndpoint=()=>namedPipe||existsSync(sockPath);
7
7
  const args=process.argv.slice(2);
8
8
  const cmd=args.find(a=>!a.startsWith("-"));
9
- const skip=new Set(["seed","mcp","install","help","start","setup","login","logout","auth","context","update","uninstall","daemon","stop","restart","upgrade","hook","hooks","claude","crew","harness","doctor","watch","version","prefs","retro","health","skill-adherence","review-risk","context-save","context-restore","-h","--help","-v","--version","intent","spec","audit-spec","dev","web","serve","__internal-auto-update","__post-upgrade"]);
9
+ const skip=new Set(["seed","mcp","install","help","start","setup","login","logout","auth","context","update","uninstall","daemon","stop","restart","upgrade","hook","hooks","claude","crew","harness","doctor","watch","version","prefs","retro","health","skill-adherence","review-risk","context-save","context-restore","-h","--help","-v","--version","intent","spec","audit-spec","dev","web","serve","__internal-auto-update","__post-upgrade","__internal-ensure-daemon"]);
10
10
  function refuse(m){console.error("prjct: daemon dropped the request ("+m+"). Retry: prjct "+args.join(" "));process.exit(1)}
11
11
  function isSafeRetry(e){const c=e&&e.code||"",m=e&&e.message||"";return c==="ECONNREFUSED"||c==="ENOENT"||c==="EACCES"||c==="EPERM"||m.includes("ECONNREFUSED")||m.includes("ENOENT")||m.includes("EACCES")||m.includes("EPERM")}
12
12
  // Hook fast path: forward the event (stdin) to the warm daemon and write its
@@ -19,7 +19,7 @@ function sendHook(sub,data){
19
19
  const msg=JSON.stringify({id:randomUUID(),command:"hook",args:sub?[sub]:[],options:{},cwd:process.cwd(),stdin:data})+"\n";
20
20
  const sock=connect(sockPath);const chunks=[],completion=new AbortController();
21
21
  const soft=()=>{if(!completion.signal.aborted){completion.abort();clearTimeout(t);sock.destroy();process.stdout.write("{}\n");process.exit(0)}};
22
- const t=setTimeout(soft,5000);
22
+ const t=setTimeout(soft,800);
23
23
  sock.on("connect",()=>sock.write(msg));
24
24
  sock.on("data",c=>{chunks.push(c.toString());const buf=chunks.join("");const n=buf.indexOf("\n");if(n!==-1){const r=JSON.parse(buf.slice(0,n));if(r.retry){soft();return}completion.abort();clearTimeout(t);sock.end();if(r.stdout)process.stdout.write(r.stdout);process.exit(r.exitCode!=null?r.exitCode:0)}});
25
25
  sock.on("error",soft);
@@ -33,6 +33,12 @@ if(cmd==="hook"){
33
33
  // Cold path (daemon disabled/unreachable): run the hook from the dedicated
34
34
  // hooks bundle, NOT the full core. cold-entry emits host JSON then detaches
35
35
  // afterEmit into a worker (PRJCT_HOOK_AFTER_EMIT) so Stop does not block.
36
+ // When the daemon is simply DOWN (not disabled), kick a detached
37
+ // __internal-ensure-daemon child first (fire-and-forget — never blocks
38
+ // this hook) so the NEXT hook gets the warm path. The child re-runs this
39
+ // shim; __internal-ensure-daemon is in the skip set, so it falls through
40
+ // to prjct-core.mjs, whose bin entry calls spawnDaemon() and exits.
41
+ if(process.env.PRJCT_NO_DAEMON!=="1"){try{const c=spawn(process.execPath,[process.argv[1],"__internal-ensure-daemon"],{detached:true,stdio:"ignore"});c.unref()}catch{}}
36
42
  import("./prjct-hooks.mjs").catch(()=>{process.stdout.write("{}\n");process.exit(0)})
37
43
  }
38
44
  }else if(cmd&&!skip.has(cmd)&&process.env.PRJCT_NO_DAEMON!=="1"&&hasEndpoint()){