@@ -2,9 +2,15 @@ import { embeddedFiles } from 'bun';
22import { existsSync , mkdirSync , writeFileSync } from 'node:fs' ;
33import { dirname , join } from 'node:path' ;
44import os from 'node:os' ;
5+ import { appDebug } from '../logging/logger.js' ;
56
67const METADATA_FILE = '.embedded.json' ;
78
9+ // Debug helper - logs to app-debug.log via the logger
10+ function embedDebug ( msg : string , ...args : unknown [ ] ) : void {
11+ appDebug ( `[Embed] ${ msg } ` , ...args ) ;
12+ }
13+
814type EmbeddedMetadata = {
915 version : string ;
1016 generatedAt : string ;
@@ -17,11 +23,20 @@ function getResourcesBaseDir(): string {
1723 return join ( os . homedir ( ) , '.codemachine' , 'resources' ) ;
1824}
1925
20- function setEnvVars ( targetDir : string ) : void {
26+ function setEnvVars ( targetDir : string , force = false ) : void {
2127 const pkgJsonPath = join ( targetDir , 'package.json' ) ;
22- process . env . CODEMACHINE_PACKAGE_ROOT ??= targetDir ;
23- process . env . CODEMACHINE_INSTALL_DIR ??= targetDir ;
24- process . env . CODEMACHINE_PACKAGE_JSON ??= pkgJsonPath ;
28+ if ( force ) {
29+ // For compiled binaries: force overwrite any stale env vars from dev sessions
30+ embedDebug ( 'Force setting env vars to: %s' , targetDir ) ;
31+ process . env . CODEMACHINE_PACKAGE_ROOT = targetDir ;
32+ process . env . CODEMACHINE_INSTALL_DIR = targetDir ;
33+ process . env . CODEMACHINE_PACKAGE_JSON = pkgJsonPath ;
34+ } else {
35+ // For dev mode: only set if not already set
36+ process . env . CODEMACHINE_PACKAGE_ROOT ??= targetDir ;
37+ process . env . CODEMACHINE_INSTALL_DIR ??= targetDir ;
38+ process . env . CODEMACHINE_PACKAGE_JSON ??= pkgJsonPath ;
39+ }
2540}
2641
2742/**
@@ -33,40 +48,76 @@ function setEnvVars(targetDir: string): void {
3348 * Returns the package root directory if resources are installed, or undefined in dev mode.
3449 */
3550export async function ensure ( ) : Promise < string | undefined > {
36- if ( process . env . DEBUG_EMBED ) {
37- console . error ( '[DEBUG] embeddedFiles.length:', embeddedFiles . length ) ;
38- }
51+ embedDebug ( 'ensure() called' ) ;
52+ embedDebug ( ' embeddedFiles.length: %s ', embeddedFiles . length ) ;
53+ embedDebug ( 'process.argv[1]: %s' , process . argv [ 1 ] ) ;
3954
4055 // Bun's embedded files are Blobs; cast to include name/text helpers for type safety
4156 const files = embeddedFiles as Array < Blob & { name : string ; text : ( ) => Promise < string > } > ;
4257
58+ // Log first few embedded file names for debugging
59+ if ( files . length > 0 ) {
60+ embedDebug ( 'First 5 embedded files: %s' , files . slice ( 0 , 5 ) . map ( f => f . name ) . join ( ', ' ) ) ;
61+ }
62+
4363 // Dev mode: no embedded files, return early (reads repo directly via package root resolver)
4464 if ( embeddedFiles . length === 0 ) {
65+ embedDebug ( 'No embedded files detected (dev mode), returning undefined' ) ;
4566 return undefined ;
4667 }
4768
69+ embedDebug ( 'Compiled binary detected (has %s embedded files)' , embeddedFiles . length ) ;
70+
71+ // Log env vars for debugging
72+ embedDebug ( 'CODEMACHINE_PACKAGE_ROOT: %s' , process . env . CODEMACHINE_PACKAGE_ROOT ?? '(not set)' ) ;
73+ embedDebug ( 'CODEMACHINE_INSTALL_DIR: %s' , process . env . CODEMACHINE_INSTALL_DIR ?? '(not set)' ) ;
74+ embedDebug ( 'CODEMACHINE_PACKAGE_JSON: %s' , process . env . CODEMACHINE_PACKAGE_JSON ?? '(not set)' ) ;
75+
4876 // Compiled binary: check for existing installation via env vars
77+ // IMPORTANT: For compiled binaries, we should NOT use env vars that might be left over
78+ // from dev mode. Only check the resources directory.
4979 const existingRoot =
5080 process . env . CODEMACHINE_PACKAGE_ROOT ??
5181 process . env . CODEMACHINE_INSTALL_DIR ??
5282 ( process . env . CODEMACHINE_PACKAGE_JSON && dirname ( process . env . CODEMACHINE_PACKAGE_JSON ) ) ;
5383
54- if ( existingRoot && existsSync ( existingRoot ) ) {
55- return existingRoot ;
84+ embedDebug ( 'existingRoot resolved to: %s' , existingRoot ?? '(none)' ) ;
85+
86+ if ( existingRoot ) {
87+ const exists = existsSync ( existingRoot ) ;
88+ embedDebug ( 'existingRoot exists: %s' , exists ) ;
89+
90+ // Check if this looks like a valid resources directory (has .embedded.json)
91+ // or if it's just a stale env var pointing to dev directory
92+ const metadataInExisting = join ( existingRoot , METADATA_FILE ) ;
93+ const hasMetadata = existsSync ( metadataInExisting ) ;
94+ embedDebug ( 'existingRoot has .embedded.json: %s' , hasMetadata ) ;
95+
96+ if ( exists && hasMetadata ) {
97+ embedDebug ( 'Using existing installation at: %s' , existingRoot ) ;
98+ return existingRoot ;
99+ } else if ( exists && ! hasMetadata ) {
100+ embedDebug ( 'existingRoot exists but has no .embedded.json - likely stale dev env var, continuing to extract' ) ;
101+ }
56102 }
57103
58104 // Get version from embedded package.json (may have ./ prefix)
59105 const pkgFile = files . find ( ( f ) =>
60106 f . name === 'package.json' || f . name === './package.json'
61107 ) ;
108+ embedDebug ( 'Found embedded package.json: %s' , pkgFile ? pkgFile . name : '(not found)' ) ;
109+
62110 let version = process . env . CODEMACHINE_VERSION ;
111+ embedDebug ( 'CODEMACHINE_VERSION env var: %s' , version ?? '(not set)' ) ;
63112
64113 if ( ! version && pkgFile ) {
65114 try {
66115 const pkgText = await pkgFile . text ( ) ;
67116 const pkg = JSON . parse ( pkgText ) ;
68117 version = pkg . version ;
69- } catch {
118+ embedDebug ( 'Version from embedded package.json: %s' , version ) ;
119+ } catch ( err ) {
120+ embedDebug ( 'Failed to parse embedded package.json: %s' , err ) ;
70121 version = 'unknown' ;
71122 }
72123 }
@@ -75,36 +126,57 @@ export async function ensure(): Promise<string | undefined> {
75126 const targetRoot = join ( baseDir , version || 'unknown' ) ;
76127 const metadataPath = join ( targetRoot , METADATA_FILE ) ;
77128
129+ embedDebug ( 'Resources base dir: %s' , baseDir ) ;
130+ embedDebug ( 'Target root: %s' , targetRoot ) ;
131+ embedDebug ( 'Metadata path: %s' , metadataPath ) ;
132+
78133 // Already installed?
79- if ( existsSync ( metadataPath ) ) {
80- setEnvVars ( targetRoot ) ;
134+ const metadataExists = existsSync ( metadataPath ) ;
135+ embedDebug ( 'Metadata file exists: %s' , metadataExists ) ;
136+
137+ if ( metadataExists ) {
138+ embedDebug ( 'Resources already installed, setting env vars and returning' ) ;
139+ setEnvVars ( targetRoot , true ) ; // force=true for compiled binary
81140 return targetRoot ;
82141 }
83142
84143 // First-time install: extract all resources
144+ embedDebug ( 'First-time install: extracting %s files to %s' , files . length , targetRoot ) ;
145+
146+ let extractedCount = 0 ;
147+ let errorCount = 0 ;
148+
85149 for ( const file of files ) {
86150 // Remove leading ./ if present
87151 const cleanName = file . name . startsWith ( './' ) ? file . name . slice ( 2 ) : file . name ;
88152 const destPath = join ( targetRoot , cleanName ) ;
89153
90- if ( process . env . DEBUG_EMBED ) {
91- console . error ( `[DEBUG] Extracting ${ cleanName } ` ) ;
154+ try {
155+ mkdirSync ( dirname ( destPath ) , { recursive : true } ) ;
156+ await Bun . write ( destPath , file ) ;
157+ extractedCount ++ ;
158+ embedDebug ( 'Extracted: %s' , cleanName ) ;
159+ } catch ( err ) {
160+ errorCount ++ ;
161+ embedDebug ( 'Failed to extract %s: %s' , cleanName , err ) ;
92162 }
93-
94- mkdirSync ( dirname ( destPath ) , { recursive : true } ) ;
95- await Bun . write ( destPath , file ) ;
96163 }
97164
165+ embedDebug ( 'Extraction complete: %s succeeded, %s failed' , extractedCount , errorCount ) ;
166+
98167 // Write metadata
99168 const metadata : EmbeddedMetadata = {
100169 version : version || 'unknown' ,
101170 generatedAt : new Date ( ) . toISOString ( ) ,
102171 source : 'embedded' ,
103172 } ;
104173
174+ embedDebug ( 'Writing metadata file' ) ;
105175 mkdirSync ( targetRoot , { recursive : true } ) ;
106176 writeFileSync ( metadataPath , JSON . stringify ( metadata , null , 2 ) ) ;
177+ embedDebug ( 'Metadata written successfully' ) ;
107178
108- setEnvVars ( targetRoot ) ;
179+ setEnvVars ( targetRoot , true ) ; // force=true for compiled binary
180+ embedDebug ( 'Env vars set (forced), returning targetRoot: %s' , targetRoot ) ;
109181 return targetRoot ;
110182}
0 commit comments