@@ -44,6 +44,8 @@ struct PullFunctionRow {
4444 #[ serde( default ) ]
4545 function_data : Option < Value > ,
4646 #[ serde( default ) ]
47+ environments : Option < Value > ,
48+ #[ serde( default ) ]
4749 created : Option < String > ,
4850 #[ serde( default ) ]
4951 _xact_id : Option < String > ,
@@ -64,6 +66,7 @@ struct NormalizedPrompt {
6466 tools : Option < Value > ,
6567 raw_tools_json : Option < String > ,
6668 tool_functions : Option < Value > ,
69+ environments : Option < Value > ,
6770}
6871
6972#[ derive( Debug ) ]
@@ -1065,6 +1068,11 @@ fn normalize_prompt_row(row: &PullFunctionRow) -> Result<NormalizedPrompt> {
10651068 . get ( "tool_functions" )
10661069 . filter ( |value| !is_empty_render_value ( value) )
10671070 . cloned ( ) ;
1071+ let environments = row
1072+ . environments
1073+ . as_ref ( )
1074+ . or_else ( || prompt_data. get ( "environments" ) )
1075+ . and_then ( normalize_environment_slugs) ;
10681076 let version = row
10691077 . _xact_id
10701078 . as_deref ( )
@@ -1086,6 +1094,7 @@ fn normalize_prompt_row(row: &PullFunctionRow) -> Result<NormalizedPrompt> {
10861094 tools,
10871095 raw_tools_json,
10881096 tool_functions,
1097+ environments,
10891098 } )
10901099}
10911100
@@ -1171,6 +1180,12 @@ fn render_project_file_ts(
11711180 format_ts_value( tool_functions, 2 )
11721181 ) ) ;
11731182 }
1183+ if let Some ( environments) = & row. environments {
1184+ body_lines. push ( format ! (
1185+ " environments: {}," ,
1186+ format_ts_value( environments, 2 )
1187+ ) ) ;
1188+ }
11741189
11751190 out. push_str ( & format ! (
11761191 "export const {var_name} = project.prompts.create({{\n "
@@ -1268,6 +1283,12 @@ fn render_project_file_py(
12681283 format_py_value( tool_functions, 4 )
12691284 ) ) ;
12701285 }
1286+ if let Some ( environments) = & row. environments {
1287+ out. push_str ( & format ! (
1288+ " environments={},\n " ,
1289+ format_py_value( environments, 4 )
1290+ ) ) ;
1291+ }
12711292 out. push_str ( ")\n \n " ) ;
12721293 }
12731294
@@ -1444,6 +1465,30 @@ fn should_unquote_object_key(key: &str) -> bool {
14441465 chars. all ( |ch| ch == '$' || ch == '_' || ch. is_ascii_alphanumeric ( ) )
14451466}
14461467
1468+ fn normalize_environment_slugs ( value : & Value ) -> Option < Value > {
1469+ let items = value. as_array ( ) ?;
1470+ let mut slugs = Vec :: new ( ) ;
1471+ for item in items {
1472+ let slug = item
1473+ . as_object ( )
1474+ . and_then ( |object| object. get ( "slug" ) )
1475+ . and_then ( Value :: as_str)
1476+ . or_else ( || item. as_str ( ) )
1477+ . map ( str:: trim)
1478+ . filter ( |value| !value. is_empty ( ) )
1479+ . map ( ToOwned :: to_owned) ;
1480+ if let Some ( slug) = slug {
1481+ slugs. push ( Value :: String ( slug) ) ;
1482+ }
1483+ }
1484+
1485+ if slugs. is_empty ( ) {
1486+ None
1487+ } else {
1488+ Some ( Value :: Array ( slugs) )
1489+ }
1490+ }
1491+
14471492fn is_empty_render_value ( value : & Value ) -> bool {
14481493 match value {
14491494 Value :: Null => true ,
@@ -1600,6 +1645,7 @@ mod tests {
16001645 description : None ,
16011646 prompt_data : None ,
16021647 function_data : None ,
1648+ environments : None ,
16031649 created : None ,
16041650 _xact_id : None ,
16051651 } ;
@@ -1631,6 +1677,7 @@ mod tests {
16311677 description: None ,
16321678 prompt_data: None ,
16331679 function_data: None ,
1680+ environments: None ,
16341681 created: None ,
16351682 _xact_id: None ,
16361683 } ,
@@ -1643,6 +1690,7 @@ mod tests {
16431690 description: None ,
16441691 prompt_data: None ,
16451692 function_data: None ,
1693+ environments: None ,
16461694 created: None ,
16471695 _xact_id: None ,
16481696 } ,
@@ -1655,6 +1703,7 @@ mod tests {
16551703 description: None ,
16561704 prompt_data: None ,
16571705 function_data: None ,
1706+ environments: None ,
16581707 created: None ,
16591708 _xact_id: None ,
16601709 } ,
@@ -1689,6 +1738,7 @@ mod tests {
16891738 description : None ,
16901739 prompt_data : None ,
16911740 function_data : None ,
1741+ environments : None ,
16921742 created : None ,
16931743 _xact_id : None ,
16941744 } ;
@@ -1715,6 +1765,7 @@ mod tests {
17151765 description : None ,
17161766 prompt_data : None ,
17171767 function_data : None ,
1768+ environments : None ,
17181769 created : None ,
17191770 _xact_id : None ,
17201771 } ;
@@ -1787,6 +1838,10 @@ mod tests {
17871838 ]
17881839 } ) ) ,
17891840 function_data : Some ( serde_json:: json!( { "type" : "prompt" } ) ) ,
1841+ environments : Some ( serde_json:: json!( [
1842+ { "slug" : "staging" } ,
1843+ { "slug" : "production" }
1844+ ] ) ) ,
17901845 created : None ,
17911846 _xact_id : Some ( "123" . to_string ( ) ) ,
17921847 } ;
@@ -1809,6 +1864,9 @@ mod tests {
18091864 assert ! ( rendered. contains( " version=\" 123\" ," ) ) ;
18101865 assert ! ( rendered. contains( "messages=[" ) ) ;
18111866 assert ! ( rendered. contains( "model=\" gpt-4o-mini\" " ) ) ;
1867+ assert ! ( rendered. contains( "environments=[" ) ) ;
1868+ assert ! ( rendered. contains( "\" staging\" " ) ) ;
1869+ assert ! ( rendered. contains( "\" production\" " ) ) ;
18121870 }
18131871
18141872 #[ test]
@@ -1832,6 +1890,9 @@ mod tests {
18321890 }
18331891 } ) ) ,
18341892 function_data : Some ( serde_json:: json!( { "type" : "prompt" } ) ) ,
1893+ environments : Some ( serde_json:: json!( [
1894+ { "slug" : "test-env" }
1895+ ] ) ) ,
18351896 created : None ,
18361897 _xact_id : Some ( "123" . to_string ( ) ) ,
18371898 } ;
@@ -1851,6 +1912,23 @@ mod tests {
18511912 assert ! ( rendered. contains( "export const basicMath = project.prompts.create({" ) ) ;
18521913 assert ! ( rendered. contains( " id: \" f1\" ," ) ) ;
18531914 assert ! ( rendered. contains( " version: \" 123\" ," ) ) ;
1915+ assert ! ( rendered. contains( "environments: [" ) ) ;
1916+ assert ! ( rendered. contains( "\" test-env\" " ) ) ;
1917+ }
1918+
1919+ #[ test]
1920+ fn normalize_environment_slugs_supports_objects_and_strings ( ) {
1921+ let raw = serde_json:: json!( [
1922+ { "slug" : " staging " } ,
1923+ "production" ,
1924+ { "slug" : "" } ,
1925+ { "foo" : "bar" }
1926+ ] ) ;
1927+
1928+ assert_eq ! (
1929+ normalize_environment_slugs( & raw) ,
1930+ Some ( serde_json:: json!( [ "staging" , "production" ] ) )
1931+ ) ;
18541932 }
18551933
18561934 #[ test]
0 commit comments