Coverage for sources / agentsmgr / renderers / base.py: 50%
26 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-30 00:03 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-30 00:03 +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''' Coder renderer base class and type definitions.
23 Defines base class for coder-specific renderers which handle
24 path resolution, targeting mode validation, and output structure
25 for different AI coding assistants.
26'''
29from . import __
32TargetMode: __.typx.TypeAlias = __.typx.Literal[
33 'default', 'per-user', 'per-project', 'nowhere' ]
34ExplicitTargetMode: __.typx.TypeAlias = __.typx.Literal[
35 'per-user', 'per-project' ]
38class RendererBase( __.immut.Object ):
39 ''' Base class for coder-specific rendering and path resolution.
41 Provides interface that all coder renderers must implement for
42 coder-specific behavior including targeting mode validation and
43 path resolution for output files.
44 '''
46 name: str
47 modes_available: frozenset[ ExplicitTargetMode ]
48 mode_default: ExplicitTargetMode
49 memory_filename: str
51 def validate_mode( self, mode: ExplicitTargetMode ) -> None:
52 ''' Validates targeting mode is supported by this coder.
54 Raises TargetModeNoSupport if mode not supported.
55 '''
56 if mode not in self.modes_available:
57 raise __.TargetModeNoSupport( self.name, mode )
59 def resolve_base_directory(
60 self,
61 mode: ExplicitTargetMode,
62 target: __.Path,
63 configuration: __.cabc.Mapping[ str, __.typx.Any ],
64 environment: __.cabc.Mapping[ str, str ],
65 ) -> __.Path:
66 ''' Resolves base output directory for this coder.
68 Determines appropriate output location based on targeting mode,
69 respecting precedence of environment variables over file
70 configuration over coder defaults. For per-user mode, checks
71 environment first, then configuration file overrides, then
72 falls back to coder-specific defaults. For per-project mode,
73 constructs path within project structure.
74 '''
75 raise NotImplementedError
77 def produce_output_structure(
78 self, item_type: str, category: __.Absential[ str ] = __.absent
79 ) -> str:
80 ''' Produces subdirectory structure for item type.
82 Translates generic item type to coder-specific directory
83 structure with optional category-based organization. Most
84 coders use same structure, but some may have different
85 conventions. Category enables hierarchical organization
86 (e.g., commands/deploy/kubernetes for nested structure).
87 '''
88 dirname = self.calculate_directory_location( item_type )
89 if __.is_absent( category ): return dirname
90 return f"{dirname}/{category}"
92 def calculate_directory_location( self, item_type: str ) -> str:
93 ''' Returns directory name for item type. Override in subclasses. '''
94 return item_type
96 def get_template_flavor( self, item_type: str ) -> str:
97 ''' Determines template flavor (pioneering coder name) for item type.
99 Returns the name of the pioneering coder whose template format
100 should be used for this item type. For example, Claude pioneered
101 the markdown command format, Gemini pioneered the TOML format.
102 Each coder specifies which flavor it uses for each item type.
103 '''
104 return 'claude'
106 def provide_project_symlinks(
107 self, target: __.Path
108 ) -> __.cabc.Sequence[ tuple[ __.Path, __.Path ] ]:
109 ''' Provides symlinks required for coder in per-project mode.
111 Returns sequence of (source, link_path) tuples where source
112 is the target path and link_path is where the symlink should
113 be created. Default implementation returns base symlink from
114 .auxiliary/configuration/coders/{coder_name} to .{coder_name}.
116 Subclasses may override to provide additional coder-specific
117 symlinks (e.g., Claude's .mcp.json, OpenCode's opencode.jsonc).
118 '''
119 source = (
120 target / '.auxiliary' / 'configuration' / 'coders' / self.name )
121 link_path = target / f'.{self.name}'
122 return [ ( source, link_path ) ]
125RENDERERS: __.accret.Dictionary[ str, RendererBase ] = (
126 __.accret.Dictionary( ) )