* Add automatic chat mode with native tool calling support
Introduces a new automatic chat mode (now the default) that automatically invokes tools when the provider supports native tool calling. Conditionally shows/hides the @agent command based on whether native tooling is available.
- Add supportsNativeToolCalling() to AI providers (OpenAI, Anthropic, Azure always support; others opt-in via ENV)
- Update all locale translations with new mode descriptions
- Enhance translator to preserve Trans component tags
- Remove deprecated ability tags UI
* rebase translations
* WIP on image attachments. Supports initial image attachment + subsequent attachments
* persist images
* Image attachments and updates for providers
* desktop pre-change
* always show command on failure
* add back gemini streaming detection
* move provider native tooling flag to Provider func
* whoops - forgot to delete
* strip "@agent" from prompts to prevent weird replies
* translations for automatic-mode (#5145)
* translations for automatic-mode
* rebase
* translations
* lint
* fix dead translations
* change default for now to chat mode just for rollout
* remove pfp for workspace
* passthrough workspace for showAgentCommand detection and rendering
* Agent API automatic mode support
* ephemeral attachments passthrough
* support reading of pinned documents in agent context
116 lines
3.3 KiB
JavaScript
116 lines
3.3 KiB
JavaScript
const pluralize = require("pluralize");
|
|
const {
|
|
WorkspaceAgentInvocation,
|
|
} = require("../../models/workspaceAgentInvocation");
|
|
const { writeResponseChunk } = require("../helpers/chat/responses");
|
|
const { Workspace } = require("../../models/workspace");
|
|
|
|
/**
|
|
* In-memory cache for attachments associated with agent invocations.
|
|
* Attachments are stored here when grepAgents creates an invocation,
|
|
* then retrieved by AgentHandler when the websocket connects.
|
|
* @type {Map<string, Array>}
|
|
*/
|
|
const invocationAttachmentsCache = new Map();
|
|
|
|
/**
|
|
* Store attachments for an invocation UUID
|
|
* @param {string} uuid - The invocation UUID
|
|
* @param {Array} attachments - The attachments array
|
|
*/
|
|
function cacheInvocationAttachments(uuid, attachments = []) {
|
|
if (attachments.length > 0) {
|
|
invocationAttachmentsCache.set(uuid, attachments);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve and remove attachments for an invocation UUID
|
|
* @param {string} uuid - The invocation UUID
|
|
* @returns {Array} The attachments array (empty if none cached)
|
|
*/
|
|
function getAndClearInvocationAttachments(uuid) {
|
|
const attachments = invocationAttachmentsCache.get(uuid) || [];
|
|
invocationAttachmentsCache.delete(uuid);
|
|
return attachments;
|
|
}
|
|
|
|
async function grepAgents({
|
|
uuid,
|
|
response,
|
|
message,
|
|
workspace,
|
|
user = null,
|
|
thread = null,
|
|
attachments = [],
|
|
}) {
|
|
let nativeToolingEnabled = false;
|
|
|
|
// If the workspace is in automatic mode, check if the workspace supports native tooling
|
|
// to determine if the agent flow should be used or not.
|
|
if (workspace?.chatMode === "automatic")
|
|
nativeToolingEnabled = await Workspace.supportsNativeToolCalling(workspace);
|
|
|
|
const agentHandles = WorkspaceAgentInvocation.parseAgents(message);
|
|
if (agentHandles.length > 0 || nativeToolingEnabled) {
|
|
const { invocation: newInvocation } = await WorkspaceAgentInvocation.new({
|
|
prompt: message,
|
|
workspace: workspace,
|
|
user: user,
|
|
thread: thread,
|
|
});
|
|
|
|
if (!newInvocation) {
|
|
writeResponseChunk(response, {
|
|
id: uuid,
|
|
type: "statusResponse",
|
|
textResponse: `${pluralize(
|
|
"Agent",
|
|
agentHandles.length
|
|
)} ${agentHandles.join(
|
|
", "
|
|
)} could not be called. Chat will be handled as default chat.`,
|
|
sources: [],
|
|
close: true,
|
|
animate: false,
|
|
error: null,
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Cache attachments for the websocket handler to retrieve later
|
|
cacheInvocationAttachments(newInvocation.uuid, attachments);
|
|
|
|
writeResponseChunk(response, {
|
|
id: uuid,
|
|
type: "agentInitWebsocketConnection",
|
|
textResponse: null,
|
|
sources: [],
|
|
close: false,
|
|
error: null,
|
|
websocketUUID: newInvocation.uuid,
|
|
});
|
|
|
|
// Close HTTP stream-able chunk response method because we will swap to agents now.
|
|
writeResponseChunk(response, {
|
|
id: uuid,
|
|
type: "statusResponse",
|
|
textResponse: `${pluralize(
|
|
"Agent",
|
|
agentHandles.length
|
|
)} ${agentHandles.join(
|
|
", "
|
|
)} invoked.\nSwapping over to agent chat. Type /exit to exit agent execution loop early.`,
|
|
sources: [],
|
|
close: true,
|
|
error: null,
|
|
animate: true,
|
|
});
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
module.exports = { grepAgents, getAndClearInvocationAttachments };
|