@@ -89,7 +89,9 @@ func NewACPAgentFromConfig(config *config.ACPAgentConfig) *ACPAgent {
8989 if autoApproveMode := strings .TrimSpace (config .AutoApproveMode ); autoApproveMode != "" {
9090 agent .AutoApproveMode = autoApproveMode
9191 }
92- if mode := strings .TrimSpace (config .Mode ); mode != "" {
92+ if config .DisableModeNegotiation {
93+ agent .Mode = ""
94+ } else if mode := strings .TrimSpace (config .Mode ); mode != "" {
9395 agent .Mode = mode
9496 } else {
9597 agent .Mode = agent .ReadOnlyMode
@@ -139,6 +141,9 @@ func (a *ACPAgent) WithAgentic(agentic bool) Agent {
139141 if agentic && a .AutoApproveMode != "" {
140142 mode = a .AutoApproveMode
141143 }
144+ if strings .TrimSpace (a .Mode ) == "" {
145+ mode = ""
146+ }
142147
143148 return & ACPAgent {
144149 agentName : a .agentName ,
@@ -584,12 +589,13 @@ func readTextFileWindow(path string, startLine int, limit *int, maxBytes int) (s
584589
585590 reader := bufio .NewReader (file )
586591 var out strings.Builder
592+ var lineBuf bytes.Buffer
587593 currentLine := 0
588594 selectedLines := 0
589595 wroteLine := false
590596 endedWithNewline := false
591597
592- appendLine := func (line string ) error {
598+ appendLine := func (line [] byte ) error {
593599 additionalBytes := len (line )
594600 if wroteLine {
595601 additionalBytes ++
@@ -600,14 +606,43 @@ func readTextFileWindow(path string, startLine int, limit *int, maxBytes int) (s
600606 if wroteLine {
601607 out .WriteByte ('\n' )
602608 }
603- out .WriteString (line )
609+ if len (line ) > 0 {
610+ out .Write (line )
611+ }
604612 wroteLine = true
605613 selectedLines ++
606614 return nil
607615 }
608616
617+ lineBufferBudget := func () int {
618+ budget := maxBytes - out .Len ()
619+ if wroteLine {
620+ budget --
621+ }
622+ return budget
623+ }
624+
625+ appendLineChunk := func (chunk []byte ) error {
626+ if len (chunk ) == 0 {
627+ return nil
628+ }
629+ if lineBufferBudget () < lineBuf .Len ()+ len (chunk ) {
630+ return fmt .Errorf ("file content too large: exceeds max %d bytes" , maxBytes )
631+ }
632+ _ , err := lineBuf .Write (chunk )
633+ return err
634+ }
635+
609636 for {
610- chunk , readErr := reader .ReadBytes ('\n' )
637+ chunk , readErr := reader .ReadSlice ('\n' )
638+ if readErr == bufio .ErrBufferFull {
639+ if currentLine >= startLine && (limit == nil || selectedLines < * limit ) {
640+ if err := appendLineChunk (chunk ); err != nil {
641+ return "" , err
642+ }
643+ }
644+ continue
645+ }
611646 if readErr != nil && readErr != io .EOF {
612647 return "" , readErr
613648 }
@@ -616,15 +651,19 @@ func readTextFileWindow(path string, startLine int, limit *int, maxBytes int) (s
616651 }
617652
618653 hasTrailingNewline := len (chunk ) > 0 && chunk [len (chunk )- 1 ] == '\n'
619- if hasTrailingNewline {
620- chunk = chunk [:len (chunk )- 1 ]
621- }
622654 endedWithNewline = hasTrailingNewline
623655
624656 if currentLine >= startLine && (limit == nil || selectedLines < * limit ) {
625- if err := appendLine (string (chunk )); err != nil {
657+ if hasTrailingNewline {
658+ chunk = chunk [:len (chunk )- 1 ]
659+ }
660+ if err := appendLineChunk (chunk ); err != nil {
661+ return "" , err
662+ }
663+ if err := appendLine (lineBuf .Bytes ()); err != nil {
626664 return "" , err
627665 }
666+ lineBuf .Reset ()
628667 if limit != nil && selectedLines >= * limit {
629668 return out .String (), nil
630669 }
@@ -788,7 +827,7 @@ func (c *acpClient) WriteTextFile(ctx context.Context, params acp.WriteTextFileR
788827
789828 // Enforce authorization at point of operation.
790829 if ! c .agent .mutatingOperationsAllowed () {
791- if c .agent .Mode == c .agent .ReadOnlyMode {
830+ if c .agent .effectivePermissionMode () == c .agent .ReadOnlyMode {
792831 return acp.WriteTextFileResponse {}, fmt .Errorf ("write operation not permitted in read-only mode" )
793832 }
794833 return acp.WriteTextFileResponse {}, fmt .Errorf ("write operation not permitted unless auto-approve mode is explicitly enabled" )
@@ -1071,7 +1110,7 @@ func (c *acpClient) CreateTerminal(ctx context.Context, params acp.CreateTermina
10711110
10721111 // Enforce authorization at point of operation.
10731112 if ! c .agent .mutatingOperationsAllowed () {
1074- if c .agent .Mode == c .agent .ReadOnlyMode {
1113+ if c .agent .effectivePermissionMode () == c .agent .ReadOnlyMode {
10751114 return acp.CreateTerminalResponse {}, fmt .Errorf ("terminal creation not permitted in read-only mode" )
10761115 }
10771116 return acp.CreateTerminalResponse {}, fmt .Errorf ("terminal creation not permitted unless auto-approve mode is explicitly enabled" )
@@ -1410,13 +1449,16 @@ func validateConfiguredModel(configuredModel string, models *acp.SessionModelSta
14101449}
14111450
14121451func (a * ACPAgent ) mutatingOperationsAllowed () bool {
1413- return a .AutoApproveMode != "" && a .Mode == a .AutoApproveMode
1452+ return a .AutoApproveMode != "" && a .effectivePermissionMode () == a .AutoApproveMode
14141453}
14151454
14161455func (a * ACPAgent ) effectivePermissionMode () string {
14171456 if strings .TrimSpace (a .Mode ) != "" {
14181457 return a .Mode
14191458 }
1459+ if a .Agentic && strings .TrimSpace (a .AutoApproveMode ) != "" {
1460+ return a .AutoApproveMode
1461+ }
14201462 return a .ReadOnlyMode
14211463}
14221464
@@ -1512,7 +1554,12 @@ func applyACPAgentConfigOverride(cfg *config.ACPAgentConfig, override *config.AC
15121554 if autoApproveMode := strings .TrimSpace (override .AutoApproveMode ); autoApproveMode != "" {
15131555 cfg .AutoApproveMode = autoApproveMode
15141556 }
1515- if mode := strings .TrimSpace (override .Mode ); mode != "" {
1557+ if override .DisableModeNegotiation {
1558+ cfg .DisableModeNegotiation = true
1559+ }
1560+ if cfg .DisableModeNegotiation {
1561+ cfg .Mode = ""
1562+ } else if mode := strings .TrimSpace (override .Mode ); mode != "" {
15161563 cfg .Mode = mode
15171564 } else {
15181565 // If mode is omitted, default to the effective read-only mode.
0 commit comments