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
« 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 -*-
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#============================================================================#
21''' OpenCode renderer implementation.
23 Provides path resolution and targeting mode validation for OpenCode,
24 which supports both per-user and per-project configuration.
25'''
28from . import __
29from .base import RENDERERS, ExplicitTargetMode, RendererBase
32class OpencodeRenderer( RendererBase ):
33 ''' Renderer for OpenCode coder.
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 '''
40 name = 'opencode'
41 modes_available = frozenset( ( 'per-user', 'per-project' ) )
42 mode_default = 'per-project'
43 memory_filename = 'AGENTS.md'
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.
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 )
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.
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'
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.
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 { }
103RENDERERS[ 'opencode' ] = OpencodeRenderer( )