@danypops/pi-packed 0.21.15 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/client.d.ts +2 -2
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +1 -1
  4. package/dist/protocol.d.ts +33 -0
  5. package/dist/protocol.d.ts.map +1 -1
  6. package/extension/src/menu-theme.ts +13 -3
  7. package/extension/src/packed.ts +2 -2
  8. package/extension/src/profile.ts +1 -34
  9. package/extension/src/tools.ts +24 -8
  10. package/extension/src/tui.ts +7 -3
  11. package/package.json +4 -4
  12. package/service/src/adoption/doctor.ts +15 -0
  13. package/service/src/adoption/install-validation.ts +97 -5
  14. package/service/src/adoption/module-freshness.ts +100 -0
  15. package/service/src/adoption/smoke.ts +26 -2
  16. package/service/src/cli/cli.ts +30 -5
  17. package/service/src/daemon/client.ts +13 -7
  18. package/service/src/daemon/daemon.ts +35 -3
  19. package/service/src/daemon/service.ts +42 -7
  20. package/service/src/daemon/vehicle-registration.ts +118 -35
  21. package/service/src/daemon/watcher.ts +1 -18
  22. package/service/src/packages/deploy-verify.ts +151 -0
  23. package/service/src/packages/install.ts +120 -3
  24. package/service/src/packages/package.ts +67 -1
  25. package/service/src/packages/resources.ts +63 -0
  26. package/service/src/public/client.ts +9 -3
  27. package/service/src/public/protocol.ts +13 -1
  28. package/service/test/cli.test.ts +75 -1
  29. package/service/test/deploy-verify.test.ts +168 -0
  30. package/service/test/doctor.test.ts +104 -1
  31. package/service/test/fixtures/install-validation/convention-only-package/extensions/index.ts +3 -0
  32. package/service/test/fixtures/install-validation/convention-only-package/package.json +5 -0
  33. package/service/test/install-validation.test.ts +14 -1
  34. package/service/test/install.test.ts +229 -0
  35. package/service/test/module-freshness.test.ts +146 -0
  36. package/service/test/resources.test.ts +66 -1
  37. package/service/test/service.test.ts +68 -1
  38. package/service/test/smoke.test.ts +49 -2
  39. package/service/test/vehicle-registration.test.ts +97 -5
package/dist/client.d.ts CHANGED
@@ -31,7 +31,7 @@ export interface PackedExtensionClient {
31
31
  spec?: ServiceSpecSummary;
32
32
  }>;
33
33
  remove(name: string, approved?: boolean): Promise<string>;
34
- update(source: string, approved?: boolean): Promise<UpdateOutcome>;
34
+ update(source: string, approved?: boolean, target?: string): Promise<UpdateOutcome>;
35
35
  setupPlan(manifestPath: string, prune?: boolean): Promise<SetupPlan>;
36
36
  setupApply(manifestPath: string, approved?: boolean, prune?: boolean): Promise<SetupApplyResult>;
37
37
  listResources(projectRoot?: string): Promise<{
@@ -81,7 +81,7 @@ export declare class PackedClient implements PackedExtensionClient {
81
81
  spec: ServiceSpecSummary | undefined;
82
82
  }>;
83
83
  remove(name: string, approved?: boolean): Promise<string>;
84
- update(source: string, approved?: boolean): Promise<UpdateOutcome>;
84
+ update(source: string, approved?: boolean, target?: string): Promise<UpdateOutcome>;
85
85
  setupPlan(manifestPath: string, prune?: boolean): Promise<SetupPlan>;
86
86
  setupApply(manifestPath: string, approved?: boolean, prune?: boolean): Promise<SetupApplyResult>;
87
87
  listResources(projectRoot?: string): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../service/src/public/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGX,yBAAyB,EACzB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,aAAa,EACb,MAAM,eAAe,CAAC;AAEvB,6NAA6N;AAC7N,qBAAa,mBAAoB,SAAQ,KAAK;IAG5C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO;gBAD7B,OAAO,EAAE,MAAM,EACN,UAAU,CAAC,EAAE,OAAO,YAAA;CAK9B;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,iBAAiB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC3B;AACD,MAAM,WAAW,qBAAqB;IACrC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC,CAAC;IAC9H,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,SAAS,IAAI,OAAO,CAAC,yBAAyB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACrE,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,QAAQ,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtC,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,kBAAkB,CAAA;KAAE,CAAC,CAAC;IAC3G,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACnE,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACrE,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjG,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAAC,OAAO,EAAE,gBAAgB,EAAE,CAAA;KAAE,CAAC,CAAC;IAC1G,cAAc,CACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9B;AAED,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,iBAAsB,GAAG,iBAAiB,CAiB3F;AAED,MAAM,WAAW,yBAAyB;IACzC;;;4CAGwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,oBAA6B,GAAG,yBAAyB,GAAG,SAAS,CAWpH;AAOD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAMrE,qBAAa,YAAa,YAAW,qBAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsG;gBAC9G,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,cAAsB;IAG1E,OAAO,CAAC,IAAI;IAMZ,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAG1B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,UAAQ;;;;;;IAGpD,IAAI,CAAC,IAAI,EAAE,MAAM;IAGjB,SAAS;IAGH,OAAO;IAGb,QAAQ;IAGR,mBAAmB,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,QAAQ,UAAQ;IAGtF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAQ;IAKxC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAQ;;;;IAK/C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,UAAQ;IAKrC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IAYtE,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,UAAQ;IAG7C,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,UAAQ,EAAE,KAAK,UAAQ;IAGhE,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM;;;;IAG5B,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,UAAQ;IAKjI,QAAQ;CAGR;AAED,wBAAsB,mBAAmB,CAAC,KAAK,oBAA6B,EAAE,SAAS,GAAE,cAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAatI;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IACjC;;mCAE+B;IAC/B,kBAAkB,IAAI,OAAO,CAAC;IAC9B;yDACqD;IACrD,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBhF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAgB7F;AAED,wBAAsB,kBAAkB,CAAC,KAAK,oBAA6B,EAAE,SAAS,GAAE,cAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBrI"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../service/src/public/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- import{spawn as A}from"node:child_process";import{accessSync as f,constants as S,readFileSync as U}from"node:fs";import{delimiter as I,dirname as y,join as T,resolve as k}from"node:path";import{fileURLToPath as P}from"node:url";class j{baseUrl;token;opsPath;transport;label;constructor(z,J,G){this.baseUrl=z;this.token=J;this.label=G.label,this.opsPath=G.opsPath??"/api/v1/ops",this.transport=G.transport??fetch}authedRequest(z,J={}){return this.transport(new Request(`${this.baseUrl}${z}`,{...J,headers:{...J.headers,authorization:`Bearer ${this.token}`}}))}async call(z,J){let G=await this.authedRequest(this.opsPath,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({op:z,input:J})}),Z=await G.json();if(!G.ok)throw Error(Z.error??`${this.label} operation failed with HTTP ${G.status}`);return Z.result}async operations(){let z=await this.authedRequest(this.opsPath),J=await z.json();if(!z.ok)throw Error(J.error??`${this.label} discovery failed with HTTP ${z.status}`);return J.operations??[]}async ready(){let z=await this.authedRequest("/ready");if(z.status===503)return!1;if(!z.ok)throw Error(`${this.label} readiness check failed with HTTP ${z.status}`);return!0}async health(){let z=await this.authedRequest("/health"),J=await z.json();if(!z.ok||J.ok!==!0||typeof J.version!=="string")throw Error(J.error??`${this.label} health check failed`);return{ok:!0,version:J.version}}}import{chmodSync as r,existsSync as p,mkdirSync as o,readFileSync as C,renameSync as n,rmSync as t,writeFileSync as a}from"node:fs";import{homedir as N,tmpdir as _}from"node:os";import{dirname as zz,join as W,win32 as Y}from"node:path";var R="127.0.0.1";function H(z,J={}){let G=J.platform??process.platform,Z=J.home??N();if(G==="darwin")return M(z,Z);if(G==="win32")return E(z,J.env??process.env,Z);return L(z,J,Z)}function L(z,J,G){let Z=J.env??process.env,$=J.uid??process.getuid?.()??0,K=Z.XDG_DATA_HOME??W(G,".local","share"),Q=Z.XDG_STATE_HOME??W(G,".local","state"),D=Z.XDG_RUNTIME_DIR??W("/run","user",String($)),b=Z.XDG_CONFIG_HOME??W(G,".config");return{database:W(K,z.stateDirectoryName,z.databaseFilename),token:W(Q,z.stateDirectoryName,z.tokenFilename),handle:W(D,z.stateDirectoryName,z.handleFilename),serviceDescriptor:W(b,"systemd","user",z.systemdUnitName)}}function M(z,J){let G=W(J,"Library"),Z=W(G,"Application Support",z.stateDirectoryName);return{database:W(Z,z.databaseFilename),token:W(Z,z.tokenFilename),handle:W(_(),z.stateDirectoryName,z.handleFilename),serviceDescriptor:W(Z,z.systemdUnitName)}}function E(z,J,G){let Z=J.LOCALAPPDATA??Y.join(G,"AppData","Local"),$=J.APPDATA??Y.join(G,"AppData","Roaming"),K=Y.join(Z,z.stateDirectoryName,"Data");return{database:Y.join(K,z.databaseFilename),token:Y.join(K,z.tokenFilename),handle:Y.join(Z,"Temp",z.stateDirectoryName,z.handleFilename),serviceDescriptor:Y.join($,z.stateDirectoryName,"Config",z.systemdUnitName)}}function q(z){try{let J=JSON.parse(C(z,"utf8"));if(J.host!==R||!Number.isInteger(J.port)||J.port<1||J.port>65535||!Number.isInteger(J.pid))return null;return J}catch{return null}}import{execFileSync as w}from"node:child_process";import{fileURLToPath as g}from"node:url";function B(z,J){let G=J.runCommand(process.execPath,[J.armadaCliPath,"status","--json"]);if(!G.ok)return!1;try{return JSON.parse(G.output).vehicles?.some(($)=>$.name===z)??!1}catch{return!1}}function O(){return{armadaCliPath:g(import.meta.resolve("@danypops/armada/cli")),runCommand:(z,J,G)=>{try{return{ok:!0,output:w(z,J,{encoding:"utf8",input:G,stdio:[G===void 0?"ignore":"pipe","pipe","pipe"]})}}catch(Z){let $=Z;return{ok:!1,output:($.stdout??"")+($.stderr??$.message)}}}}}class V extends Error{notADaemon;constructor(z,J){super(z);this.notADaemon=J;this.name="InstallServiceError"}}var u="pi-packed",F="pi-packed.service";function X(z={}){let J=z.env??process.env;if(J.PI_PACKED_HOME){let Z=k(J.PI_PACKED_HOME);return{token:`${Z}/token`,handle:`${Z}/handle.json`,serviceDescriptor:`${Z}/${F}`}}let G=H({stateDirectoryName:"pi-packed",databaseFilename:"packages.db",tokenFilename:"token",handleFilename:"handle.json",systemdUnitName:F},z);return{token:G.token,handle:G.handle,serviceDescriptor:G.serviceDescriptor}}function Hz(z=X()){let J=q(z.handle);if(!J)return;let G;try{G=U(z.token,"utf8").trim()}catch{return}if(!/^[a-f0-9]{64}$/.test(G))return;return{baseUrl:`http://${J.host}:${J.port}`,token:G}}function v(){return B(u,O())}function h(z,J=30000){return(G)=>z(new Request(G,{signal:AbortSignal.any([G.signal,AbortSignal.timeout(J)])}))}class x{rpc;constructor(z,J,G=fetch){this.rpc=new j(z,J,{label:"Packed",transport:h(G)})}call(z,J){return this.rpc.call(z,J)}health(){return this.rpc.health()}search(z,J,G=!1){return this.call("package.search",{query:z,limit:J,offline:G})}info(z){return this.call("package.info",{name:z})}installed(){return this.call("package.installed",{})}async updates(){return(await this.call("package.updates",{})).updates}security(){return this.call("package.security.get",{})}setMutationApproval(z,J=!1){return this.call("package.security.set",{mutationApproval:z,approved:J})}async install(z,J=!1){let G=await this.call("package.install",{source:z,approved:J});if(!G.ok)throw Error(G.output);return G.output}async installService(z,J=!1){let G=await this.call("package.install_service",{source:z,approved:J});if(!G.ok)throw new V(G.output,G.notADaemon);return{output:G.output,spec:G.spec}}async remove(z,J=!1){let G=await this.call("package.remove",{name:z,approved:J});if(!G.ok)throw Error(G.output);return G.output}async update(z,J=!1){let G=await this.call("package.update",{source:z,approved:J});if(!G.ok)throw Error(G.output);return{output:G.output,reloadRequired:G.reloadRequired??!0,alreadyUpToDate:G.alreadyUpToDate??!1,pinned:G.pinned??!1,previousVersion:G.previousVersion,currentVersion:G.currentVersion}}setupPlan(z,J=!1){return this.call("setup.plan",{manifestPath:z,prune:J})}setupApply(z,J=!1,G=!1){return this.call("setup.apply",{manifestPath:z,approved:J,prune:G})}listResources(z){return this.call("resources.list",{projectRoot:z})}async toggleResource(z,J,G,Z,$,K=!1){let Q=await this.call("resources.toggle",{source:z,field:J,path:G,enabled:Z,projectRoot:$,approved:K});if(!Q.ok)throw Error(Q.output);return Q.output}piStatus(){return this.call("pi.status",{})}}async function m(z=X(),J=fetch){let G=q(z.handle);if(!G)throw Error("Packed daemon is not running");let Z;try{Z=U(z.token,"utf8").trim()}catch{throw Error("Packed daemon token is unavailable")}if(!/^[a-f0-9]{64}$/.test(Z))throw Error("Packed daemon token is invalid");let $=new x(`http://${G.host}:${G.port}`,Z,J);return await $.health(),$}async function c(z){try{return await z.connect()}catch{}let J=z.retryAttempts??30,G=z.retryDelayMs??100,Z=z.isServiceInstalled();if(!Z)z.spawn();for(let K=0;K<J;K++){await z.sleep(G);try{return await z.connect()}catch{}}let $=J*G/1000;throw Error(Z?`The managed Packed service is registered but unreachable after ${$} seconds. Its supervisor may have stopped it or it may be failing; restart the managed service and inspect its status and logs. Packed will not auto-spawn a competing process.`:`Packed daemon did not become ready within ${$} seconds`)}function d(z=process.env){if(z.PI_PACKED_PI_BIN||z.PI_BIN)return;let J=z.PATH;if(!J)return;let G=process.platform==="win32"?["pi.exe","pi.cmd","pi.bat","pi"]:["pi"];for(let Z of J.split(I)){if(!Z)continue;for(let $ of G){let K=T(Z,$);try{return f(K,S.X_OK),K}catch{}}}return}async function Bz(z=X(),J=fetch){return c({connect:()=>m(z,J),isServiceInstalled:()=>v(),spawn:()=>{let G=process.env.PI_PACKED_BIN,Z=G??process.env.PI_PACKED_BUN??"bun",$=G?["serve"]:[T(y(P(import.meta.url)),"../service/src/cli/cli.ts"),"serve"],K=d(),Q=A(Z,$,{detached:!0,stdio:"ignore",env:{...process.env,DAEMON_KIT_LAUNCH_PROVENANCE:"auto-spawn",...K?{PI_BIN:K}:{}}});Q.once("error",()=>{}),Q.unref()},sleep:(G)=>new Promise((Z)=>setTimeout(Z,G))})}export{Hz as resolveVehicleClientTarget,d as resolvePiBinForSpawn,X as resolvePackedClientPaths,Bz as ensurePackedClient,c as ensureClient,m as connectPackedClient,x as PackedClient,V as InstallServiceError};
1
+ import{spawn as A}from"node:child_process";import{accessSync as f,constants as I,readFileSync as T}from"node:fs";import{delimiter as S,dirname as y,join as U,resolve as k}from"node:path";import{fileURLToPath as P}from"node:url";class q{baseUrl;token;opsPath;transport;label;constructor(z,G,J){this.baseUrl=z;this.token=G;this.label=J.label,this.opsPath=J.opsPath??"/api/v1/ops",this.transport=J.transport??fetch}authedRequest(z,G={}){return this.transport(new Request(`${this.baseUrl}${z}`,{...G,headers:{...G.headers,authorization:`Bearer ${this.token}`}}))}async call(z,G){let J=await this.authedRequest(this.opsPath,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({op:z,input:G})}),Z=await J.json();if(!J.ok)throw Error(Z.error??`${this.label} operation failed with HTTP ${J.status}`);return Z.result}async operations(){let z=await this.authedRequest(this.opsPath),G=await z.json();if(!z.ok)throw Error(G.error??`${this.label} discovery failed with HTTP ${z.status}`);return G.operations??[]}async ready(){let z=await this.authedRequest("/ready");if(z.status===503)return!1;if(!z.ok)throw Error(`${this.label} readiness check failed with HTTP ${z.status}`);return!0}async health(){let z=await this.authedRequest("/health"),G=await z.json();if(!z.ok||G.ok!==!0||typeof G.version!=="string")throw Error(G.error??`${this.label} health check failed`);return{ok:!0,version:G.version}}}import{chmodSync as r,existsSync as p,mkdirSync as o,readFileSync as _,renameSync as n,rmSync as t,writeFileSync as a}from"node:fs";import{homedir as R,tmpdir as b}from"node:os";import{dirname as zz,join as W,win32 as Y}from"node:path";var L="127.0.0.1";function H(z,G={}){let J=G.platform??process.platform,Z=G.home??R();if(J==="darwin")return E(z,Z);if(J==="win32")return N(z,G.env??process.env,Z);return M(z,G,Z)}function M(z,G,J){let Z=G.env??process.env,$=G.uid??process.getuid?.()??0,K=Z.XDG_DATA_HOME??W(J,".local","share"),Q=Z.XDG_STATE_HOME??W(J,".local","state"),D=Z.XDG_RUNTIME_DIR??W("/run","user",String($)),C=Z.XDG_CONFIG_HOME??W(J,".config");return{database:W(K,z.stateDirectoryName,z.databaseFilename),token:W(Q,z.stateDirectoryName,z.tokenFilename),handle:W(D,z.stateDirectoryName,z.handleFilename),serviceDescriptor:W(C,"systemd","user",z.systemdUnitName)}}function E(z,G){let J=W(G,"Library"),Z=W(J,"Application Support",z.stateDirectoryName);return{database:W(Z,z.databaseFilename),token:W(Z,z.tokenFilename),handle:W(b(),z.stateDirectoryName,z.handleFilename),serviceDescriptor:W(Z,z.systemdUnitName)}}function N(z,G,J){let Z=G.LOCALAPPDATA??Y.join(J,"AppData","Local"),$=G.APPDATA??Y.join(J,"AppData","Roaming"),K=Y.join(Z,z.stateDirectoryName,"Data");return{database:Y.join(K,z.databaseFilename),token:Y.join(K,z.tokenFilename),handle:Y.join(Z,"Temp",z.stateDirectoryName,z.handleFilename),serviceDescriptor:Y.join($,z.stateDirectoryName,"Config",z.systemdUnitName)}}function X(z){try{let G=JSON.parse(_(z,"utf8"));if(G.host!==L||!Number.isInteger(G.port)||G.port<1||G.port>65535||!Number.isInteger(G.pid))return null;return G}catch{return null}}import{execFileSync as g}from"node:child_process";import{fileURLToPath as w}from"node:url";function B(z,G){let J=G.runCommand(process.execPath,[G.armadaCliPath,"status","--json"]);if(!J.ok)return!1;try{return JSON.parse(J.output).vehicles?.some(($)=>$.name===z)??!1}catch{return!1}}function O(){return{armadaCliPath:w(import.meta.resolve("@danypops/armada/cli")),runCommand:(z,G,J)=>{try{return{ok:!0,output:g(z,G,{encoding:"utf8",input:J,stdio:[J===void 0?"ignore":"pipe","pipe","pipe"]})}}catch(Z){let $=Z;return{ok:!1,output:($.stdout??"")+($.stderr??$.message)}}}}}class V extends Error{notADaemon;constructor(z,G){super(z);this.notADaemon=G;this.name="InstallServiceError"}}var u="pi-packed",F="pi-packed.service";function j(z={}){let G=z.env??process.env;if(G.PI_PACKED_HOME){let Z=k(G.PI_PACKED_HOME);return{token:`${Z}/token`,handle:`${Z}/handle.json`,serviceDescriptor:`${Z}/${F}`}}let J=H({stateDirectoryName:"pi-packed",databaseFilename:"packages.db",tokenFilename:"token",handleFilename:"handle.json",systemdUnitName:F},z);return{token:J.token,handle:J.handle,serviceDescriptor:J.serviceDescriptor}}function Hz(z=j()){let G=X(z.handle);if(!G)return;let J;try{J=T(z.token,"utf8").trim()}catch{return}if(!/^[a-f0-9]{64}$/.test(J))return;return{baseUrl:`http://${G.host}:${G.port}`,token:J}}function v(){return B(u,O())}function h(z,G=30000){return(J)=>z(new Request(J,{signal:AbortSignal.any([J.signal,AbortSignal.timeout(G)])}))}class x{rpc;constructor(z,G,J=fetch){this.rpc=new q(z,G,{label:"Packed",transport:h(J)})}call(z,G){return this.rpc.call(z,G)}health(){return this.rpc.health()}search(z,G,J=!1){return this.call("package.search",{query:z,limit:G,offline:J})}info(z){return this.call("package.info",{name:z})}installed(){return this.call("package.installed",{})}async updates(){return(await this.call("package.updates",{})).updates}security(){return this.call("package.security.get",{})}setMutationApproval(z,G=!1){return this.call("package.security.set",{mutationApproval:z,approved:G})}async install(z,G=!1){let J=await this.call("package.install",{source:z,approved:G});if(!J.ok)throw Error(J.output);return J.output}async installService(z,G=!1){let J=await this.call("package.install_service",{source:z,approved:G});if(!J.ok)throw new V(J.output,J.notADaemon);return{output:J.output,spec:J.spec}}async remove(z,G=!1){let J=await this.call("package.remove",{name:z,approved:G});if(!J.ok)throw Error(J.output);return J.output}async update(z,G=!1,J){let Z=await this.call("package.update",{source:z,approved:G,target:J});if(!Z.ok)throw Error(Z.output);return{output:Z.output,reloadRequired:Z.reloadRequired??!0,alreadyUpToDate:Z.alreadyUpToDate??!1,pinned:Z.pinned??!1,previousVersion:Z.previousVersion,currentVersion:Z.currentVersion,outOfRangeUpdateAvailable:Z.outOfRangeUpdateAvailable,pinnedSourceRequiresTarget:Z.pinnedSourceRequiresTarget,replaced:Z.replaced,before:Z.before,after:Z.after,rollback:Z.rollback}}setupPlan(z,G=!1){return this.call("setup.plan",{manifestPath:z,prune:G})}setupApply(z,G=!1,J=!1){return this.call("setup.apply",{manifestPath:z,approved:G,prune:J})}listResources(z){return this.call("resources.list",{projectRoot:z})}async toggleResource(z,G,J,Z,$,K=!1){let Q=await this.call("resources.toggle",{source:z,field:G,path:J,enabled:Z,projectRoot:$,approved:K});if(!Q.ok)throw Error(Q.output);return Q.output}piStatus(){return this.call("pi.status",{})}}async function m(z=j(),G=fetch){let J=X(z.handle);if(!J)throw Error("Packed daemon is not running");let Z;try{Z=T(z.token,"utf8").trim()}catch{throw Error("Packed daemon token is unavailable")}if(!/^[a-f0-9]{64}$/.test(Z))throw Error("Packed daemon token is invalid");let $=new x(`http://${J.host}:${J.port}`,Z,G);return await $.health(),$}async function d(z){try{return await z.connect()}catch{}let G=z.retryAttempts??30,J=z.retryDelayMs??100,Z=z.isServiceInstalled();if(!Z)z.spawn();for(let K=0;K<G;K++){await z.sleep(J);try{return await z.connect()}catch{}}let $=G*J/1000;throw Error(Z?`The managed Packed service is registered but unreachable after ${$} seconds. Its supervisor may have stopped it or it may be failing; restart the managed service and inspect its status and logs. Packed will not auto-spawn a competing process.`:`Packed daemon did not become ready within ${$} seconds`)}function c(z=process.env){if(z.PI_PACKED_PI_BIN||z.PI_BIN)return;let G=z.PATH;if(!G)return;let J=process.platform==="win32"?["pi.exe","pi.cmd","pi.bat","pi"]:["pi"];for(let Z of G.split(S)){if(!Z)continue;for(let $ of J){let K=U(Z,$);try{return f(K,I.X_OK),K}catch{}}}return}async function Bz(z=j(),G=fetch){return d({connect:()=>m(z,G),isServiceInstalled:()=>v(),spawn:()=>{let J=process.env.PI_PACKED_BIN,Z=J??process.env.PI_PACKED_BUN??"bun",$=J?["serve"]:[U(y(P(import.meta.url)),"../service/src/cli/cli.ts"),"serve"],K=c(),Q=A(Z,$,{detached:!0,stdio:"ignore",env:{...process.env,DAEMON_KIT_LAUNCH_PROVENANCE:"auto-spawn",...K?{PI_BIN:K}:{}}});Q.once("error",()=>{}),Q.unref()},sleep:(J)=>new Promise((Z)=>setTimeout(Z,J))})}export{Hz as resolveVehicleClientTarget,c as resolvePiBinForSpawn,j as resolvePackedClientPaths,Bz as ensurePackedClient,d as ensureClient,m as connectPackedClient,x as PackedClient,V as InstallServiceError};
@@ -53,6 +53,22 @@ export interface UpdateOutcome {
53
53
  pinned: boolean;
54
54
  previousVersion?: string;
55
55
  currentVersion?: string;
56
+ outOfRangeUpdateAvailable?: string;
57
+ pinnedSourceRequiresTarget?: boolean;
58
+ replaced?: boolean;
59
+ before?: {
60
+ source: string;
61
+ version?: string;
62
+ };
63
+ after?: {
64
+ source: string;
65
+ version?: string;
66
+ };
67
+ rollback?: {
68
+ attempted: boolean;
69
+ ok: boolean;
70
+ message?: string;
71
+ };
56
72
  }
57
73
  export interface Diagnostic {
58
74
  code: string;
@@ -152,6 +168,7 @@ export interface ExtensionOperationInputs {
152
168
  "package.update": {
153
169
  source: string;
154
170
  approved?: boolean;
171
+ target?: string;
155
172
  };
156
173
  "setup.plan": {
157
174
  manifestPath: string;
@@ -210,6 +227,22 @@ export interface ExtensionOperationOutputs {
210
227
  pinned?: boolean;
211
228
  previousVersion?: string;
212
229
  currentVersion?: string;
230
+ outOfRangeUpdateAvailable?: string;
231
+ pinnedSourceRequiresTarget?: boolean;
232
+ replaced?: boolean;
233
+ before?: {
234
+ source: string;
235
+ version?: string;
236
+ };
237
+ after?: {
238
+ source: string;
239
+ version?: string;
240
+ };
241
+ rollback?: {
242
+ attempted: boolean;
243
+ ok: boolean;
244
+ message?: string;
245
+ };
213
246
  };
214
247
  "setup.plan": SetupPlan;
215
248
  "setup.apply": SetupApplyResult;
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../service/src/public/protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../service/src/public/protocol.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,20 @@ import type { Theme } from "@earendil-works/pi-coding-agent";
2
2
  import type { CardTheme, DialogTheme, MenuTheme, TabBarTheme } from "malevich-tui-components";
3
3
 
4
4
  /** Maps Pi's own Theme onto Malevich's Menu -- the one place this mapping
5
- * exists, shared by every ctx.ui.custom overlay menu in this extension. */
6
- export function cardTheme(theme: Theme): CardTheme {
5
+ * exists, shared by every ctx.ui.custom overlay menu in this extension.
6
+ *
7
+ * `updateAvailable` gives an unselected Card's *frame only* a distinct
8
+ * `warning` color -- the same semantic color already used for a row's own
9
+ * `↑<latest>` status text -- so a package with an update sitting available
10
+ * stands out in the grid without scanning every card's body text. Body
11
+ * content is left untouched (`content` stays a passthrough) so the
12
+ * already-styled status/version spans inside render exactly as before.
13
+ * Selected state still wins outright (accent, unchanged) so focus stays
14
+ * visually distinct from the update highlight -- only the unselected
15
+ * border picks up the warning treatment. */
16
+ export function cardTheme(theme: Theme, options?: { updateAvailable?: boolean }): CardTheme {
7
17
  return {
8
- border: (s) => theme.fg("border", s),
18
+ border: options?.updateAvailable ? (s) => theme.fg("warning", s) : (s) => theme.fg("border", s),
9
19
  selectedBorder: (s) => theme.fg("accent", s),
10
20
  content: (s) => s,
11
21
  selectedContent: (s) => theme.fg("accent", s),
@@ -59,7 +59,7 @@ export interface Natives {
59
59
  /** Throws InstallServiceError; check .notADaemon before surfacing a failure -- most packages aren't daemons at all. */
60
60
  installService(source: string, approved?: boolean): Promise<{ output: string; spec?: ServiceSpecSummary }>;
61
61
  remove(name: string, approved?: boolean): Promise<string>;
62
- update(source: string, approved?: boolean): Promise<UpdateOutcome>;
62
+ update(source: string, approved?: boolean, target?: string): Promise<UpdateOutcome>;
63
63
  setupPlan(manifestPath: string, prune?: boolean): Promise<SetupPlan>;
64
64
  setupApply(manifestPath: string, approved?: boolean, prune?: boolean): Promise<SetupApplyResult>;
65
65
  listResources(projectRoot?: string): Promise<{ global: PackageResources[]; project: PackageResources[] }>;
@@ -100,7 +100,7 @@ export async function createNatives(connect: PackageDaemonConnector = connectDef
100
100
  install: (source, approved) => client.callOnce((daemon) => daemon.install(source, approved)),
101
101
  installService: (source, approved) => client.callOnce((daemon) => daemon.installService(source, approved)),
102
102
  remove: (name, approved) => client.callOnce((daemon) => daemon.remove(name, approved)),
103
- update: (source, approved) => client.callOnce((daemon) => daemon.update(source, approved)),
103
+ update: (source, approved, target) => client.callOnce((daemon) => daemon.update(source, approved, target)),
104
104
  setupApply: (manifestPath, approved, prune) => client.callOnce((daemon) => daemon.setupApply(manifestPath, approved, prune)),
105
105
  toggleResource: (source, field, path, enabled, projectRoot, approved) =>
106
106
  client.callOnce((daemon) => daemon.toggleResource(source, field, path, enabled, projectRoot, approved)),
@@ -96,22 +96,6 @@ export function loadProfiles(agentDir: string, cwd: string, projectTrusted: bool
96
96
  return { ...globalProfiles, ...readProfileFile(join(cwd, CONFIG_DIR_NAME, PROFILE_FILE)) };
97
97
  }
98
98
 
99
- function loadDefaultProfile(cwd: string, projectTrusted: boolean): string | undefined {
100
- if (!projectTrusted) return undefined;
101
- try {
102
- const path = join(cwd, "pi-setup.json");
103
- if (!existsSync(path)) return undefined;
104
- const stat = lstatSync(path);
105
- if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024) return undefined;
106
- const value = JSON.parse(readFileSync(path, "utf8")) as { schemaVersion?: unknown; defaultProfile?: unknown };
107
- return value.schemaVersion === 1 && typeof value.defaultProfile === "string" && PROFILE_NAME.test(value.defaultProfile)
108
- ? value.defaultProfile
109
- : undefined;
110
- } catch {
111
- return undefined;
112
- }
113
- }
114
-
115
99
  function loadLastProfile(agentDir: string): string | undefined {
116
100
  try {
117
101
  const path = join(agentDir, LAST_PROFILE_FILE);
@@ -299,7 +283,7 @@ export function registerProfiles(pi: ExtensionAPI): void {
299
283
  pi.on("before_agent_start", (event) =>
300
284
  activeProfile?.instructions ? { systemPrompt: `${event.systemPrompt}\n\n${activeProfile.instructions}` } : undefined,
301
285
  );
302
- pi.on("session_start", async (event, ctx) => {
286
+ pi.on("session_start", async (_event, ctx) => {
303
287
  try {
304
288
  profiles = loadProfiles(agentDir, ctx.cwd, ctx.isProjectTrusted());
305
289
  } catch (error) {
@@ -317,15 +301,6 @@ export function registerProfiles(pi: ExtensionAPI): void {
317
301
  ctx.ui.notify(`Profile "${flag}" activated`, "info");
318
302
  return;
319
303
  }
320
- const defaultProfile = loadDefaultProfile(ctx.cwd, ctx.isProjectTrusted());
321
- if ((event.reason === "reload" || event.reason === "new") && defaultProfile) {
322
- if (profiles[defaultProfile]) await apply(defaultProfile, profiles[defaultProfile]!, ctx, false);
323
- else {
324
- ctx.ui.notify(`Default profile "${defaultProfile}" is not defined`, "warning");
325
- setStatus(ctx);
326
- }
327
- return;
328
- }
329
304
  const state = [...ctx.sessionManager.getEntries()]
330
305
  .reverse()
331
306
  .find(
@@ -340,14 +315,6 @@ export function registerProfiles(pi: ExtensionAPI): void {
340
315
  setStatus(ctx);
341
316
  return;
342
317
  }
343
- if (defaultProfile) {
344
- if (profiles[defaultProfile]) await apply(defaultProfile, profiles[defaultProfile]!, ctx, false);
345
- else {
346
- ctx.ui.notify(`Default profile "${defaultProfile}" is not defined`, "warning");
347
- setStatus(ctx);
348
- }
349
- return;
350
- }
351
318
  const last = loadLastProfile(agentDir);
352
319
  if (last && profiles[last]) {
353
320
  await apply(last, profiles[last]!, ctx, false);
@@ -87,27 +87,37 @@ export async function installPackageWithPolicy(
87
87
  return text(output, createMutationDetails("install", source, "succeeded", output));
88
88
  }
89
89
 
90
- export async function updatePackageWithPolicy(source: string, natives: Pick<Natives, "security" | "update">, ctx: ApprovalContext) {
90
+ export async function updatePackageWithPolicy(
91
+ source: string,
92
+ natives: Pick<Natives, "security" | "update">,
93
+ ctx: ApprovalContext,
94
+ target?: string,
95
+ ) {
91
96
  const restartRequired = targetsPackedItself(source);
92
- const approval = await approvePackageOperation("update", `pi update --extension ${source}`, natives, ctx, restartRequired);
97
+ const command = target ? `pi remove ${source} && pi install ${target}` : `pi update --extension ${source}`;
98
+ const approval = await approvePackageOperation("update", command, natives, ctx, restartRequired);
93
99
  if (!approval.allowed) {
94
100
  const output = approval.message ?? "update denied";
95
101
  return text(output, createMutationDetails("update", source, approval.reason ?? "denied", output));
96
102
  }
97
- const outcome = await natives.update(source, approval.approved);
103
+ const outcome = await natives.update(source, approval.approved, target);
98
104
  if (outcome.alreadyUpToDate) {
99
105
  const version = outcome.currentVersion ?? outcome.previousVersion;
100
106
  const reason = outcome.pinned
101
- ? `pinned to ${version ?? "an exact version"} -- pi update intentionally leaves pinned packages unchanged; reinstall with a different (or no) version to move off the pin`
107
+ ? `pinned to ${version ?? "an exact version"} -- pi update intentionally leaves pinned packages unchanged; call pkg_update again with target set to move off the pin`
102
108
  : `already up to date${version ? ` at ${version}` : ""}`;
103
- const message = `${source} is ${reason}.`;
109
+ const outOfRangeNote = outcome.outOfRangeUpdateAvailable
110
+ ? ` A newer version, ${outcome.outOfRangeUpdateAvailable}, exists outside the declared range -- widen it to update.`
111
+ : "";
112
+ const message = `${source} is ${reason}.${outOfRangeNote}`;
104
113
  return text(message, createMutationDetails("update", source, "succeeded", outcome.output || message, false));
105
114
  }
106
115
  const transition = outcome.previousVersion && outcome.currentVersion ? ` (${outcome.previousVersion} → ${outcome.currentVersion})` : "";
107
116
  const activateNote = restartRequired
108
117
  ? "Restart Pi (exit and relaunch) to activate -- Packed's own running code can't hot-reload itself."
109
118
  : "Reload with /reload to activate.";
110
- const message = `${outcome.output || `Updated ${source}.`}${transition} ${activateNote}`;
119
+ const replacedNote = outcome.replaced ? ` Replaced ${outcome.before?.source ?? source} with ${outcome.after?.source ?? target}.` : "";
120
+ const message = `${outcome.output || `Updated ${source}.`}${transition}${replacedNote} ${activateNote}`;
111
121
  return text(message, createMutationDetails("update", source, "succeeded", outcome.output || message, true));
112
122
  }
113
123
 
@@ -224,9 +234,15 @@ export function registerTools(pi: ExtensionAPI, natives: Natives): void {
224
234
  name: "pkg_update",
225
235
  label: "Pi Extension Update",
226
236
  description:
227
- "Update one already-installed Pi extension through Pi's documented update command. Operation-aware approval is secure by default.",
237
+ "Update one already-installed Pi extension through Pi's documented update command. Operation-aware approval is secure by default. An exact pin (e.g. npm:@scope/pkg@1.2.3) is intentionally left unchanged by a plain update -- pass target to move it, via a supervised remove+install workflow with identity checks, filter preservation, postcondition verification, and rollback on failure.",
228
238
  parameters: Type.Object({
229
239
  source: Type.String({ description: "configured npm:, git:, or https source of the installed Pi extension" }),
240
+ target: Type.Optional(
241
+ Type.String({
242
+ description:
243
+ "new npm:, git:, or https source to replace source with -- required to move an exact pin (source and target must name the same package)",
244
+ }),
245
+ ),
230
246
  }),
231
247
  renderCall(args, theme) {
232
248
  return renderPackageToolCall("Update Pi extension", args, theme);
@@ -235,7 +251,7 @@ export function registerTools(pi: ExtensionAPI, natives: Natives): void {
235
251
  return renderPackageToolResult(result, options, theme, context);
236
252
  },
237
253
  async execute(_id, params, _signal, _onUpdate, ctx) {
238
- return updatePackageWithPolicy(params.source, natives, ctx);
254
+ return updatePackageWithPolicy(params.source, natives, ctx, params.target);
239
255
  },
240
256
  });
241
257
 
@@ -110,7 +110,7 @@ export async function applyPackageChoice(
110
110
  if (!outcome.reloadRequired) {
111
111
  const version = outcome.currentVersion ?? outcome.previousVersion;
112
112
  const reason = outcome.pinned
113
- ? `pinned to ${version ?? "an exact version"} -- pi update intentionally leaves pinned packages unchanged`
113
+ ? `pinned to ${version ?? "an exact version"} -- pi update intentionally leaves pinned packages unchanged; run \`packed update npm:${row.name} --to <new-source>\`, or pkg_update with target set, to move off the pin`
114
114
  : `already up to date${version ? ` at ${version}` : ""}`;
115
115
  ctx.ui.notify(`${row.name} is ${reason}.`, "info");
116
116
  onSettled?.({ ok: true, message: reason });
@@ -610,18 +610,22 @@ export class PackagesTab implements Component {
610
610
  // the next row's "start" event moves updatingRowName off it.
611
611
  const rowSettled = this.settled.get(row.name);
612
612
  const isUpdating = !rowSettled && this.updatingRowName === row.name;
613
+ // Same idle+hasUpdate condition the status text below already
614
+ // gates on -- an updating or just-settled row shows its own
615
+ // transient outcome instead, so the frame doesn't also flag it.
616
+ const updateAvailable = !isUpdating && !rowSettled && row.hasUpdate;
613
617
  const status = isUpdating
614
618
  ? theme.fg("accent", `${this.spinner.glyph()} updating…`)
615
619
  : rowSettled
616
620
  ? theme.fg(rowSettled.ok ? "success" : "error", `${rowSettled.ok ? "✓" : "✗"}${rowSettled.tail ? ` ${rowSettled.tail}` : ""}`)
617
- : row.hasUpdate
621
+ : updateAvailable
618
622
  ? theme.fg("warning", `↑${row.latest}`)
619
623
  : theme.fg("muted", "installed");
620
624
  const card = new Card({
621
625
  title: theme.bold(row.name),
622
626
  content: [`${theme.fg("dim", row.version)} · ${status}`],
623
627
  selected,
624
- theme: cardTheme(theme),
628
+ theme: cardTheme(theme, { updateAvailable }),
625
629
  measure: this.measure,
626
630
  });
627
631
  return card.render(columnWidth);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-packed",
3
- "version": "0.21.15",
3
+ "version": "0.22.1",
4
4
  "description": "Pi package lifecycle, validation, daemon, tools, profiles, and TUI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,9 +31,9 @@
31
31
  "@danypops/packed": "^0.7.0",
32
32
  "@danypops/pi-extension-harness": "^0.2.0",
33
33
  "@danypops/vehicle-client": "^0.5.2",
34
- "@danypops/vehicle-client-pi": "^0.18.4",
35
- "@danypops/vehicle-core": "^0.12.3",
36
- "@danypops/vehicle-server": "^0.17.1",
34
+ "@danypops/vehicle-client-pi": "^0.25.0",
35
+ "@danypops/vehicle-core": "^0.14.0",
36
+ "@danypops/vehicle-server": "^0.20.0",
37
37
  "jiti": "^2.7.0",
38
38
  "malevich-tui-components": "^0.21.1",
39
39
  "publint": "0.3.22",
@@ -10,6 +10,7 @@ import { existsSync } from "node:fs";
10
10
  import { join } from "node:path";
11
11
  import { createNodeServiceInstallDeps } from "@danypops/vehicle-server/service";
12
12
  import { listPackageResources, type PackageResources, resolveInstalledDir } from "../packages/resources.ts";
13
+ import type { ModuleFreshnessDiagnostic } from "./module-freshness.ts";
13
14
  import { checkServiceUnitPaths, type ServiceUnitDiagnostic } from "./service-doctor.ts";
14
15
  import { runExtensionSmoke, type SmokeOptions, type SmokeRegistrations } from "./smoke.ts";
15
16
 
@@ -55,6 +56,16 @@ export interface DoctorReport {
55
56
  truncated: boolean;
56
57
  /** A daemon-backed package's systemd --user unit referencing a path that no longer exists on disk -- see service-doctor.ts. Empty (not omitted) on a platform without systemd --user coverage. */
57
58
  serviceUnits: ServiceUnitDiagnostic[];
59
+ /**
60
+ * Whether THIS running process still holds a stale in-memory copy of one
61
+ * of its own runtime dependencies, loaded once at startup -- see
62
+ * module-freshness.ts. Only meaningful for a long-running daemon process
63
+ * (the one thing that can actually go stale); omitted entirely for a
64
+ * standalone `packed doctor` invocation (a fresh CLI process has nothing
65
+ * of its own to compare against). Populated by the daemon's own
66
+ * doctor.run route, never by runDoctor() itself.
67
+ */
68
+ moduleFreshness?: ModuleFreshnessDiagnostic[];
58
69
  }
59
70
 
60
71
  interface ScanJob {
@@ -150,6 +161,10 @@ export function formatDoctorReport(report: DoctorReport, json: boolean): string
150
161
  for (const diagnostic of report.serviceUnits) {
151
162
  out += `\n${diagnostic.severity.toUpperCase()} ${diagnostic.code} ${diagnostic.package} (${diagnostic.unitName}.service): ${diagnostic.message}\n`;
152
163
  }
164
+ for (const module of report.moduleFreshness ?? []) {
165
+ if (!module.stale) continue;
166
+ out += `\nSTALE_MODULE_CACHE ${module.name}: the daemon loaded ${module.loadedVersion ?? "an unknown version"} at startup, but ${module.currentVersion ?? "a different version"} is now on disk -- restart the daemon (systemctl --user restart pi-packed.service) to pick it up.\n`;
167
+ }
153
168
  if (report.truncated) out += "\nOutput truncated: more enabled extensions exist than this run's bound.\n";
154
169
  return out;
155
170
  }
@@ -12,7 +12,7 @@
12
12
  * subprocess as non-gating, observational evidence alongside that gating
13
13
  * check -- see ExtensionLoadResult.additionalLoadPaths.
14
14
  */
15
- import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
15
+ import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs";
16
16
  import { createRequire } from "node:module";
17
17
  import { tmpdir } from "node:os";
18
18
  import { join, resolve } from "node:path";
@@ -74,6 +74,75 @@ const MAX_LOAD_TIMEOUT_MS = 30_000;
74
74
  const PACK_TIMEOUT_MS = 30_000;
75
75
  const INSTALL_TIMEOUT_MS = 60_000;
76
76
  const MAX_EXTENSIONS = 20;
77
+ /** Bounds directoryHasMatchingFile's own recursive walk -- a real Pi package's
78
+ * resource directories are small; this only exists so an adversarial or
79
+ * accidentally enormous tarball can't make the convention-directory scan
80
+ * itself expensive. */
81
+ const MAX_CONVENTION_SCAN_ENTRIES = 500;
82
+
83
+ /** The four resource kinds a package.json's own `pi` manifest key, or (absent
84
+ * a manifest) pi's own convention directories, can declare -- see
85
+ * @earendil-works/pi-coding-agent's docs/packages.md "Package Structure". */
86
+ const MANIFEST_RESOURCE_FIELDS = ["extensions", "skills", "prompts", "themes"] as const;
87
+
88
+ /** Loosely mirrors (not a byte-for-byte port -- pi's own walker is
89
+ * .gitignore-aware via the `ignore` package, this isn't) pi's own
90
+ * convention-directory file matching from @earendil-works/pi-coding-agent's
91
+ * package-manager.js: extensions/ take .ts/.js recursively, skills/ take
92
+ * SKILL.md or any .md recursively, prompts/ and themes/ take top-level
93
+ * .md/.json respectively. Close enough to answer "would pi's own loader ever
94
+ * find anything to load here", which is all a pre-install admission check
95
+ * needs. */
96
+ const CONVENTION_RESOURCE_DIRS: Record<string, { match: (name: string) => boolean; recursive: boolean }> = {
97
+ extensions: { match: (name) => name.endsWith(".ts") || name.endsWith(".js"), recursive: true },
98
+ skills: { match: (name) => name === "SKILL.md" || name.endsWith(".md"), recursive: true },
99
+ prompts: { match: (name) => name.endsWith(".md"), recursive: false },
100
+ themes: { match: (name) => name.endsWith(".json"), recursive: false },
101
+ };
102
+
103
+ function hasNonEmptyStringArray(value: unknown): boolean {
104
+ return Array.isArray(value) && value.some((entry) => typeof entry === "string" && entry.trim().length > 0);
105
+ }
106
+
107
+ /** True if the package's own `pi` manifest key declares at least one
108
+ * non-empty resource array of any of the four kinds -- not just
109
+ * `extensions`, which the caller already checked separately. */
110
+ function hasAnyManifestResource(pi: Record<string, unknown> | undefined): boolean {
111
+ if (!pi) return false;
112
+ return MANIFEST_RESOURCE_FIELDS.some((field) => hasNonEmptyStringArray(pi[field]));
113
+ }
114
+
115
+ /** Bounded recursive scan for at least one file matching `match` under `dir`.
116
+ * `remaining` is a shared mutable budget across the whole call tree so a
117
+ * pathological directory structure can't make this unbounded work. */
118
+ function directoryHasMatchingFile(dir: string, match: (name: string) => boolean, recursive: boolean, remaining: { count: number }): boolean {
119
+ if (!existsSync(dir) || remaining.count <= 0) return false;
120
+ let entries: import("node:fs").Dirent<string>[];
121
+ try {
122
+ entries = readdirSync(dir, { withFileTypes: true, encoding: "utf8" });
123
+ } catch {
124
+ return false;
125
+ }
126
+ for (const entry of entries) {
127
+ if (remaining.count-- <= 0) return false;
128
+ if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
129
+ const full = join(dir, entry.name);
130
+ if (entry.isFile() && match(entry.name)) return true;
131
+ if (recursive && entry.isDirectory() && directoryHasMatchingFile(full, match, recursive, remaining)) return true;
132
+ }
133
+ return false;
134
+ }
135
+
136
+ /** True if the staged package root has any of pi's own convention resource
137
+ * directories (extensions/, skills/, prompts/, themes/) containing at least
138
+ * one file pi's own loader would actually pick up -- the fallback pi itself
139
+ * uses when a package declares no `pi` manifest at all. */
140
+ function hasConventionResources(root: string): boolean {
141
+ const remaining = { count: MAX_CONVENTION_SCAN_ENTRIES };
142
+ return Object.entries(CONVENTION_RESOURCE_DIRS).some(([dirName, { match, recursive }]) =>
143
+ directoryHasMatchingFile(join(root, dirName), match, recursive, remaining),
144
+ );
145
+ }
77
146
 
78
147
  function bounded(value: number | undefined, fallback: number, maximum: number): number {
79
148
  if (!Number.isFinite(value) || value === undefined || value <= 0) return fallback;
@@ -215,9 +284,13 @@ async function verifyAllLoadPathsHeadless(entryPath: string, timeoutMs?: number)
215
284
  }
216
285
 
217
286
  /** Stages the real npm tarball in isolation and headlessly load-checks
218
- * every pi.extensions entry it declares. A package with no pi.extensions
219
- * (most npm packages) or a non-npm source has nothing to validate and
220
- * passes through as ok. */
287
+ * every pi.extensions entry it declares. A non-npm source has nothing to
288
+ * stage and passes through as ok. A package with no pi.extensions passes
289
+ * only if it declares some other pi manifest resource (skills/prompts/
290
+ * themes) or has a matching pi convention directory on disk -- otherwise
291
+ * it isn't a Pi package at all (a plain npm dependency like is-number or
292
+ * is-buffer) and is refused rather than silently admitted as a dead
293
+ * `packages` entry pi itself would never load anything from. */
221
294
  export class HeadlessInstallValidator implements InstallValidator {
222
295
  constructor(private readonly timeoutMs?: number) {}
223
296
 
@@ -241,7 +314,26 @@ export class HeadlessInstallValidator implements InstallValidator {
241
314
  const declared = Array.isArray(pi?.extensions)
242
315
  ? pi.extensions.filter((entry): entry is string => typeof entry === "string").slice(0, MAX_EXTENSIONS)
243
316
  : [];
244
- if (declared.length === 0) return { ok: true, source, extensions: [] };
317
+ if (declared.length === 0) {
318
+ // No pi.extensions to headlessly load-check -- but that alone isn't
319
+ // license to wave the package through. A real Pi package with only
320
+ // skills/prompts/themes (declared in the manifest or found via pi's
321
+ // own convention directories) still passes here unexamined; a
322
+ // package that is neither -- e.g. `is-number`, `is-buffer`, any
323
+ // plain leaf npm dependency someone points `pkg_install` at
324
+ // directly -- gets refused instead of silently becoming a dead
325
+ // `packages` entry that pi itself will never load anything from.
326
+ if (hasAnyManifestResource(pi) || hasConventionResources(staged.root)) {
327
+ return { ok: true, source, extensions: [] };
328
+ }
329
+ return {
330
+ ok: false,
331
+ source,
332
+ extensions: [],
333
+ message:
334
+ "package declares no pi.extensions/skills/prompts/themes and has no extensions/skills/prompts/themes directory -- not a Pi package",
335
+ };
336
+ }
245
337
 
246
338
  const installed = await installStagedDependencies(staged.root);
247
339
  if (!installed.ok) return { ok: false, source, extensions: [], message: installed.message };