@@ -3,13 +3,14 @@ import { join, resolve } from 'node:path';
33import yaml from 'js-yaml' ;
44import { loadAgentManifest , loadFileIfExists } from '../utils/loader.js' ;
55import { loadAllSkills , getAllowedTools } from '../utils/skill-loader.js' ;
6+ import { buildComplianceSection } from './shared.js' ;
67
78/**
89 * Export a gitagent to OpenCode format.
910 *
1011 * OpenCode (sst/opencode) uses:
11- * - .opencode/instructions. md (custom agent instructions)
12- * - opencode.json (project configuration)
12+ * - AGENTS. md (custom agent instructions, project root )
13+ * - opencode.json (project configuration)
1314 *
1415 * Returns structured output with all files that should be written.
1516 */
@@ -35,7 +36,7 @@ export function exportToOpenCodeString(dir: string): string {
3536 const exp = exportToOpenCode ( dir ) ;
3637 const parts : string [ ] = [ ] ;
3738
38- parts . push ( '# === .opencode/instructions .md ===' ) ;
39+ parts . push ( '# === AGENTS .md ===' ) ;
3940 parts . push ( exp . instructions ) ;
4041 parts . push ( '\n# === opencode.json ===' ) ;
4142 parts . push ( JSON . stringify ( exp . config , null , 2 ) ) ;
@@ -177,8 +178,12 @@ function buildConfig(manifest: ReturnType<typeof loadAgentManifest>): Record<str
177178 if ( manifest . model ?. preferred ) {
178179 const model = manifest . model . preferred ;
179180 const provider = inferProvider ( model ) ;
180- config . provider = provider ;
181- config . model = model ;
181+ config . model = `${ provider } /${ model } ` ;
182+ config . provider = {
183+ [ provider ] : {
184+ npm : getNpmPackage ( provider ) ,
185+ } ,
186+ } ;
182187 }
183188
184189 return config ;
@@ -193,65 +198,13 @@ function inferProvider(model: string): string {
193198 return 'openai' ;
194199}
195200
196- function buildComplianceSection ( compliance : NonNullable < ReturnType < typeof loadAgentManifest > [ 'compliance' ] > ) : string {
197- const c = compliance ;
198- const constraints : string [ ] = [ ] ;
199-
200- if ( c . supervision ?. human_in_the_loop === 'always' ) {
201- constraints . push ( '- All decisions require human approval before execution' ) ;
202- }
203- if ( c . supervision ?. escalation_triggers ) {
204- constraints . push ( '- Escalate to human supervisor when:' ) ;
205- for ( const trigger of c . supervision . escalation_triggers ) {
206- for ( const [ key , value ] of Object . entries ( trigger ) ) {
207- constraints . push ( ` - ${ key } : ${ value } ` ) ;
208- }
209- }
210- }
211- if ( c . communications ?. fair_balanced ) {
212- constraints . push ( '- All communications must be fair and balanced (FINRA 2210)' ) ;
213- }
214- if ( c . communications ?. no_misleading ) {
215- constraints . push ( '- Never make misleading, exaggerated, or promissory statements' ) ;
216- }
217- if ( c . data_governance ?. pii_handling === 'redact' ) {
218- constraints . push ( '- Redact all PII from outputs' ) ;
219- }
220- if ( c . data_governance ?. pii_handling === 'prohibit' ) {
221- constraints . push ( '- Do not process any personally identifiable information' ) ;
222- }
223-
224- if ( c . segregation_of_duties ) {
225- const sod = c . segregation_of_duties ;
226- constraints . push ( '- Segregation of duties is enforced:' ) ;
227- if ( sod . assignments ) {
228- for ( const [ agentName , roles ] of Object . entries ( sod . assignments ) ) {
229- constraints . push ( ` - Agent "${ agentName } " has role(s): ${ roles . join ( ', ' ) } ` ) ;
230- }
231- }
232- if ( sod . conflicts ) {
233- constraints . push ( '- Duty separation rules (no single agent may hold both):' ) ;
234- for ( const [ a , b ] of sod . conflicts ) {
235- constraints . push ( ` - ${ a } and ${ b } ` ) ;
236- }
237- }
238- if ( sod . handoffs ) {
239- constraints . push ( '- The following actions require multi-agent handoff:' ) ;
240- for ( const h of sod . handoffs ) {
241- constraints . push ( ` - ${ h . action } : must pass through roles ${ h . required_roles . join ( ' → ' ) } ${ h . approval_required !== false ? ' (approval required)' : '' } ` ) ;
242- }
243- }
244- if ( sod . isolation ?. state === 'full' ) {
245- constraints . push ( '- Agent state/memory is fully isolated per role' ) ;
246- }
247- if ( sod . isolation ?. credentials === 'separate' ) {
248- constraints . push ( '- Credentials are segregated per role' ) ;
249- }
250- if ( sod . enforcement === 'strict' ) {
251- constraints . push ( '- SOD enforcement is STRICT — violations will block execution' ) ;
252- }
253- }
254-
255- if ( constraints . length === 0 ) return '' ;
256- return `## Compliance Constraints\n\n${ constraints . join ( '\n' ) } ` ;
201+ function getNpmPackage ( provider : string ) : string {
202+ const packages : Record < string , string > = {
203+ anthropic : '@ai-sdk/anthropic' ,
204+ openai : '@ai-sdk/openai' ,
205+ google : '@ai-sdk/google' ,
206+ deepseek : '@ai-sdk/deepseek' ,
207+ ollama : '@ai-sdk/ollama' ,
208+ } ;
209+ return packages [ provider ] || `@ai-sdk/${ provider } ` ;
257210}
0 commit comments