mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-12 02:19:43 +00:00
feat: Improve computer-use prompt in Instance AI (no-changelog) (#29450)
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
import { getComputerUsePrompt } from '../computer-use-prompt';
|
||||
|
||||
describe('getComputerUsePrompt', () => {
|
||||
describe('when localGateway is undefined', () => {
|
||||
it('returns an empty string', () => {
|
||||
expect(getComputerUsePrompt({ browserAvailable: undefined, localGateway: undefined })).toBe(
|
||||
'',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is disabled globally', () => {
|
||||
it('returns an empty string', () => {
|
||||
expect(
|
||||
getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disabledGlobally' },
|
||||
}),
|
||||
).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use has not been set up (disabled)', () => {
|
||||
it('includes the Computer Use intro section', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disabled' },
|
||||
});
|
||||
|
||||
expect(result).toContain('## Computer Use');
|
||||
});
|
||||
|
||||
it('tells the agent not to use Computer Use tools', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disabled' },
|
||||
});
|
||||
|
||||
expect(result).toContain('Do NOT attempt to use Computer Use tools');
|
||||
});
|
||||
|
||||
it('provides UI setup instructions', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disabled' },
|
||||
});
|
||||
|
||||
expect(result).toContain('Setup computer use');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is disconnected', () => {
|
||||
it('includes the Computer Use intro section', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disconnected' },
|
||||
});
|
||||
|
||||
expect(result).toContain('## Computer Use');
|
||||
});
|
||||
|
||||
it('tells the agent not to use Computer Use tools', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disconnected' },
|
||||
});
|
||||
|
||||
expect(result).toContain('Do NOT attempt to use Computer Use tools');
|
||||
});
|
||||
|
||||
it('provides UI connection instructions', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disconnected' },
|
||||
});
|
||||
|
||||
expect(result).toContain('"Connect"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is connected with no capabilities enabled', () => {
|
||||
it('reports that no capabilities are enabled', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'connected', capabilities: [] },
|
||||
});
|
||||
|
||||
expect(result).toContain('did not enable any capabilities');
|
||||
});
|
||||
|
||||
it('does not include the filesystem exploration section', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'connected', capabilities: [] },
|
||||
});
|
||||
|
||||
expect(result).not.toContain('Filesystem Exploration');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is connected with filesystem capability', () => {
|
||||
it('includes the filesystem exploration guidance', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'connected', capabilities: ['filesystem'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('### Computer Use - Filesystem Exploration');
|
||||
expect(result).toContain('start at depth 1');
|
||||
expect(result).toContain('prefer `search` over browsing');
|
||||
expect(result).toContain('read specific files rather than whole directories');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is connected without filesystem capability', () => {
|
||||
it('does not include the filesystem exploration section', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: true,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).not.toContain('Filesystem Exploration');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is connected with browser available', () => {
|
||||
it('includes the browser automation rules', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: true,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('### Computer Use - Browser Automation rules');
|
||||
});
|
||||
|
||||
it('includes handoff instructions', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: true,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('end your turn');
|
||||
expect(result).toContain('Authentication');
|
||||
expect(result).toContain('CAPTCHAs');
|
||||
});
|
||||
|
||||
it('includes the secrets guardrail', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: true,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('NEVER include passwords, API keys');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is connected but browser is not available', () => {
|
||||
it('includes the browser-disabled notice', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: false,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('Browser Automation (Disabled in Computer Use)');
|
||||
});
|
||||
|
||||
it('does not include the full browser automation rules', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: false,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).not.toContain('end your turn');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Computer Use is connected with both filesystem and browser', () => {
|
||||
it('includes both the filesystem exploration section and browser rules', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: true,
|
||||
localGateway: { status: 'connected', capabilities: ['filesystem', 'browser'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('Filesystem Exploration');
|
||||
expect(result).toContain('Browser Automation rules');
|
||||
});
|
||||
});
|
||||
|
||||
describe('proactive suggestion guidance', () => {
|
||||
it('is included for a connected gateway', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: true,
|
||||
localGateway: { status: 'connected', capabilities: ['browser'] },
|
||||
});
|
||||
|
||||
expect(result).toContain('When to suggest or use Computer Use');
|
||||
});
|
||||
|
||||
it('is included for a disconnected gateway', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disconnected' },
|
||||
});
|
||||
|
||||
expect(result).toContain('When to suggest or use Computer Use');
|
||||
});
|
||||
|
||||
it('is included for a disabled (not set up) gateway', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disabled' },
|
||||
});
|
||||
|
||||
expect(result).toContain('When to suggest or use Computer Use');
|
||||
});
|
||||
|
||||
it('is absent when localGateway is undefined', () => {
|
||||
const result = getComputerUsePrompt({ browserAvailable: undefined, localGateway: undefined });
|
||||
|
||||
expect(result).not.toContain('When to suggest or use Computer Use');
|
||||
});
|
||||
|
||||
it('is absent when Computer Use is disabled globally', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disabledGlobally' },
|
||||
});
|
||||
|
||||
expect(result).not.toContain('When to suggest or use Computer Use');
|
||||
});
|
||||
|
||||
it('lists all 7 use-case categories', () => {
|
||||
const result = getComputerUsePrompt({
|
||||
browserAvailable: undefined,
|
||||
localGateway: { status: 'disconnected' },
|
||||
});
|
||||
|
||||
expect(result).toContain('Credential / OAuth setup');
|
||||
expect(result).toContain('Local file as context');
|
||||
expect(result).toContain('Documentation / output to files');
|
||||
expect(result).toContain('Authenticated web research');
|
||||
expect(result).toContain('Form / frontend testing');
|
||||
expect(result).toContain('Shell / environment');
|
||||
expect(result).toContain('Platform migration');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,115 @@
|
||||
import { type LocalGatewayStatus } from '@/types';
|
||||
|
||||
const BROWSER_USE_EXTENSION_URL =
|
||||
'https://chromewebstore.google.com/detail/n8n-browser-use/cegmdpndekdfpnafgacidejijecomlhh';
|
||||
|
||||
export function getComputerUsePrompt({
|
||||
browserAvailable,
|
||||
localGateway,
|
||||
}: {
|
||||
browserAvailable: boolean | undefined;
|
||||
localGateway: LocalGatewayStatus | undefined;
|
||||
}) {
|
||||
if (localGateway && localGateway.status !== 'disabledGlobally') {
|
||||
const promptParts: string[] = [];
|
||||
|
||||
promptParts.push(`
|
||||
## Computer Use
|
||||
This instance support "Computer Use", which allows connecting to user's computer and execute following functionality:
|
||||
- *filesystem* - read and write files. Use it when users want to include their own files in the automation.
|
||||
- *shell* - Execute shell commands. Use it when you need or are asked to execute commands on user's computer
|
||||
- *browser* - Automate user's browser to access web pages and do tasks on user's behalf. Use it when you require access to user's browser session for example when creating credentials with user's accounts. Requires installing the "n8n Browser Use" Chrome extension from the Chrome Web Store: ${BROWSER_USE_EXTENSION_URL}
|
||||
- *screenshot*, *mouse-keyboard* - control user's computer mouse, keyboard and do screenshots (do not advertise or use this functionality if user does not explicitly ask for it)
|
||||
|
||||
Users have control over this functionality and can enable only the tools they want to provide.
|
||||
Users can reconnect Computer Use with different set of functionality, so always rely on Computer Use status and the available tools and not the conversation history.
|
||||
|
||||
### When to suggest or use Computer Use
|
||||
|
||||
Proactively suggest Computer Use (or use it directly if connected) when you detect these signals:
|
||||
|
||||
- **Credential / OAuth setup** — user needs to set up, create, configure, or connect credentials for any service that requires OAuth or API key generation through a web portal (Slack, Google, Microsoft, HubSpot, Notion, Stripe, Twilio, etc.) → *browser*
|
||||
- **Local file as context** — user mentions a file, PDF, CSV, spec, or requirements doc they want to use as reference while building a workflow → *filesystem*
|
||||
- **Documentation / output to files** — user asks to document, write up, export, or save a workflow description, runbook, or handover doc → *filesystem*
|
||||
- **Authenticated web research** — user wants to check something on a site they're logged into, or gather data from a web-based tool → *browser*
|
||||
- **Form / frontend testing** — user is building n8n forms or a web app with n8n as backend and wants end-to-end testing → *browser*
|
||||
- **Shell / environment** — user asks to run a command (curl, CLI, DB query), automate something locally, or debug connectivity → *shell*
|
||||
- **Platform migration** — user wants to migrate from Make, Zapier, or another automation platform, or replicate an existing workflow from it → *browser* + *filesystem*
|
||||
`);
|
||||
|
||||
promptParts.push(`
|
||||
### Computer Use status`);
|
||||
|
||||
switch (localGateway.status) {
|
||||
case 'connected':
|
||||
if (localGateway.capabilities.length > 0) {
|
||||
promptParts.push(
|
||||
`Computer Use is connected, the user has enabled following capabilities: ${localGateway.capabilities.join(',')}`,
|
||||
);
|
||||
if (localGateway.capabilities.includes('filesystem')) {
|
||||
promptParts.push(`
|
||||
### Computer Use - Filesystem Exploration
|
||||
|
||||
Keep exploration shallow: start at depth 1–2, prefer \`search\` over browsing, and read specific files rather than whole directories.`);
|
||||
}
|
||||
if (browserAvailable) {
|
||||
promptParts.push(`
|
||||
### Computer Use - Browser Automation rules
|
||||
|
||||
You can control the user's browser using the browser_* tools. Since this is their real browser, you share it with them.
|
||||
|
||||
#### Handing control to the user
|
||||
|
||||
When the user needs to act in the browser, **end your turn** with a clear message explaining what they should do. Resume after they reply. Hand off when:
|
||||
- **Authentication** — login pages, OAuth, SSO, 2FA/MFA prompts
|
||||
- **CAPTCHAs or visual challenges** — you cannot solve these
|
||||
- **Accessing downloads** — you can click download buttons, but you cannot open or read downloaded files; ask the user to open the file and share the content you need
|
||||
- **Sensitive content on screen** — passwords, tokens, secrets visible in the browser
|
||||
- **User requests manual control** — they explicitly want to do something themselves
|
||||
|
||||
After the user confirms they're done, take a snapshot to verify before continuing.
|
||||
|
||||
#### Secrets and sensitive data
|
||||
|
||||
**NEVER include passwords, API keys, tokens, or secrets in your chat messages** — even if visible on a page. If the user asks you to retrieve a secret, tell them to read it directly from their browser.
|
||||
|
||||
#### When browser tools fail at runtime
|
||||
|
||||
If a browser_* tool call fails because the browser is unreachable (e.g. connection lost, extension not responding), ask the user to verify the **n8n Browser Use** Chrome extension is installed and connected. If needed, they can reinstall from the Chrome Web Store: ${BROWSER_USE_EXTENSION_URL}`);
|
||||
} else {
|
||||
promptParts.push(`
|
||||
### Browser Automation (Disabled in Computer Use)
|
||||
|
||||
Browser tools are not enabled in the user's Computer Use configuration. If the user asks for browser automation, tell them to (1) enable browser tools in their Computer Use config, and (2) install the n8n Browser Use Chrome extension from the Chrome Web Store: ${BROWSER_USE_EXTENSION_URL}`);
|
||||
}
|
||||
} else {
|
||||
promptParts.push(
|
||||
'Computer Use is connected, but the user did not enable any capabilities',
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'disconnected':
|
||||
promptParts.push(
|
||||
`Computer Use is not connected. Do NOT attempt to use Computer Use tools — they are not available. You can provide these instructions to establish a connection:
|
||||
1. open the right sidebar
|
||||
2. click on the "..." button next to "Computer Use"
|
||||
3. click on "Connect" and follow the instructions in the dialog`,
|
||||
);
|
||||
break;
|
||||
case 'disabled':
|
||||
promptParts.push(
|
||||
`Computer Use is not connected and not set-up. Do NOT attempt to use Computer Use tools — they are not available. You can provide these instructions to establish a connection:
|
||||
1. open the right sidebar
|
||||
2. click on "Setup computer use"
|
||||
3. follow the instructions in the dialog`,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return promptParts.join('\n');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
@@ -208,7 +208,6 @@ export async function createInstanceAgent(options: CreateInstanceAgentOptions):
|
||||
const systemPrompt = getSystemPrompt({
|
||||
researchMode: orchestrationContext?.researchMode,
|
||||
webhookBaseUrl: orchestrationContext?.webhookBaseUrl,
|
||||
filesystemAccess: (context.localMcpServer?.getToolsByCategory('filesystem').length ?? 0) > 0,
|
||||
localGateway: context.localGatewayStatus,
|
||||
toolSearchEnabled: hasDeferrableTools,
|
||||
licenseHints: context.licenseHints,
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { getComputerUsePrompt } from './computer-use-prompt';
|
||||
import { SECRET_ASK_GUARDRAIL } from './credential-guardrails.prompt';
|
||||
import { UNTRUSTED_CONTENT_DOCTRINE } from './shared-prompts';
|
||||
import type { LocalGatewayStatus } from '../types';
|
||||
|
||||
const BROWSER_USE_EXTENSION_URL =
|
||||
'https://chromewebstore.google.com/detail/n8n-browser-use/cegmdpndekdfpnafgacidejijecomlhh';
|
||||
|
||||
interface SystemPromptOptions {
|
||||
researchMode?: boolean;
|
||||
webhookBaseUrl?: string;
|
||||
filesystemAccess?: boolean;
|
||||
localGateway?: LocalGatewayStatus;
|
||||
toolSearchEnabled?: boolean;
|
||||
/** Human-readable hints about licensed features that are NOT available on this instance. */
|
||||
@@ -48,104 +45,6 @@ Some trigger nodes expose HTTP endpoints. Always share the full production URL w
|
||||
**These URLs are for sharing with the user only.** Do NOT include them in \`build-workflow-with-agent\` task descriptions — the builder cannot reach the n8n instance via HTTP and will fail if it tries to curl/fetch these URLs.`;
|
||||
}
|
||||
|
||||
function getFilesystemSection(
|
||||
filesystemAccess: boolean | undefined,
|
||||
localGateway: LocalGatewayStatus | undefined,
|
||||
webhookBaseUrl?: string,
|
||||
): string {
|
||||
// When gateway status is explicitly provided, use multi-way logic
|
||||
if (localGateway?.status === 'disconnected') {
|
||||
const capabilityLines: string[] = [];
|
||||
if (localGateway.capabilities.includes('filesystem')) {
|
||||
capabilityLines.push('- **Filesystem access** — browse, read, and search project files');
|
||||
}
|
||||
if (localGateway.capabilities.includes('browser')) {
|
||||
capabilityLines.push(
|
||||
"- **Browser control** — automate browser interactions on the user's machine",
|
||||
);
|
||||
}
|
||||
const capList =
|
||||
capabilityLines.length > 0
|
||||
? capabilityLines.join('\n')
|
||||
: '- Local machine access capabilities';
|
||||
const instanceUrl = webhookBaseUrl ? new URL(webhookBaseUrl).origin : '<your-instance-url>';
|
||||
return `
|
||||
## Computer Use (Not Connected)
|
||||
|
||||
A **Computer Use** can connect this n8n instance to the user's local machine, providing:
|
||||
${capList}
|
||||
|
||||
The gateway is not currently connected. When the user asks for something that requires local machine access (reading files, browsing, etc.), let them know they can connect by either:
|
||||
|
||||
1. **Run via CLI:** \`npx @n8n/computer-use ${instanceUrl}\`
|
||||
|
||||
Do NOT attempt to use Computer Use tools — they are not available until the gateway connects.`;
|
||||
}
|
||||
|
||||
if (filesystemAccess) {
|
||||
return `
|
||||
## Project Filesystem Access
|
||||
|
||||
You have read-only access to the user's project files via the \`filesystem\` tool with actions: \`tree\`, \`search\`, \`read\`, \`list\`. Explore the project before building workflows that depend on user data shapes.
|
||||
|
||||
Keep exploration shallow — start at depth 1-2, prefer \`search\` over browsing, read specific files not whole directories.`;
|
||||
}
|
||||
|
||||
return `
|
||||
## No Filesystem Access
|
||||
|
||||
You do NOT have access to the user's project files. The filesystem tool is not available. Do not attempt to use it or claim you can browse the user's codebase.`;
|
||||
}
|
||||
|
||||
function getBrowserSection(
|
||||
browserAvailable: boolean | undefined,
|
||||
localGateway: LocalGatewayStatus | undefined,
|
||||
): string {
|
||||
if (!browserAvailable) {
|
||||
if (localGateway?.status === 'disconnected') {
|
||||
return `
|
||||
|
||||
## Browser Automation (Unavailable)
|
||||
|
||||
Browser tools require both the Computer Use daemon (see above) **and** the n8n Browser Use Chrome extension. If the user asks for browser automation, tell them to start the daemon and install the extension from the Chrome Web Store: ${BROWSER_USE_EXTENSION_URL}`;
|
||||
}
|
||||
|
||||
if (localGateway?.status === 'connected') {
|
||||
return `
|
||||
|
||||
## Browser Automation (Disabled in Computer Use)
|
||||
|
||||
Browser tools are not enabled in the user's Computer Use configuration. If the user asks for browser automation, tell them to (1) enable browser tools in their Computer Use config, and (2) install the n8n Browser Use Chrome extension from the Chrome Web Store: ${BROWSER_USE_EXTENSION_URL}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
return `
|
||||
|
||||
## Browser Automation
|
||||
|
||||
You can control the user's browser using the browser_* tools. Since this is their real browser, you share it with them.
|
||||
|
||||
### Handing control to the user
|
||||
|
||||
When the user needs to act in the browser, **end your turn** with a clear message explaining what they should do. Resume after they reply. Hand off when:
|
||||
- **Authentication** — login pages, OAuth, SSO, 2FA/MFA prompts
|
||||
- **CAPTCHAs or visual challenges** — you cannot solve these
|
||||
- **Accessing downloads** — you can click download buttons, but you cannot open or read downloaded files; ask the user to open the file and share the content you need
|
||||
- **Sensitive content on screen** — passwords, tokens, secrets visible in the browser
|
||||
- **User requests manual control** — they explicitly want to do something themselves
|
||||
|
||||
After the user confirms they're done, take a snapshot to verify before continuing.
|
||||
|
||||
### Secrets and sensitive data
|
||||
|
||||
**NEVER include passwords, API keys, tokens, or secrets in your chat messages** — even if visible on a page. If the user asks you to retrieve a secret, tell them to read it directly from their browser.
|
||||
|
||||
### When browser tools fail at runtime
|
||||
|
||||
If a browser_* tool call fails because the browser is unreachable (e.g. connection lost, extension not responding), ask the user to verify the **n8n Browser Use** Chrome extension is installed and connected. If needed, they can reinstall from the Chrome Web Store: ${BROWSER_USE_EXTENSION_URL}`;
|
||||
}
|
||||
|
||||
function getReadOnlySection(branchReadOnly?: boolean): string {
|
||||
if (!branchReadOnly) return '';
|
||||
return `
|
||||
@@ -172,7 +71,6 @@ export function getSystemPrompt(options: SystemPromptOptions = {}): string {
|
||||
const {
|
||||
researchMode,
|
||||
webhookBaseUrl,
|
||||
filesystemAccess,
|
||||
localGateway,
|
||||
toolSearchEnabled,
|
||||
licenseHints,
|
||||
@@ -283,8 +181,7 @@ You have the \`research\` tool with \`web-search\` and \`fetch-url\` actions. Us
|
||||
}
|
||||
|
||||
${UNTRUSTED_CONTENT_DOCTRINE}
|
||||
${getFilesystemSection(filesystemAccess, localGateway, webhookBaseUrl)}
|
||||
${getBrowserSection(browserAvailable, localGateway)}
|
||||
${getComputerUsePrompt({ browserAvailable, localGateway })}
|
||||
|
||||
${
|
||||
licenseHints && licenseHints.length > 0
|
||||
|
||||
@@ -545,9 +545,13 @@ export interface InstanceAiWorkspaceService {
|
||||
// ── Local gateway status ─────────────────────────────────────────────────────
|
||||
|
||||
export type LocalGatewayStatus =
|
||||
| { status: 'connected' }
|
||||
| { status: 'disconnected'; capabilities: string[] }
|
||||
| { status: 'disabled' };
|
||||
| {
|
||||
status: 'connected';
|
||||
capabilities: string[];
|
||||
}
|
||||
| {
|
||||
status: 'disabledGlobally' | 'disconnected' | 'disabled';
|
||||
};
|
||||
|
||||
// ── Context bundle ───────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -1485,7 +1485,11 @@ export class InstanceAiService {
|
||||
messageGroupId?: string,
|
||||
pushRef?: string,
|
||||
) {
|
||||
const localGatewayDisabled = await this.settingsService.isLocalGatewayDisabledForUser(user.id);
|
||||
const localGatewayDisabledGlobally =
|
||||
this.settingsService.getAdminSettings().localGatewayDisabled;
|
||||
const localGatewayDisabledForUser = await this.settingsService.isLocalGatewayDisabledForUser(
|
||||
user.id,
|
||||
);
|
||||
const userGateway = this.gatewayRegistry.findGateway(user.id);
|
||||
|
||||
// When the proxy is enabled, create a single ProxyTokenManager and
|
||||
@@ -1528,7 +1532,7 @@ export class InstanceAiService {
|
||||
pushRef,
|
||||
threadId,
|
||||
});
|
||||
if (!localGatewayDisabled && userGateway?.isConnected) {
|
||||
if (!localGatewayDisabledForUser && userGateway?.isConnected) {
|
||||
context.localMcpServer = userGateway;
|
||||
}
|
||||
context.permissions = this.settingsService.getPermissions();
|
||||
@@ -1546,14 +1550,19 @@ export class InstanceAiService {
|
||||
context.runId = runId;
|
||||
|
||||
// Compute gateway status for the system prompt
|
||||
if (localGatewayDisabled) {
|
||||
context.localGatewayStatus = { status: 'disabled' };
|
||||
} else if (userGateway?.isConnected) {
|
||||
context.localGatewayStatus = { status: 'connected' };
|
||||
if (localGatewayDisabledGlobally) {
|
||||
context.localGatewayStatus = { status: 'disabledGlobally' };
|
||||
} else if (!localGatewayDisabledForUser && userGateway?.isConnected) {
|
||||
context.localGatewayStatus = {
|
||||
status: 'connected',
|
||||
capabilities: userGateway
|
||||
.getStatus()
|
||||
.toolCategories.filter(({ enabled }) => enabled)
|
||||
.map(({ name }) => name),
|
||||
};
|
||||
} else {
|
||||
context.localGatewayStatus = {
|
||||
status: 'disconnected',
|
||||
capabilities: ['filesystem', 'browser'],
|
||||
status: localGatewayDisabledForUser ? 'disabled' : 'disconnected',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user