@@ -20,11 +20,6 @@ function requiredString(name) {
2020 return value
2121}
2222
23- function optionalString ( name ) {
24- const value = process . env [ name ] ?. trim ( ) ?? ""
25- return value || undefined
26- }
27-
2823function booleanEnv ( name ) {
2924 return process . env [ name ] === "true"
3025}
@@ -37,22 +32,39 @@ function numberEnv(name) {
3732 return value
3833}
3934
35+ const MAX_OUTPUT_CHARS = 8192
36+
4037function output ( name , value ) {
41- appendFileSync ( process . env . GITHUB_OUTPUT , `${ name } <<__WP_CODEBOX_OUTPUT__\n${ String ( value ) } \n__WP_CODEBOX_OUTPUT__\n` )
38+ const rendered = String ( value )
39+ if ( rendered . length > MAX_OUTPUT_CHARS ) throw new Error ( `${ name } exceeds the ${ MAX_OUTPUT_CHARS } -character workflow output limit.` )
40+ appendFileSync ( process . env . GITHUB_OUTPUT , `${ name } <<__WP_CODEBOX_OUTPUT__\n${ rendered } \n__WP_CODEBOX_OUTPUT__\n` )
4241}
4342
44- const artifactDeclarations = parseJson ( "ARTIFACT_DECLARATIONS" , [ ] , "array" )
45- const runnerRecipe = optionalString ( "RUNNER_RECIPE" )
46- const runAgent = booleanEnv ( "RUN_AGENT" )
47- const dryRun = booleanEnv ( "DRY_RUN" )
43+ function repositoryList ( name ) {
44+ const repositories = ( process . env [ name ] || "" ) . split ( "," ) . map ( ( value ) => value . trim ( ) ) . filter ( Boolean )
45+ if ( repositories . some ( ( repository ) => ! / ^ [ A - Z a - z 0 - 9 _ . - ] + \/ [ A - Z a - z 0 - 9 _ . - ] + $ / . test ( repository ) ) ) {
46+ throw new Error ( `${ name } must contain comma-separated OWNER/REPO values.` )
47+ }
48+ return repositories
49+ }
4850
49- if ( ! runnerRecipe && runAgent && ! dryRun ) {
50- throw new Error ( "RUNNER_RECIPE may be omitted only when RUN_AGENT=false or DRY_RUN=true. The executable workflow in wp-codebox PR #1751 must land before a live agent run can omit it." )
51+ function commandList ( name ) {
52+ const value = parseJson ( name , [ ] , "array" )
53+ return value . map ( ( entry , index ) => {
54+ if ( typeof entry === "string" && entry . trim ( ) ) return { command : entry . trim ( ) , description : entry . trim ( ) }
55+ if ( ! entry || typeof entry !== "object" || Array . isArray ( entry ) || typeof entry . command !== "string" || ! entry . command . trim ( ) ) {
56+ throw new Error ( `${ name } [${ index } ] must be a non-empty command string or an object with a non-empty command.` )
57+ }
58+ if ( entry . description !== undefined && ( typeof entry . description !== "string" || ! entry . description . trim ( ) ) ) {
59+ throw new Error ( `${ name } [${ index } ].description must be a non-empty string when provided.` )
60+ }
61+ return { command : entry . command . trim ( ) , description : typeof entry . description === "string" ? entry . description . trim ( ) : entry . command . trim ( ) }
62+ } )
5163}
5264
65+ const artifactDeclarations = parseJson ( "ARTIFACT_DECLARATIONS" , [ ] , "array" )
5366const request = {
5467 schema : "wp-codebox/agent-task-workflow-request/v1" ,
55- ...( runnerRecipe ? { runner_recipe : runnerRecipe } : { } ) ,
5668 agent_bundle : requiredString ( "AGENT_BUNDLE" ) ,
5769 workload : {
5870 id : process . env . WORKLOAD_ID || "agent-task" ,
@@ -68,23 +80,18 @@ const request = {
6880 } ,
6981 runner_workspace : parseJson ( "RUNNER_WORKSPACE_CONFIG" , { } , "object" ) ,
7082 validation_dependencies : process . env . VALIDATION_DEPENDENCIES || "" ,
71- context_repositories : parseJson ( "CONTEXT_REPOSITORIES" , [ ] , "array" ) ,
72- verification_commands : parseJson ( "VERIFICATION_COMMANDS" , [ ] , "array" ) ,
73- drift_checks : parseJson ( "DRIFT_CHECKS" , [ ] , "array" ) ,
74- workspace_contract_checks : parseJson ( "WORKSPACE_CONTRACT_CHECKS" , { } , "object" ) ,
75- actions_artifact_downloads : parseJson ( "ACTIONS_ARTIFACT_DOWNLOADS" , [ ] , "array" ) ,
83+ verification_commands : commandList ( "VERIFICATION_COMMANDS" ) ,
84+ drift_checks : commandList ( "DRIFT_CHECKS" ) ,
7685 success : {
7786 requires_pr : booleanEnv ( "SUCCESS_REQUIRES_PR" ) ,
78- completion_outcomes : parseJson ( "SUCCESS_COMPLETION_OUTCOMES" , [ ] , "array" ) ,
7987 } ,
8088 access : {
81- access_token_repos : process . env . ACCESS_TOKEN_REPOS || process . env . TARGET_REPO || "" ,
89+ access_token_repos : repositoryList ( " ACCESS_TOKEN_REPOS" ) ,
8290 require_access_token : booleanEnv ( "REQUIRE_ACCESS_TOKEN" ) ,
8391 allowed_repos : parseJson ( "ALLOWED_REPOS" , [ ] , "array" ) ,
8492 } ,
8593 limits : {
8694 max_turns : numberEnv ( "MAX_TURNS" ) ,
87- step_budget : numberEnv ( "STEP_BUDGET" ) ,
8895 time_budget_ms : numberEnv ( "TIME_BUDGET_MS" ) ,
8996 } ,
9097 artifacts : {
@@ -94,48 +101,29 @@ const request = {
94101 replay_bundle_name : process . env . REPLAY_BUNDLE_ARTIFACT_NAME || "" ,
95102 } ,
96103 outputs : {
97- tool_results_key : process . env . TOOL_RESULTS_KEY || "tool_results" ,
98104 projections : parseJson ( "OUTPUT_PROJECTIONS" , { } , "object" ) ,
99105 } ,
100106 callback_data : parseJson ( "CALLBACK_DATA" , { } , "object" ) ,
101- run_agent : runAgent ,
102- dry_run : dryRun ,
107+ run_agent : booleanEnv ( "RUN_AGENT" ) ,
108+ dry_run : booleanEnv ( "DRY_RUN" ) ,
103109}
104110
105- const runId = `${ request . workload . id } -${ process . env . GITHUB_RUN_ID || "local" } ` . replace ( / [ ^ A - Z a - z 0 - 9 . _ - ] + / g, "-" )
106- const status = ! request . run_agent ? "skipped" : request . dry_run ? "dry-run" : "planned"
107- const result = {
108- schema : "wp-codebox/agent-task-workflow-result/v1" ,
109- run_id : runId ,
110- status,
111- request_path : ".codebox/agent-task-request.json" ,
112- transcript : {
113- artifact_name : request . artifacts . transcript_name ,
114- } ,
115- artifacts : {
116- declarations : artifactDeclarations ,
117- expected : request . artifacts . expected ,
118- replay_bundle_name : request . artifacts . replay_bundle_name ,
119- } ,
120- outputs : {
121- engine_data : { } ,
122- projections : request . outputs . projections ,
123- } ,
124- access : {
125- credential_mode : request . access . require_access_token ? "app-token" : "default" ,
126- } ,
111+ if ( request . access . allowed_repos . some ( ( repository ) => typeof repository !== "string" || ! / ^ [ A - Z a - z 0 - 9 _ . - ] + \/ [ A - Z a - z 0 - 9 _ . - ] + $ / . test ( repository ) ) ) {
112+ throw new Error ( "ALLOWED_REPOS must be a JSON array of OWNER/REPO values." )
113+ }
114+ request . access . allowed_repos = [ ...new Set ( request . access . allowed_repos . map ( ( repository ) => repository . toLowerCase ( ) ) ) ]
115+ request . access . access_token_repos = [ ...new Set ( request . access . access_token_repos . map ( ( repository ) => repository . toLowerCase ( ) ) ) ]
116+ request . target_repo = request . target_repo . toLowerCase ( )
117+ if ( ! request . access . allowed_repos . includes ( request . target_repo ) ) {
118+ throw new Error ( "ALLOWED_REPOS must explicitly include TARGET_REPO." )
119+ }
120+ if ( ! request . access . access_token_repos . includes ( request . target_repo ) ) {
121+ throw new Error ( "ACCESS_TOKEN_REPOS must explicitly include TARGET_REPO." )
127122}
128123
124+ const runId = `${ request . workload . id } -${ process . env . GITHUB_RUN_ID || "local" } ` . replace ( / [ ^ A - Z a - z 0 - 9 . _ - ] + / g, "-" )
129125mkdirSync ( ".codebox" , { recursive : true } )
130126writeFileSync ( ".codebox/agent-task-request.json" , `${ JSON . stringify ( request , null , 2 ) } \n` )
131- writeFileSync ( ".codebox/agent-task-workflow-result.json" , `${ JSON . stringify ( result , null , 2 ) } \n` )
132127
133- output ( "job_status" , status )
134- output ( "transcript_json" , request . artifacts . transcript_name )
135- output ( "transcript_summary" , `${ request . workload . label } : ${ status } ` )
136- output ( "engine_data_json" , JSON . stringify ( result . outputs . engine_data ) )
137- output ( "credential_mode" , result . access . credential_mode )
138- output ( "declared_artifacts_json" , JSON . stringify ( artifactDeclarations ) )
139- output ( "request_path" , result . request_path )
140- output ( "result_path" , ".codebox/agent-task-workflow-result.json" )
128+ output ( "request_path" , ".codebox/agent-task-request.json" )
141129output ( "run_id" , runId )
0 commit comments