@danypops/pi-packed 0.21.14 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) 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/approval/reload.ts +51 -2
  7. package/extension/src/menu-theme.ts +13 -3
  8. package/extension/src/packed.ts +2 -2
  9. package/extension/src/tabs/discover.ts +13 -2
  10. package/extension/src/tool-output.ts +14 -1
  11. package/extension/src/tools.ts +46 -14
  12. package/extension/src/tui.ts +7 -3
  13. package/package.json +4 -4
  14. package/service/src/adoption/doctor.ts +15 -0
  15. package/service/src/adoption/install-validation.ts +97 -5
  16. package/service/src/adoption/module-freshness.ts +100 -0
  17. package/service/src/adoption/smoke.ts +26 -2
  18. package/service/src/cli/cli.ts +30 -5
  19. package/service/src/daemon/client.ts +13 -7
  20. package/service/src/daemon/daemon.ts +35 -3
  21. package/service/src/daemon/service.ts +42 -7
  22. package/service/src/daemon/vehicle-registration.ts +118 -35
  23. package/service/src/daemon/watcher.ts +1 -18
  24. package/service/src/packages/deploy-verify.ts +151 -0
  25. package/service/src/packages/install.ts +120 -3
  26. package/service/src/packages/package.ts +67 -1
  27. package/service/src/packages/resources.ts +63 -0
  28. package/service/src/public/client.ts +9 -3
  29. package/service/src/public/protocol.ts +13 -1
  30. package/service/test/cli.test.ts +75 -1
  31. package/service/test/deploy-verify.test.ts +168 -0
  32. package/service/test/doctor.test.ts +104 -1
  33. package/service/test/fixtures/install-validation/convention-only-package/extensions/index.ts +3 -0
  34. package/service/test/fixtures/install-validation/convention-only-package/package.json +5 -0
  35. package/service/test/install-validation.test.ts +14 -1
  36. package/service/test/install.test.ts +229 -0
  37. package/service/test/module-freshness.test.ts +146 -0
  38. package/service/test/resources.test.ts +66 -1
  39. package/service/test/service.test.ts +68 -1
  40. package/service/test/smoke.test.ts +49 -2
  41. 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":"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"}
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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"}
@@ -7,9 +7,52 @@
7
7
  */
8
8
  import type { PackageOperation } from "./permission.js";
9
9
 
10
+ /**
11
+ * Packed's own npm package name -- the one target where install/update/
12
+ * remove has a real, confirmed hazard plain /reload cannot fix: this
13
+ * extension's own already-loaded code (e.g. vehicle-target.ts importing
14
+ * @danypops/pi-packed/client) keeps a stale reference to the pre-mutation
15
+ * module even after /reload re-evaluates the extension's own source files.
16
+ * Confirmed live: updating pi-packed mid-session, then /reload, threw
17
+ * "resolveVehicleClientTarget is not a function" -- a brand-new process
18
+ * importing the exact same on-disk files resolved it fine. Node/Bun cache
19
+ * an ES module by resolved file path for the life of the process; an
20
+ * in-place npm overwrite never invalidates an already-loaded entry, and
21
+ * /reload only re-executes the extension's own entry file, not every
22
+ * transitively-cached dependency. Only a full process restart re-imports
23
+ * everything fresh.
24
+ */
25
+ export const PACKED_NPM_PACKAGE_NAME = "@danypops/pi-packed";
26
+
27
+ /**
28
+ * True when a pkg_install/pkg_update source (npm:@danypops/pi-packed,
29
+ * npm:@danypops/pi-packed@1.2.3, git:/https: sources never match) or a
30
+ * pkg_remove bare name refers to Packed's own npm package. Deliberately
31
+ * narrow -- this is the one case Packed can be CERTAIN has the stale-
32
+ * module-cache hazard above, since it's the package whose own code is
33
+ * running the mutation. Any other package's extension could in principle
34
+ * have the same self-import pattern, but Packed has no way to know that
35
+ * about third-party code, so it never guesses there.
36
+ */
37
+ export function targetsPackedItself(sourceOrName: string): boolean {
38
+ const withoutScheme = sourceOrName.startsWith("npm:") ? sourceOrName.slice(4) : sourceOrName;
39
+ const bare = withoutScheme.startsWith("@") ? withoutScheme.split("@").slice(0, 2).join("@") : withoutScheme.split("@")[0];
40
+ return bare === PACKED_NPM_PACKAGE_NAME;
41
+ }
42
+
43
+ export interface ReloadWarningOptions {
44
+ /** True when the target is Packed's own package -- see targetsPackedItself(). */
45
+ restartRequired?: boolean;
46
+ }
47
+
10
48
  /** Inline warning appended to a mutation's pre-confirmation dialog, before
11
49
  * the operation runs -- the moment the user is actually deciding. */
12
- export function reloadWarning(operation: PackageOperation): string {
50
+ export function reloadWarning(operation: PackageOperation, options: ReloadWarningOptions = {}): string {
51
+ if (options.restartRequired) {
52
+ return operation === "remove"
53
+ ? "Packed's own code is already running inside this Pi process -- deactivating it needs a full restart (exit and relaunch Pi), not just /reload."
54
+ : "Packed's own code is already running inside this Pi process -- its updated code can only be picked up by a full restart (exit and relaunch Pi), not just /reload.";
55
+ }
13
56
  return operation === "remove"
14
57
  ? "This will require a Pi reload (/reload) to deactivate it."
15
58
  : "This will likely require a Pi reload (/reload) to activate its resources.";
@@ -35,7 +78,13 @@ export interface ReloadConfirmContext {
35
78
  * shares identical wording and behavior instead of drifting apart --
36
79
  * reload.ts's whole reason for existing.
37
80
  */
38
- export async function confirmReload(ctx: ReloadConfirmContext): Promise<boolean> {
81
+ export async function confirmReload(ctx: ReloadConfirmContext, options: ReloadWarningOptions = {}): Promise<boolean> {
39
82
  if (!ctx.hasUI) return true;
83
+ if (options.restartRequired) {
84
+ return ctx.ui.confirm(
85
+ "Restart Pi now?",
86
+ "Packed's own code changed and cannot be hot-reloaded from inside itself -- exit and relaunch Pi to pick it up. /reload alone will not work.",
87
+ );
88
+ }
40
89
  return ctx.ui.confirm("Reload Pi now?", "This change only takes effect after a reload.");
41
90
  }
@@ -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)),
@@ -13,6 +13,7 @@ import type { ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-a
13
13
  import { rawKeyHint } from "@earendil-works/pi-coding-agent";
14
14
  import { Input, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
15
15
  import { Card, type Component } from "malevich-tui-components";
16
+ import { targetsPackedItself } from "../approval/reload.js";
16
17
  import { cardTheme } from "../menu-theme.js";
17
18
  import { formatDownloadCount, formatRelativeDate } from "../model.js";
18
19
  import type { Natives, PackageSummary } from "../packed.js";
@@ -32,7 +33,8 @@ export type InstallOutcome = "installed" | "cancelled" | "failed";
32
33
  * path (installPackageWithPolicy) -- most packages aren't daemons at all. */
33
34
  export async function applyInstall(result: PackageSummary, natives: Natives, ctx: ExtensionCommandContext): Promise<InstallOutcome> {
34
35
  const source = `npm:${result.name}`;
35
- const approval = await approvePackageOperation("install", `pi install ${source}`, natives, ctx);
36
+ const restartRequired = targetsPackedItself(result.name);
37
+ const approval = await approvePackageOperation("install", `pi install ${source}`, natives, ctx, restartRequired);
36
38
  if (!approval.allowed) {
37
39
  ctx.ui.notify(approval.message ?? "install denied", "warning");
38
40
  return "cancelled";
@@ -46,7 +48,16 @@ export async function applyInstall(result: PackageSummary, natives: Natives, ctx
46
48
  ctx.ui.notify(`note: could not register a persistent service for ${result.name}: ${e instanceof Error ? e.message : e}`, "warning");
47
49
  }
48
50
  }
49
- ctx.ui.notify(`${output}; reloading Pi resources.`, "info");
51
+ // ctx.reload() re-evaluates this extension's own entry file, same as /reload -- harmless to
52
+ // call either way, but it cannot bust an already-loaded copy of Packed's own client module,
53
+ // so a self-install/update needs the stronger, honest wording instead of implying reload alone
54
+ // finished the job (see approval/reload.ts's targetsPackedItself()).
55
+ ctx.ui.notify(
56
+ restartRequired
57
+ ? `${output}; restart Pi (exit and relaunch) to activate -- /reload alone will not pick up Packed's own updated code.`
58
+ : `${output}; reloading Pi resources.`,
59
+ "info",
60
+ );
50
61
  await ctx.reload();
51
62
  return "installed";
52
63
  } catch (e) {
@@ -1,6 +1,7 @@
1
1
  import type { PackageSummary as Pkg, PackageInfo as PkgInfo } from "@danypops/pi-packed/protocol";
2
2
  import type { AgentToolResult, Theme } from "@earendil-works/pi-coding-agent";
3
3
  import { Text, truncateToWidth } from "@earendil-works/pi-tui";
4
+ import { targetsPackedItself } from "./approval/reload.js";
4
5
  import {
5
6
  TOOL_COLLAPSED_PACKAGE_PREVIEW,
6
7
  TOOL_DETAILS_MAX_CAPABILITIES,
@@ -59,6 +60,11 @@ export interface MutationToolDetails {
59
60
  status: "succeeded" | "cancelled" | "denied";
60
61
  output: string;
61
62
  reloadRequired: boolean;
63
+ /** Optional (not version-gated) -- see approval/reload.ts's targetsPackedItself().
64
+ * Absent on details serialized before this field existed; the renderer treats
65
+ * absent the same as false, so an older persisted tool result still renders
66
+ * exactly as it always did. */
67
+ restartRequired?: boolean;
62
68
  }
63
69
 
64
70
  export type PackageToolDetails = SearchToolDetails | InfoToolDetails | MutationToolDetails;
@@ -181,6 +187,10 @@ export function createMutationDetails(
181
187
  status,
182
188
  output: safeDisplayText(output, TOOL_DETAILS_MAX_OUTPUT_CHARACTERS),
183
189
  reloadRequired,
190
+ // Derived from the raw (pre-sanitized) target -- targetsPackedItself only ever matches a
191
+ // plain npm name/source, never affected by safePackageTarget's URL-credential redaction.
192
+ // Only meaningful when a reload/restart is actually pending at all.
193
+ ...(status === "succeeded" && targetsPackedItself(target) ? { restartRequired: true } : {}),
184
194
  };
185
195
  }
186
196
 
@@ -235,6 +245,7 @@ export function parsePackageToolDetails(value: unknown): PackageToolDetails | un
235
245
  if (typeof candidate.status !== "string" || !MUTATION_STATUSES.has(candidate.status)) return undefined;
236
246
  if (!isShortString(candidate.target) || !isShortString(candidate.output) || typeof candidate.reloadRequired !== "boolean")
237
247
  return undefined;
248
+ if (candidate.restartRequired !== undefined && typeof candidate.restartRequired !== "boolean") return undefined;
238
249
  return value as MutationToolDetails;
239
250
  }
240
251
  } catch {
@@ -312,7 +323,9 @@ export function renderPackageToolResult(
312
323
  const statusColor = details.status === "succeeded" ? "success" : "warning";
313
324
  const lines = [`${theme.fg(statusColor, details.status === "succeeded" ? "✓" : "○")} ${details.operation} ${details.target}`];
314
325
  if (options.expanded && details.output) lines.push(details.output);
315
- if (details.reloadRequired) lines.push(theme.fg("warning", "Reload Pi with /reload to activate the update."));
326
+ if (details.restartRequired)
327
+ lines.push(theme.fg("warning", "Restart Pi (exit and relaunch) to activate -- Packed's own running code can't hot-reload itself."));
328
+ else if (details.reloadRequired) lines.push(theme.fg("warning", "Reload Pi with /reload to activate the update."));
316
329
  return lines.map((line) => truncateToWidth(line, safeWidth));
317
330
  },
318
331
  invalidate() {},
@@ -2,7 +2,7 @@
2
2
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { Type } from "typebox";
4
4
  import { type PackageOperation, packagePermissionDecision } from "./approval/permission.js";
5
- import { reloadWarning } from "./approval/reload.js";
5
+ import { reloadWarning, targetsPackedItself } from "./approval/reload.js";
6
6
  import { InstallServiceError, type Natives, PI_COMMAND_NAME } from "./packed.js";
7
7
  import {
8
8
  createInfoDetails,
@@ -28,6 +28,10 @@ export async function approvePackageOperation(
28
28
  command: string,
29
29
  natives: Pick<Natives, "security">,
30
30
  ctx: ApprovalContext,
31
+ // True only for a source/name that resolves to Packed's own npm package -- see
32
+ // targetsPackedItself(). Every caller below computes this from the exact string it's
33
+ // about to mutate, so the warning always reflects the real target.
34
+ restartRequired = false,
31
35
  ): Promise<{ allowed: boolean; approved: boolean; reason?: "cancelled" | "denied"; message?: string }> {
32
36
  const settings = await natives.security();
33
37
  const decision = packagePermissionDecision(settings, operation);
@@ -42,7 +46,7 @@ export async function approvePackageOperation(
42
46
  }
43
47
  const approved = await ctx.ui.confirm(
44
48
  `${operation[0]!.toUpperCase()}${operation.slice(1)} Pi package`,
45
- `Run: ${command}\n\nThis operation can execute package code or mutate Pi settings/install roots. ${reloadWarning(operation)} Continue?`,
49
+ `Run: ${command}\n\nThis operation can execute package code or mutate Pi settings/install roots. ${reloadWarning(operation, { restartRequired })} Continue?`,
46
50
  );
47
51
  return approved
48
52
  ? { allowed: true, approved: true }
@@ -54,12 +58,16 @@ export async function installPackageWithPolicy(
54
58
  natives: Pick<Natives, "security" | "install" | "installService">,
55
59
  ctx: ApprovalContext,
56
60
  ) {
57
- const approval = await approvePackageOperation("install", `pi install ${source}`, natives, ctx);
61
+ const restartRequired = targetsPackedItself(source);
62
+ const approval = await approvePackageOperation("install", `pi install ${source}`, natives, ctx, restartRequired);
58
63
  if (!approval.allowed) {
59
64
  const output = approval.message ?? "install denied";
60
65
  return text(output, createMutationDetails("install", source, approval.reason ?? "denied", output));
61
66
  }
62
- let output = (await natives.install(source, approval.approved)) || `Installed ${source}. Reload with /reload to activate.`;
67
+ const activateNote = restartRequired
68
+ ? "Restart Pi (exit and relaunch) to activate -- Packed's own running code can't hot-reload itself."
69
+ : "Reload with /reload to activate.";
70
+ let output = (await natives.install(source, approval.approved)) || `Installed ${source}. ${activateNote}`;
63
71
  // Piggybacks on the same approval already granted for install -- both are
64
72
  // the same code-execution mutation tier, not a new consent surface. Silent
65
73
  // for the overwhelmingly common case (most Pi packages aren't daemons at
@@ -79,33 +87,51 @@ export async function installPackageWithPolicy(
79
87
  return text(output, createMutationDetails("install", source, "succeeded", output));
80
88
  }
81
89
 
82
- export async function updatePackageWithPolicy(source: string, natives: Pick<Natives, "security" | "update">, ctx: ApprovalContext) {
83
- const approval = await approvePackageOperation("update", `pi update --extension ${source}`, natives, ctx);
90
+ export async function updatePackageWithPolicy(
91
+ source: string,
92
+ natives: Pick<Natives, "security" | "update">,
93
+ ctx: ApprovalContext,
94
+ target?: string,
95
+ ) {
96
+ const restartRequired = targetsPackedItself(source);
97
+ const command = target ? `pi remove ${source} && pi install ${target}` : `pi update --extension ${source}`;
98
+ const approval = await approvePackageOperation("update", command, natives, ctx, restartRequired);
84
99
  if (!approval.allowed) {
85
100
  const output = approval.message ?? "update denied";
86
101
  return text(output, createMutationDetails("update", source, approval.reason ?? "denied", output));
87
102
  }
88
- const outcome = await natives.update(source, approval.approved);
103
+ const outcome = await natives.update(source, approval.approved, target);
89
104
  if (outcome.alreadyUpToDate) {
90
105
  const version = outcome.currentVersion ?? outcome.previousVersion;
91
106
  const reason = outcome.pinned
92
- ? `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`
93
108
  : `already up to date${version ? ` at ${version}` : ""}`;
94
- 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}`;
95
113
  return text(message, createMutationDetails("update", source, "succeeded", outcome.output || message, false));
96
114
  }
97
115
  const transition = outcome.previousVersion && outcome.currentVersion ? ` (${outcome.previousVersion} → ${outcome.currentVersion})` : "";
98
- const message = `${outcome.output || `Updated ${source}.`}${transition} Reload with /reload to activate.`;
116
+ const activateNote = restartRequired
117
+ ? "Restart Pi (exit and relaunch) to activate -- Packed's own running code can't hot-reload itself."
118
+ : "Reload with /reload to activate.";
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}`;
99
121
  return text(message, createMutationDetails("update", source, "succeeded", outcome.output || message, true));
100
122
  }
101
123
 
102
124
  export async function removePackageWithPolicy(name: string, natives: Pick<Natives, "security" | "remove">, ctx: ApprovalContext) {
103
- const approval = await approvePackageOperation("remove", `pi remove npm:${name}`, natives, ctx);
125
+ const restartRequired = targetsPackedItself(name);
126
+ const approval = await approvePackageOperation("remove", `pi remove npm:${name}`, natives, ctx, restartRequired);
104
127
  if (!approval.allowed) {
105
128
  const output = approval.message ?? "remove denied";
106
129
  return text(output, createMutationDetails("remove", name, approval.reason ?? "denied", output));
107
130
  }
108
- const output = (await natives.remove(name, approval.approved)) || `Removed ${name}. Reload with /reload to deactivate.`;
131
+ const deactivateNote = restartRequired
132
+ ? "Restart Pi (exit and relaunch) to deactivate -- Packed's own running code can't hot-reload itself."
133
+ : "Reload with /reload to deactivate.";
134
+ const output = (await natives.remove(name, approval.approved)) || `Removed ${name}. ${deactivateNote}`;
109
135
  return text(output, createMutationDetails("remove", name, "succeeded", output));
110
136
  }
111
137
 
@@ -208,9 +234,15 @@ export function registerTools(pi: ExtensionAPI, natives: Natives): void {
208
234
  name: "pkg_update",
209
235
  label: "Pi Extension Update",
210
236
  description:
211
- "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.",
212
238
  parameters: Type.Object({
213
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
+ ),
214
246
  }),
215
247
  renderCall(args, theme) {
216
248
  return renderPackageToolCall("Update Pi extension", args, theme);
@@ -219,7 +251,7 @@ export function registerTools(pi: ExtensionAPI, natives: Natives): void {
219
251
  return renderPackageToolResult(result, options, theme, context);
220
252
  },
221
253
  async execute(_id, params, _signal, _onUpdate, ctx) {
222
- return updatePackageWithPolicy(params.source, natives, ctx);
254
+ return updatePackageWithPolicy(params.source, natives, ctx, params.target);
223
255
  },
224
256
  });
225
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.14",
3
+ "version": "0.22.0",
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
  }