Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/configuration/miscellaneous.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ Sets content for the top banner in the user interface.

---

## COPILOT_ENABLED

!!! tip "Dynamic Configuration Parameter"

Default: `True`

Enables or disables the [NetBox Copilot](https://netboxlabs.com/docs/copilot/) agent globally. When enabled, users can opt to toggle the agent individually.

---

## CENSUS_REPORTING_ENABLED

Default: `True`
Expand Down
18 changes: 11 additions & 7 deletions docs/development/user-preferences.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ For end‑user guidance on resetting saved table layouts, see [Features > User P

## Available Preferences

| Name | Description |
|--------------------------|---------------------------------------------------------------|
| data_format | Preferred format when rendering raw data (JSON or YAML) |
| pagination.per_page | The number of items to display per page of a paginated table |
| pagination.placement | Where to display the paginator controls relative to the table |
| tables.${table}.columns | The ordered list of columns to display when viewing the table |
| tables.${table}.ordering | A list of column names by which the table should be ordered |
| Name | Description |
|----------------------------|---------------------------------------------------------------|
| `csv_delimiter` | The delimiting character used when exporting CSV data |
| `data_format` | Preferred format when rendering raw data (JSON or YAML) |
| `locale.language` | The language selected for UI translation |
| `pagination.per_page` | The number of items to display per page of a paginated table |
| `pagination.placement` | Where to display the paginator controls relative to the table |
| `tables.${table}.columns` | The ordered list of columns to display when viewing the table |
| `tables.${table}.ordering` | A list of column names by which the table should be ordered |
| `ui.copilot_enabled` | Toggles the NetBox Copilot AI agent |
| `ui.tables.striping` | Toggles visual striping of tables in the UI |
4 changes: 2 additions & 2 deletions netbox/core/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ class ConfigRevisionForm(forms.ModelForm, metaclass=ConfigFormMetaclass):
FieldSet('CUSTOM_VALIDATORS', 'PROTECTION_RULES', name=_('Validation')),
FieldSet('DEFAULT_USER_PREFERENCES', name=_('User Preferences')),
FieldSet(
'MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL',
name=_('Miscellaneous')
'MAINTENANCE_MODE', 'COPILOT_ENABLED', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION',
'MAPS_URL', name=_('Miscellaneous'),
),
FieldSet('comment', name=_('Config Revision'))
)
Expand Down
9 changes: 9 additions & 0 deletions netbox/netbox/config/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ def __init__(self, name, label, default, description='', field=None, field_kwarg
description=_("Enable maintenance mode"),
field=forms.BooleanField
),
ConfigParam(
name='COPILOT_ENABLED',
label=_('NetBox Copilot enabled'),
default=True,
description=_(
"Enable the NetBox Copilot AI agent globally. If enabled, users can toggle the agent individually."
),
field=forms.BooleanField
),
ConfigParam(
name='GRAPHQL_ENABLED',
label=_('GraphQL enabled'),
Expand Down
7 changes: 6 additions & 1 deletion netbox/netbox/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ def preferences(request):
Adds preferences for the current user (if authenticated) to the template context.
Example: {{ preferences|get_key:"pagination.placement" }}
"""
config = get_config()
user_preferences = request.user.config if request.user.is_authenticated else {}
return {
'preferences': user_preferences,
'htmx_navigation': user_preferences.get('ui.htmx_navigation', False) == 'true'
'copilot_enabled': (
config.COPILOT_ENABLED and not django_settings.ISOLATED_DEPLOYMENT and
user_preferences.get('ui.copilot_enabled', False) == 'true'
),
'htmx_navigation': user_preferences.get('ui.htmx_navigation', False) == 'true',
}


Expand Down
9 changes: 9 additions & 0 deletions netbox/netbox/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ def get_csv_delimiters():
else ''
)
),
'ui.copilot_enabled': UserPreference(
label=_('NetBox Copilot'),
choices=(
('', _('Disabled')),
('true', _('Enabled')),
),
description=_('Enable the NetBox Copilot AI agent'),
default=False,
),
'pagination.per_page': UserPreference(
label=_('Page length'),
choices=get_page_lengths(),
Expand Down
7 changes: 7 additions & 0 deletions netbox/netbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,13 @@ def _setting(name, default=None):
CENSUS_URL = 'https://census.netbox.oss.netboxlabs.com/api/v1/'


#
# NetBox Copilot
#

NETBOX_COPILOT_URL = 'https://static.copilot.netboxlabs.ai/load.js'


#
# Django social auth
#
Expand Down
3 changes: 3 additions & 0 deletions netbox/templates/base/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
{% block layout %}{% endblock %}

{# Additional Javascript #}
{% if copilot_enabled and request.user.is_authenticated %}
<script src="{{ settings.NETBOX_COPILOT_URL }}" defer></script>
{% endif %}
{% block javascript %}{% endblock %}

{# User messages #}
Expand Down
4 changes: 4 additions & 0 deletions netbox/templates/core/inc/config_data.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@
<th scope="row" class="ps-3">{% trans "Maintenance mode" %}</th>
<td>{% checkmark config.MAINTENANCE_MODE %}</td>
</tr>
<tr>
<th scope="row" class="ps-3">{% trans "NetBox Copilot enabled" %}</th>
<td>{% checkmark config.COPILOT_ENABLED %}</td>
</tr>
<tr>
<th scope="row" class="ps-3">{% trans "GraphQL enabled" %}</th>
<td>{% checkmark config.GRAPHQL_ENABLED %}</td>
Expand Down
12 changes: 8 additions & 4 deletions netbox/users/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from core.models import ObjectType
from ipam.formfields import IPNetworkFormField
from ipam.validators import prefix_validator
from netbox.config import get_config
from netbox.preferences import PREFERENCES
from users.constants import *
from users.models import *
Expand Down Expand Up @@ -64,8 +65,8 @@ def __new__(mcs, name, bases, attrs):
class UserConfigForm(forms.ModelForm, metaclass=UserConfigFormMetaclass):
fieldsets = (
FieldSet(
'locale.language', 'pagination.per_page', 'pagination.placement', 'ui.htmx_navigation',
'ui.tables.striping',
'locale.language', 'ui.copilot_enabled', 'pagination.per_page', 'pagination.placement',
'ui.htmx_navigation', 'ui.tables.striping',
name=_('User Interface')
),
FieldSet('data_format', 'csv_delimiter', name=_('Miscellaneous')),
Expand All @@ -83,8 +84,7 @@ class Meta:
def __init__(self, *args, instance=None, **kwargs):

# Get initial data from UserConfig instance
initial_data = flatten_dict(instance.data)
kwargs['initial'] = initial_data
kwargs['initial'] = flatten_dict(instance.data)

super().__init__(*args, instance=instance, **kwargs)

Expand All @@ -93,6 +93,10 @@ def __init__(self, *args, instance=None, **kwargs):
(f'tables.{table_name}', '') for table_name in instance.data.get('tables', [])
)

# Disable Copilot preference if it has been disabled globally
if not get_config().COPILOT_ENABLED:
self.fields['ui.copilot_enabled'].disabled = True

def save(self, *args, **kwargs):

# Set UserConfig data
Expand Down