@@ -59,6 +59,7 @@ const NON_SECRET_KEY_METADATA_NAMES = new Set([
5959] ) ;
6060const MESSAGING_CREDENTIAL_PLACEHOLDER_RE =
6161 / ^ (?: o p e n s h e l l : r e s o l v e : e n v : | [ A - Z a - z 0 - 9 ] + - O P E N S H E L L - R E S O L V E - E N V - ) (?: v [ 0 - 9 ] + _ ) ? [ A - Z ] [ A - Z 0 - 9 _ ] * $ / u;
62+ const JSON_ARRAY_INDEX_SEGMENT_RE = / ^ \[ (?: 0 | [ 1 - 9 ] [ 0 - 9 ] * ) \] $ / u;
6263const SECRET_VALUE_PATTERNS : readonly RegExp [ ] = [
6364 / n v a p i - [ A - Z a - z 0 - 9 _ - ] { 10 , } / u,
6465 / n v c f - [ A - Z a - z 0 - 9 _ - ] { 10 , } / u,
@@ -1002,6 +1003,54 @@ function isMessagingCredentialPlaceholder(path: readonly string[], value: unknow
10021003 ) ;
10031004}
10041005
1006+ function messagingCredentialPlaceholderEnvKey ( value : string ) : string | null {
1007+ if ( ! MESSAGING_CREDENTIAL_PLACEHOLDER_RE . test ( value ) ) return null ;
1008+ const marker = value . startsWith ( "openshell:resolve:env:" )
1009+ ? "openshell:resolve:env:"
1010+ : "-OPENSHELL-RESOLVE-ENV-" ;
1011+ const key = value . slice ( value . indexOf ( marker ) + marker . length ) ;
1012+ return key . replace ( / ^ v [ 0 - 9 ] + _ / u, "" ) ;
1013+ }
1014+
1015+ function containsMessagingCredentialPlaceholder ( value : string ) : boolean {
1016+ return value . includes ( "openshell:resolve:env:" ) || value . includes ( "-OPENSHELL-RESOLVE-ENV-" ) ;
1017+ }
1018+
1019+ function isMessagingCredentialPlaceholderAssignment (
1020+ path : readonly string [ ] ,
1021+ value : string ,
1022+ ) : boolean {
1023+ if (
1024+ path . length !== 6 ||
1025+ path [ 0 ] !== "messaging" ||
1026+ path [ 1 ] !== "plan" ||
1027+ path [ 2 ] !== "agentRender" ||
1028+ ! JSON_ARRAY_INDEX_SEGMENT_RE . test ( path [ 3 ] ?? "" ) ||
1029+ path [ 4 ] !== "lines" ||
1030+ ! JSON_ARRAY_INDEX_SEGMENT_RE . test ( path [ 5 ] ?? "" )
1031+ ) {
1032+ return false ;
1033+ }
1034+ const separator = value . indexOf ( "=" ) ;
1035+ if ( separator <= 0 || value . indexOf ( "=" , separator + 1 ) !== - 1 ) return false ;
1036+ const envKey = value . slice ( 0 , separator ) ;
1037+ const placeholderEnvKey = messagingCredentialPlaceholderEnvKey ( value . slice ( separator + 1 ) ) ;
1038+ return CREDENTIAL_ENV_NAME_PATTERN . test ( envKey ) && envKey === placeholderEnvKey ;
1039+ }
1040+
1041+ function isMessagingPackagePin ( path : readonly string [ ] , value : unknown ) : boolean {
1042+ return (
1043+ path . length === 6 &&
1044+ path [ 0 ] === "messaging" &&
1045+ path [ 1 ] === "plan" &&
1046+ path [ 2 ] === "buildSteps" &&
1047+ JSON_ARRAY_INDEX_SEGMENT_RE . test ( path [ 3 ] ?? "" ) &&
1048+ path [ 4 ] === "value" &&
1049+ path [ 5 ] === "pin" &&
1050+ typeof value === "boolean"
1051+ ) ;
1052+ }
1053+
10051054function containsUrlWithCredentialMaterial ( value : string ) : boolean {
10061055 const candidates = value . match ( URL_CANDIDATE_RE ) ?? [ ] ;
10071056 for ( let index = 0 ; index < candidates . length ; index += 1 ) {
@@ -1367,7 +1416,9 @@ function assertPayloadStructureAndCredentialShapes(root: unknown): void {
13671416 observeText ( current . value ) ;
13681417 if (
13691418 ! isMessagingCredentialPlaceholder ( current . path , current . value ) &&
1370- valueLooksLikeSecret ( current . value )
1419+ ! isMessagingCredentialPlaceholderAssignment ( current . path , current . value ) &&
1420+ ( valueLooksLikeSecret ( current . value ) ||
1421+ containsMessagingCredentialPlaceholder ( current . value ) )
13711422 ) {
13721423 invalid (
13731424 `payload field ${ payloadPath ( current . path ) } contains credential-shaped string data` ,
@@ -1450,7 +1501,11 @@ function assertPayloadStructureAndCredentialShapes(root: unknown): void {
14501501 invalid ( "payload must contain only JSON data properties" ) ;
14511502 }
14521503 const child = descriptor . value ;
1453- if ( isCredentialShapedName ( key ) && ! isMessagingCredentialPlaceholder ( current . path , child ) ) {
1504+ if (
1505+ isCredentialShapedName ( key ) &&
1506+ ! isMessagingCredentialPlaceholder ( current . path , child ) &&
1507+ ! isMessagingPackagePin ( [ ...current . path , key ] , child )
1508+ ) {
14541509 invalid (
14551510 `payload field ${ payloadPath ( [ ...current . path , key ] ) } has a credential-shaped field name` ,
14561511 ) ;
@@ -1775,10 +1830,7 @@ function validateInference(value: unknown, agent: ManagedStartupAgent): ManagedS
17751830 if ( primaryModelRef !== null || compatibility !== null || inputModalities !== null ) {
17761831 invalid ( `${ agent } does not support primaryModelRef, compatibility, or inputModalities` ) ;
17771832 }
1778- if (
1779- agent === "langchain-deepagents-code" &&
1780- ! isValidDcodeUpstreamProvider ( upstreamProvider )
1781- ) {
1833+ if ( agent === "langchain-deepagents-code" && ! isValidDcodeUpstreamProvider ( upstreamProvider ) ) {
17821834 invalid (
17831835 "inference.upstreamProvider must start with an ASCII letter or digit and contain 1-64 ASCII letters, digits, dots, underscores, or hyphens for DCode" ,
17841836 ) ;
0 commit comments