refactor: Cleanup constants

This commit is contained in:
Aleksander Grygier
2026-08-12 17:35:57 +02:00
parent fa40e8c2fc
commit 1f4de0704c
32 changed files with 194 additions and 153 deletions
@@ -6,13 +6,14 @@
import ToolCallBlock from './ToolCallBlock.svelte';
import { Loader2 } from '@lucide/svelte';
import { MarkdownContent, SyntaxHighlightedCode } from '$lib/components/app';
import { getBuiltinToolUi, MAX_HEIGHT_CODE_BLOCK } from '$lib/constants';
import { MAX_HEIGHT_CODE_BLOCK } from '$lib/constants';
import { AttachmentType, FileTypeText, MimeTypeAudio, ToolResultKind } from '$lib/enums';
import type { DatabaseMessageExtra } from '$lib/types';
import {
type AgenticSection,
classifyToolResult,
formatJsonPretty,
getBuiltinToolUi,
parseToolResultWithMedia,
type ToolResultLine
} from '$lib/utils';
@@ -1,7 +1,7 @@
<script lang="ts">
import { parseReadMediaMeta } from './parsers/read-media';
import ToolCallBlock from './ToolCallBlock.svelte';
import { ATTACHMENT_SAVED_REGEX } from '$lib/constants/agentic';
import { ATTACHMENT_SAVED_REGEX } from '$lib/constants/agentic.constants';
import { AttachmentType, MimeTypeAudio } from '$lib/enums';
import type { DatabaseMessageExtraAudioFile, DatabaseMessageExtraImageFile } from '$lib/types';
import { type AgenticSection } from '$lib/utils';
@@ -11,10 +11,10 @@
import { Loader2, Wrench } from '@lucide/svelte';
import { CollapsibleContentBlock } from '$lib/components/app';
import { getBuiltinToolUi, ICON_CLASS_DEFAULT, ICON_CLASS_SPIN } from '$lib/constants';
import { ICON_CLASS_DEFAULT, ICON_CLASS_SPIN } from '$lib/constants';
import { AgenticSectionType } from '$lib/enums';
import { mcpStore } from '$lib/stores/mcp.svelte';
import type { AgenticSection, BuiltinToolUiEntry } from '$lib/utils';
import { type AgenticSection, type BuiltinToolUiEntry, getBuiltinToolUi } from '$lib/utils';
import type { Component, Snippet } from 'svelte';
type ToolCallBlockMetaWithError = TMeta & { errorMessage?: string };
@@ -1,4 +1,4 @@
import { FILE_PATH_SEPARATOR_REGEX, NEWLINE } from '$lib/constants/code';
import { FILE_PATH_SEPARATOR_REGEX, NEWLINE } from '$lib/constants';
import {
PREFIX_FILE,
PREFIX_MIME,
@@ -3,11 +3,12 @@
import { McpServerIdentity, TruncatedText } from '$lib/components/app';
import { Checkbox } from '$lib/components/ui/checkbox';
import * as Collapsible from '$lib/components/ui/collapsible';
import { getBuiltinToolUi, ICON_CLASS_DEFAULT } from '$lib/constants';
import { ICON_CLASS_DEFAULT } from '$lib/constants';
import { ToolSource } from '$lib/enums/tools.enums';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { permissionsStore } from '$lib/stores/permissions.svelte';
import { toolsStore } from '$lib/stores/tools.svelte';
import { getBuiltinToolUi } from '$lib/utils';
import { SvelteSet } from 'svelte/reactivity';
let expandedGroups = new SvelteSet<string>();
@@ -50,9 +50,3 @@ export const BUILTIN_TOOL_UI: Readonly<Record<BuiltInTool, BuiltinToolUiEntry>>
},
[BuiltInTool.WRITE_FILE]: { icon: FilePlus, label: 'Write file', source: ToolSource.BUILTIN }
} as const;
export function getBuiltinToolUi(toolName: string | undefined): BuiltinToolUiEntry | null {
if (!toolName) return null;
return (BUILTIN_TOOL_UI as Record<string, BuiltinToolUiEntry>)[toolName] ?? null;
}
@@ -3,5 +3,3 @@
export const CONTROL_ACTION = {
END_REASONING: 'reasoning_end'
} as const;
export type ControlAction = (typeof CONTROL_ACTION)[keyof typeof CONTROL_ACTION];
@@ -1,2 +0,0 @@
export const VIEWPORT_GUTTER = 8;
export const MENU_OFFSET = 6;
@@ -0,0 +1,35 @@
/** HTTP header handling for API and MCP requests. */
export const HEADERS = {
/** Canonical casing for the Authorization header (RFC 7235) */
AUTHORIZATION: 'Authorization',
/** Bearer scheme prefix used for Authorization headers (RFC 6750) */
BEARER: 'Bearer ',
/** Content-Type HTTP header name */
CONTENT_TYPE: 'Content-Type',
/** Partial-redaction rules for MCP headers: header name -> visible trailing chars */
PARTIAL_REDACT: new Map<string, number>([['mcp-session-id', 5]]),
/** Header names whose values should be redacted in diagnostic logs */
REDACTED: new Set([
'authorization',
'api-key',
'cookie',
'mcp-session-id',
'proxy-authorization',
'set-cookie',
'x-auth-token',
'x-api-key'
]),
/** Header carrying the stream-session identity (conversation id, optionally with a model suffix) */
X_CONVERSATION_ID_HEADER: 'X-Conversation-Id',
/** Header asking the server to encode a tool's output differently, e.g. read_file returning base64. */
X_RESP_TYPE_HEADER: 'x-resp-type',
/** Header carrying the working directory a tool call runs in; the model cannot override it */
X_TOOL_CWD_HEADER: 'x-tool-cwd'
};
/** `X_RESP_TYPE_HEADER` value that makes read_file return raw bytes as base64 instead of text. */
export const RESP_TYPE_BASE64 = 'base64';
+1 -6
View File
@@ -18,14 +18,13 @@ export * from './content-detection.constants';
export * from './built-in-tools.constants';
export * from './cache.constants';
export * from './chat-form.constants';
export * from './chat-commands.constants';
export * from './cli-flags.constants';
export * from './code-block.constants';
export * from './context-keys.constants';
export * from './control-actions.constants';
export * from './css-classes.constants';
export * from './floating-ui-constraints.constants';
export * from './formatters.constants';
export * from './headers.constants';
export * from './key-value-pairs.constants';
export * from './latex-protection.constants';
export * from './literal-html.constants';
@@ -45,7 +44,6 @@ export * from './path-display.constants';
export * from './model-id.constants';
export * from './model-loading.constants';
export * from './precision.constants';
export * from './processing-info.constants';
export * from './pwa.constants';
export * from './routes.constants';
export * from './sandbox.constants';
@@ -56,11 +54,8 @@ export * from './stream.constants';
export * from './supported-file-types.constants';
export * from './table-html-restorer.constants';
export * from './title-generation.constants';
export * from './tools.constants';
export * from './tooltip-config.constants';
export * from './ui.constants';
export * from './uri-template.constants';
export * from './url.constants';
export * from './viewport.constants';
export * from './working-directory.constants';
export * from './read-media';
@@ -59,31 +59,6 @@ export const CORS_PROXY = {
URL_PARAM: 'url'
} as const;
/** HTTP header handling for API and MCP requests. */
export const HEADERS = {
/** Canonical casing for the Authorization header (RFC 7235) */
AUTHORIZATION: 'Authorization',
/** Bearer scheme prefix used for Authorization headers (RFC 6750) */
BEARER: 'Bearer ',
/** Content-Type HTTP header name */
CONTENT_TYPE: 'Content-Type',
/** Partial-redaction rules for MCP headers: header name -> visible trailing chars */
PARTIAL_REDACT: new Map<string, number>([['mcp-session-id', 5]]),
/** Header names whose values should be redacted in diagnostic logs */
REDACTED: new Set([
'authorization',
'api-key',
'cookie',
'mcp-session-id',
'proxy-authorization',
'set-cookie',
'x-auth-token',
'x-api-key'
])
};
/** Standard SSE endpoint path indicators */
export const MCP_SSE = {
ENDPOINT: '/sse',
@@ -1,8 +0,0 @@
export const PROCESSING_INFO_TIMEOUT = 2000;
/**
* Statistics units labels
*/
export const STATS_UNITS = {
TOKENS_PER_SECOND: 't/s'
} as const;
@@ -1,5 +1,4 @@
import { BuiltInTool, JsonSchemaType, ToolCallType } from '$lib/enums';
import type { OpenAIToolDefinition } from '$lib/types';
import { BuiltInTool } from '$lib/enums';
export const SANDBOX_TOOL_NAME = BuiltInTool.RUN_JAVASCRIPT;
@@ -12,48 +11,3 @@ export const SANDBOX_OUTPUT_MAX_CHARS = 8192;
export const SANDBOX_EMPTY_OUTPUT = '(no output)';
export const SANDBOX_TRUNCATION_NOTICE = '[output truncated]';
const NERDAMER_DESCRIPTION = `
Symbolic/numeric math via \`nerdamer\`
nerdamer(expr,subs?,opts?)/nerdamer.func(...)→Expression Format via .text(fmt?) (fmt: 'decimals'|'fractions'|'scientific') eval via .evaluate(subs?)
nerdamer(expr,{x:2}) substitutes numeric via opts 'numer' or .evaluate()
simplify/expand/factor(expr) div/gcd/lcm(...) coeffs/partfrac(expr,var)
diff/integrate(expr,var) defint(expr,lo,hi,var?) sum/product(expr,var,lo,hi) limit(expr,var,pt)
solve(expr,var) solveEquations([eq1,eq2],[var1,var2])
polarform/rectform/arg/realpart/imagpart(z)
set/get Var/Constant(name,val?) setFunction(name,[params],body)
IMPORTANT:Identifier 'nerdamer' has already been declared, use it directly`;
/**
* Build the sandbox tool definition. When `includeSymbolicMath` is true,
* the description includes nerdamer API documentation; otherwise it
* describes a plain JavaScript sandbox.
*/
export function buildSandboxToolDefinition(includeSymbolicMath: boolean): OpenAIToolDefinition {
return {
function: {
description: includeSymbolicMath
? `Execute JS in a sandboxed browser worker (no DOM/page access). Top-level await ok; console.log for intermediates; top-level return is captured as result.${NERDAMER_DESCRIPTION}`
: 'Execute JS in a sandboxed browser worker (no DOM/page access). Top-level await ok; console.log for intermediates; top-level return is captured as result.',
name: SANDBOX_TOOL_NAME,
parameters: {
properties: {
code: {
description: 'JavaScript source to execute',
type: JsonSchemaType.STRING
},
timeout_ms: {
description: `Execution timeout in milliseconds, default ${SANDBOX_TIMEOUT_MS_DEFAULT}, max ${SANDBOX_TIMEOUT_MS_MAX}`,
type: JsonSchemaType.NUMBER
}
},
required: ['code'],
type: JsonSchemaType.OBJECT
}
},
type: ToolCallType.FUNCTION
};
}
/** @deprecated Use {@link buildSandboxToolDefinition} instead. Kept for backward compatibility. */
export const SANDBOX_TOOL_DEFINITION = buildSandboxToolDefinition(true);
@@ -2,6 +2,10 @@
// while the tab was hidden. covers brief background pauses without thrashing live streams
export const STREAM_VISIBILITY_KICK_MS = 3000;
// separator joining a conversation id and its per-model stream identity
// suffix (conv::model) used by the server side replay buffer
export const CONVERSATION_ID_SEPARATOR = '::';
/**
* Server-sent events wire format, shared by the chat stream and the
* /models/sse status feed (text/event-stream).
@@ -1,22 +0,0 @@
import { ToolSource } from '$lib/enums/tools.enums';
/** HTTP header carrying the working directory a tool call runs in. The server resolves relative paths against it; the model cannot override it. */
export const X_TOOL_CWD_HEADER = 'x-tool-cwd';
/** HTTP header asking the server to encode a tool's output differently, e.g. read_file returning base64. Not a tool parameter, so it stays out of the definition the model sees. */
export const X_RESP_TYPE_HEADER = 'x-resp-type';
/** `X_RESP_TYPE_HEADER` value that makes read_file return the raw bytes as base64 instead of text. */
export const RESP_TYPE_BASE64 = 'base64';
export const TOOL_GROUP_LABELS = {
[ToolSource.BUILTIN]: 'Built-in',
[ToolSource.CUSTOM]: 'JSON Schema',
[ToolSource.FRONTEND]: 'Browser'
} as const;
export const TOOL_SERVER_LABELS = {
[ToolSource.BUILTIN]: 'Built-in Tools',
[ToolSource.CUSTOM]: 'Custom Tools',
[ToolSource.FRONTEND]: 'Browser Tools'
} as const;
@@ -1 +0,0 @@
export const TOOLTIP_DELAY_DURATION = 500;
@@ -1,11 +1,40 @@
import { ROUTES } from './routes.constants';
import { Package, Search, Settings, SquarePen } from '@lucide/svelte';
import McpLogo from '$lib/components/app/mcp/McpLogo.svelte';
import { ToolSource } from '$lib/enums/tools.enums';
import type { DesktopIconStripItem } from '$lib/types';
export const FORK_TREE_DEPTH_PADDING = 8;
export const SYSTEM_MESSAGE_PLACEHOLDER = 'System message';
export const TOOL_GROUP_LABELS = {
[ToolSource.BUILTIN]: 'Built-in',
[ToolSource.CUSTOM]: 'JSON Schema',
[ToolSource.FRONTEND]: 'Browser'
} as const;
export const TOOL_SERVER_LABELS = {
[ToolSource.BUILTIN]: 'Built-in Tools',
[ToolSource.CUSTOM]: 'Custom Tools',
[ToolSource.FRONTEND]: 'Browser Tools'
} as const;
export const TOOLTIP_DELAY_DURATION = 500;
export const VIEWPORT_GUTTER = 8;
export const MENU_OFFSET = 6;
export const PROCESSING_INFO_TIMEOUT = 2000;
/**
* Statistics units labels
*/
export const STATS_UNITS = {
TOKENS_PER_SECOND: 't/s'
} as const;
export const DEFAULT_MOBILE_BREAKPOINT = 768;
/** Icon used for the model selector and the `/model` slash command. */
export const MODEL_SELECTOR_ICON = Package;
@@ -1 +0,0 @@
export const DEFAULT_MOBILE_BREAKPOINT = 768;
@@ -1,6 +1,7 @@
import { getChatCommands, PROMPT_TRIGGER_PREFIX } from '$lib/constants';
import { PROMPT_TRIGGER_PREFIX } from '$lib/constants';
import { ChatFormCommandAction, KeyboardKey } from '$lib/enums';
import type { ChatFormCommand } from '$lib/types';
import { getChatCommands } from '$lib/utils';
import {
type CommandDismissSnapshot,
findCommandToken,
+2 -1
View File
@@ -6,6 +6,7 @@ import {
API_SLOTS,
API_STREAM,
CONTROL_ACTION,
HEADERS,
LEGACY_AGENTIC_REGEX,
REASONING_EFFORT_TOKENS,
SETTINGS_KEYS,
@@ -339,7 +340,7 @@ export class ChatService {
// server side replay buffer and powers discoverActiveStream on tab reopen. with an explicit
// model the ::model suffix keeps the per model session distinct
if (stream && conversationId) {
headers['X-Conversation-Id'] = streamIdentity(conversationId, options.model);
headers[HEADERS.X_CONVERSATION_ID_HEADER] = streamIdentity(conversationId, options.model);
// persist the pending stream before the fetch: a reload during the model load or
// the prompt processing must still find its way back to the session once it exists
ChatService.saveStreamState(conversationId, 0, options.model ?? null);
+1 -1
View File
@@ -276,7 +276,7 @@ export { MCPService } from './mcp.service';
* - **toolsStore**: Exposes the tool definition when the sandbox is enabled
* - **agenticStore**: Dispatches ToolSource.FRONTEND calls here
*
* @see buildSandboxToolDefinition in constants/sandbox.ts - tool schema sent to the LLM
* @see buildSandboxToolDefinition in utils/sandbox-tool - tool schema sent to the LLM
* @see agenticStore in stores/agentic.svelte.ts - tool dispatch
*/
export { SandboxService } from './sandbox.service';
+5 -5
View File
@@ -1,5 +1,5 @@
import { base } from '$app/paths';
import { API_TOOLS, X_RESP_TYPE_HEADER, X_TOOL_CWD_HEADER } from '$lib/constants';
import { API_TOOLS, HEADERS } from '$lib/constants';
import { ToolResponseField } from '$lib/enums';
import type { ServerBuiltinToolInfo, ToolExecutionResult } from '$lib/types';
import { apiFetch } from '$lib/utils';
@@ -31,7 +31,7 @@ export class ToolsService {
): Promise<ToolExecutionResult> {
const result = await apiFetch<Record<string, unknown>>(API_TOOLS.EXECUTE, {
body: JSON.stringify({ params, tool: toolName }),
headers: cwd ? { [X_TOOL_CWD_HEADER]: cwd } : undefined,
headers: cwd ? { [HEADERS.X_TOOL_CWD_HEADER]: cwd } : undefined,
method: 'POST',
signal
});
@@ -64,9 +64,9 @@ export class ToolsService {
): Promise<Record<string, unknown>> {
const headers: Record<string, string> = {};
if (cwd) headers[X_TOOL_CWD_HEADER] = cwd;
if (cwd) headers[HEADERS.X_TOOL_CWD_HEADER] = cwd;
if (respType) headers[X_RESP_TYPE_HEADER] = respType;
if (respType) headers[HEADERS.X_RESP_TYPE_HEADER] = respType;
return apiFetch<Record<string, unknown>>(API_TOOLS.EXECUTE, {
body: JSON.stringify({ params, tool: toolName }),
@@ -99,7 +99,7 @@ export class ToolsService {
): AsyncGenerator<ToolStreamEvent> {
const headers = getJsonHeaders();
if (cwd) headers[X_TOOL_CWD_HEADER] = cwd;
if (cwd) headers[HEADERS.X_TOOL_CWD_HEADER] = cwd;
const response = await fetch(`${base}${API_TOOLS.EXECUTE}`, {
body: JSON.stringify({ params, stream: true, tool: toolName }),
+7 -1
View File
@@ -31,7 +31,13 @@ import {
MIME_TYPE_PREFIXES
} from '$lib/constants';
import { BuiltInTool, ToolPermissionDecision, ToolSource } from '$lib/enums';
import { AttachmentType, ContentPartType, MessageRole, ToolCallType } from '$lib/enums';
import {
AttachmentType,
ContentPartType,
MessageRole,
MimeTypePrefix,
ToolCallType
} from '$lib/enums';
import { ChatService } from '$lib/services';
import { ReadMediaService } from '$lib/services/read-media.service';
import { SandboxService } from '$lib/services/sandbox.service';
+3 -2
View File
@@ -12,6 +12,7 @@
*/
import {
CONVERSATION_ID_SEPARATOR,
HEADERS,
INACTIVE_CONVERSATION,
STREAM_RESUME_RETRY_MS,
@@ -413,7 +414,7 @@ class ChatStore {
// extract the model suffix, the resume calls in handleStreamResponse must reuse the model
// the session was tagged with, not the live dropdown
const sepIdx = id.indexOf('::');
const sepIdx = id.indexOf(CONVERSATION_ID_SEPARATOR);
const attachedModel: string | null = sepIdx === -1 ? null : id.slice(sepIdx + 2);
this.setChatStreaming(convId, existingContent, targetMessageId, attachedModel);
@@ -828,7 +829,7 @@ class ChatStore {
for (const s of sessions) {
if (s && !s.is_done && typeof s.conversation_id === 'string' && s.conversation_id) {
// strip the optional ::model suffix, the sidebar set is keyed by the bare conv id
const sepIdx = s.conversation_id.indexOf('::');
const sepIdx = s.conversation_id.indexOf(CONVERSATION_ID_SEPARATOR);
const bareId = sepIdx === -1 ? s.conversation_id : s.conversation_id.slice(0, sepIdx);
running.add(bareId);
+1 -1
View File
@@ -1,6 +1,5 @@
import {
buildReadMediaToolDefinition,
buildSandboxToolDefinition,
DISABLED_TOOL_KEYS_LOCALSTORAGE_KEY,
HOME_TILDE,
TOOL_GROUP_LABELS,
@@ -19,6 +18,7 @@ import { mcpStore } from '$lib/stores/mcp.svelte';
import { modelsStore, selectedModelName } from '$lib/stores/models.svelte';
import { config } from '$lib/stores/settings.svelte';
import type { OpenAIToolDefinition, ToolEntry, ToolGroup } from '$lib/types';
import { buildSandboxToolDefinition } from '$lib/utils';
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
/** Stable selection identity for a tool, shared by the disabled set and the permission store */
+12
View File
@@ -215,6 +215,18 @@ export interface FileMentionEntry {
* command whose backing capability is unavailable (e.g. `/prompt` when no
* MCP server exposes prompts): visible but greyed out and not selectable.
*/
export interface ChatCommandsOptions {
/** Gates `/model`. */
showModelSelector: boolean;
/** Gates `/prompt`. */
hasPrompts: () => boolean;
/** Gates `/cwd`. */
hasCwdTools: () => boolean;
}
/** Protocol-level verbs accepted by the realtime inference control endpoint. Mirrors `CONTROL_ACTION`. */
export type ControlAction = 'reasoning_end';
export interface ChatFormCommand {
name: string;
description: string;
+3 -1
View File
@@ -56,7 +56,9 @@ export type {
AttachmentDisplayItemsOptions,
FileProcessingResult,
FileMentionEntry,
ChatFormCommand
ChatFormCommand,
ChatCommandsOptions,
ControlAction
} from './chat.d';
// Database types
+13
View File
@@ -0,0 +1,13 @@
import { BUILTIN_TOOL_UI } from '$lib/constants';
import type { BuiltinToolUiEntry } from '$lib/types';
/**
* Resolve the UI metadata (label + icon) for a built-in tool by its name.
* Falls back to null for unknown or non-built-in tools so callers can render
* a generic chrome instead.
*/
export function getBuiltinToolUi(toolName: string | undefined): BuiltinToolUiEntry | null {
if (!toolName) return null;
return (BUILTIN_TOOL_UI as Record<string, BuiltinToolUiEntry>)[toolName] ?? null;
}
@@ -1,23 +1,14 @@
import { SET_WORKING_DIRECTORY_LABEL } from '$lib/constants';
import { ChatFormCommandAction } from '$lib/enums';
import type { ChatFormCommand } from '$lib/types';
interface ChatCommandsOptions {
/** Gates `/model`. */
showModelSelector: boolean;
/** Gates `/prompt`. */
hasPrompts: () => boolean;
/** Gates `/cwd`. */
hasCwdTools: () => boolean;
}
import type { ChatCommandsOptions, ChatFormCommand } from '$lib/types';
/**
* The slash commands surfaced by the `/` command picker, in display order.
*
* Availability is supplied as predicates rather than store imports: this
* module is re-exported through the `$lib/constants` barrel, and importing
* module is re-exported through the `$lib/utils` barrel, and importing
* stores at module load would create a circular dependency (the stores
* themselves import from `$lib/constants`).
* themselves import from `$lib/utils`).
*/
export function getChatCommands(options: ChatCommandsOptions): ChatFormCommand[] {
return [
+9 -1
View File
@@ -317,9 +317,17 @@ export { tryParseToolResultObject } from './tool-call-meta';
// Per-tool UI metadata (label + icon) used by the tool-call chrome.
// Re-exported through $lib/utils so renderer components can read the
// label without depending on $lib/constants directly.
export { getBuiltinToolUi } from '$lib/constants';
export { getBuiltinToolUi } from './built-in-tools';
export type { BuiltinToolUiEntry } from '$lib/types';
// Chat command picker
export { getChatCommands } from './chat-commands';
// Sandbox tool definition
// SANDBOX_TOOL_DEFINITION is deprecated; kept for backward compatibility.
export { buildSandboxToolDefinition, SANDBOX_TOOL_DEFINITION } from './sandbox-tool';
// Cryptography utilities
export { uuid } from './uuid';
+52
View File
@@ -0,0 +1,52 @@
import {
SANDBOX_TIMEOUT_MS_DEFAULT,
SANDBOX_TIMEOUT_MS_MAX,
SANDBOX_TOOL_NAME
} from '$lib/constants';
import { JsonSchemaType, ToolCallType } from '$lib/enums';
import type { OpenAIToolDefinition } from '$lib/types';
const NERDAMER_DESCRIPTION = `
Symbolic/numeric math via \`nerdamer\`
nerdamer(expr,subs?,opts?)/nerdamer.func(...)→Expression Format via .text(fmt?) (fmt: 'decimals'|'fractions'|'scientific') eval via .evaluate(subs?)
nerdamer(expr,{x:2}) substitutes numeric via opts 'numer' or .evaluate()
simplify/expand/factor(expr) div/gcd/lcm(...) coeffs/partfrac(expr,var)
diff/integrate(expr,var) defint(expr,lo,hi,var?) sum/product(expr,var,lo,hi) limit(expr,var,pt)
solve(expr,var) solveEquations([eq1,eq2],[var1,var2])
polarform/rectform/arg/realpart/imagpart(z)
set/get Var/Constant(name,val?) setFunction(name,[params],body)
IMPORTANT:Identifier 'nerdamer' has already been declared, use it directly`;
/**
* Build the sandbox tool definition. When `includeSymbolicMath` is true,
* the description includes nerdamer API documentation; otherwise it
* describes a plain JavaScript sandbox.
*/
export function buildSandboxToolDefinition(includeSymbolicMath: boolean): OpenAIToolDefinition {
return {
function: {
description: includeSymbolicMath
? `Execute JS in a sandboxed browser worker (no DOM/page access). Top-level await ok; console.log for intermediates; top-level return is captured as result.${NERDAMER_DESCRIPTION}`
: 'Execute JS in a sandboxed browser worker (no DOM/page access). Top-level await ok; console.log for intermediates; top-level return is captured as result.',
name: SANDBOX_TOOL_NAME,
parameters: {
properties: {
code: {
description: 'JavaScript source to execute',
type: JsonSchemaType.STRING
},
timeout_ms: {
description: `Execution timeout in milliseconds, default ${SANDBOX_TIMEOUT_MS_DEFAULT}, max ${SANDBOX_TIMEOUT_MS_MAX}`,
type: JsonSchemaType.NUMBER
}
},
required: ['code'],
type: JsonSchemaType.OBJECT
}
},
type: ToolCallType.FUNCTION
};
}
/** @deprecated Use {@link buildSandboxToolDefinition} instead. Kept for backward compatibility. */
export const SANDBOX_TOOL_DEFINITION = buildSandboxToolDefinition(true);
+3 -1
View File
@@ -1,3 +1,5 @@
import { CONVERSATION_ID_SEPARATOR } from '$lib/constants';
/**
* Build the conversation identity used by the server side replay buffer.
*
@@ -11,5 +13,5 @@ export function streamIdentity(conversationId: string, model?: string | null): s
if (!model) return conversationId;
return `${conversationId}::${model}`;
return `${conversationId}${CONVERSATION_ID_SEPARATOR}${model}`;
}