Coverage for sources/agentsmgr/renderers/opencode.py: 26%

30 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-13 00:43 +0000

1# vim: set filetype=python fileencoding=utf-8: 

2# -*- coding: utf-8 -*- 

3 

4#============================================================================# 

5# # 

6# Licensed under the Apache License, Version 2.0 (the "License"); # 

7# you may not use this file except in compliance with the License. # 

8# You may obtain a copy of the License at # 

9# # 

10# http://www.apache.org/licenses/LICENSE-2.0 # 

11# # 

12# Unless required by applicable law or agreed to in writing, software # 

13# distributed under the License is distributed on an "AS IS" BASIS, # 

14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

15# See the License for the specific language governing permissions and # 

16# limitations under the License. # 

17# # 

18#============================================================================# 

19 

20 

21''' OpenCode renderer implementation. 

22 

23 Provides path resolution and targeting mode validation for OpenCode, 

24 which supports both per-user and per-project configuration. 

25''' 

26 

27 

28from . import __ 

29from .base import RENDERERS, ExplicitTargetMode, RendererBase 

30 

31 

32class OpencodeRenderer( RendererBase ): 

33 ''' Renderer for OpenCode coder. 

34 

35 Supports both per-user and per-project configuration modes. 

36 Per-user mode respects OPENCODE_CONFIG environment variable 

37 with fallback to configuration overrides and XDG-like default. 

38 ''' 

39 

40 name = 'opencode' 

41 modes_available = frozenset( ( 'per-user', 'per-project' ) ) 

42 mode_default = 'per-project' 

43 memory_filename = 'AGENTS.md' 

44 

45 def resolve_base_directory( 

46 self, 

47 mode: ExplicitTargetMode, 

48 target: __.Path, 

49 configuration: __.cabc.Mapping[ str, __.typx.Any ], 

50 environment: __.cabc.Mapping[ str, str ], 

51 ) -> __.Path: 

52 ''' Resolves base output directory for OpenCode. 

53 

54 For per-project mode, returns .opencode in project root. 

55 For per-user mode, respects precedence: OPENCODE_CONFIG 

56 environment variable, configuration file override, or 

57 XDG-like ~/.config/opencode default. 

58 ''' 

59 self.validate_mode( mode ) 

60 if mode == 'per-project': 

61 return target / ".auxiliary/configuration/coders/opencode" 

62 if mode == 'per-user': 

63 return self._resolve_user_directory( configuration, environment ) 

64 raise __.TargetModeNoSupport( self.name, mode ) 

65 

66 def _resolve_user_directory( 

67 self, 

68 configuration: __.cabc.Mapping[ str, __.typx.Any ], 

69 environment: __.cabc.Mapping[ str, str ], 

70 ) -> __.Path: 

71 ''' Resolves per-user directory following precedence rules. 

72 

73 Precedence order: 

74 1. OPENCODE_CONFIG environment variable (directory containing 

75 opencode.json settings file) 

76 2. Configuration file override (directory for this coder) 

77 3. XDG-like default ~/.config/opencode 

78 ''' 

79 if 'OPENCODE_CONFIG' in environment: 

80 directory = __.Path( environment[ 'OPENCODE_CONFIG' ] ) 

81 return directory.expanduser( ) 

82 coder_configuration = self._extract_coder_configuration( 

83 configuration ) 

84 if 'directory' in coder_configuration: 

85 directory = __.Path( coder_configuration[ 'directory' ] ) 

86 return directory.expanduser( ) 

87 return __.Path.home( ) / '.config' / 'opencode' 

88 

89 def _extract_coder_configuration( 

90 self, configuration: __.cabc.Mapping[ str, __.typx.Any ] 

91 ) -> __.cabc.Mapping[ str, __.typx.Any ]: 

92 ''' Extracts configuration for this specific coder. 

93 

94 Looks for coder entry in configuration coders array by name. 

95 ''' 

96 coders = configuration.get( 'coders', ( ) ) 

97 for coder in coders: 

98 if coder.get( 'name' ) == self.name: 

99 return coder 

100 return { } 

101 

102 

103RENDERERS[ 'opencode' ] = OpencodeRenderer( )