ui: move get_datetime tool to frontend (#27255)
* ui: move get_datetime tool to frontend * clarify docs * server: drop the now unused ctime include strftime() and gmtime_r() were the only users, both went away with the get_datetime tool. Also make the renderer's catch inert: the browser executor always emits JSON, so a non-JSON result is no longer a date to display. --------- Co-authored-by: Pascal <admin@serveurperso.com>
This commit is contained in:
co-authored by
Pascal
parent
805984d676
commit
666f8898a2
+1
-1
@@ -33,7 +33,7 @@
|
||||
if (typeof obj.result === 'string') return { dateString: obj.result.trim() };
|
||||
}
|
||||
} catch {
|
||||
return { dateString: toolResultString.trim() };
|
||||
// not JSON - nothing to show
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
@@ -34,7 +34,7 @@ export const BUILTIN_TOOL_UI: Readonly<Record<BuiltInTool, BuiltinToolUiEntry>>
|
||||
label: 'Search files',
|
||||
source: ToolSource.BUILTIN
|
||||
},
|
||||
[BuiltInTool.GET_DATETIME]: { icon: Clock, label: 'Current time', source: ToolSource.BUILTIN },
|
||||
[BuiltInTool.GET_DATETIME]: { icon: Clock, label: 'Current time', source: ToolSource.FRONTEND },
|
||||
[BuiltInTool.GET_INFO]: { icon: Info, label: 'Runtime info', source: ToolSource.BUILTIN },
|
||||
[BuiltInTool.GREP_SEARCH]: {
|
||||
icon: SearchCode,
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { BuiltInTool, JsonSchemaType, ToolCallType } from '$lib/enums';
|
||||
import type { OpenAIToolDefinition } from '$lib/types';
|
||||
|
||||
export const GET_DATETIME_TOOL_NAME = BuiltInTool.GET_DATETIME;
|
||||
|
||||
export function buildGetDatetimeToolDefinition(): OpenAIToolDefinition {
|
||||
return {
|
||||
function: {
|
||||
description:
|
||||
'Returns the current local date and time in ISO 8601 format, with the IANA time zone name',
|
||||
name: GET_DATETIME_TOOL_NAME,
|
||||
parameters: {
|
||||
properties: {},
|
||||
required: [],
|
||||
type: JsonSchemaType.OBJECT
|
||||
}
|
||||
},
|
||||
type: ToolCallType.FUNCTION
|
||||
};
|
||||
}
|
||||
@@ -59,4 +59,5 @@ export * from './uri-template.constants';
|
||||
export * from './url.constants';
|
||||
export * from './working-directory.constants';
|
||||
export * from './read-media';
|
||||
export * from './get-datetime';
|
||||
export * from './browser-info';
|
||||
|
||||
@@ -84,7 +84,12 @@ import type {
|
||||
DatabaseMessageExtraAudioFile,
|
||||
DatabaseMessageExtraImageFile
|
||||
} from '$lib/types/database';
|
||||
import { executeBrowserInfoTool, getAudioInputFormat, isAbortError } from '$lib/utils';
|
||||
import {
|
||||
executeBrowserInfoTool,
|
||||
executeGetDatetimeTool,
|
||||
getAudioInputFormat,
|
||||
isAbortError
|
||||
} from '$lib/utils';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
|
||||
function createDefaultSession(): AgenticSession {
|
||||
@@ -946,7 +951,9 @@ class AgenticStore {
|
||||
|
||||
let executionResult: ToolExecutionResult;
|
||||
|
||||
if (toolName === BuiltInTool.GET_INFO) {
|
||||
if (toolName === BuiltInTool.GET_DATETIME) {
|
||||
executionResult = executeGetDatetimeTool();
|
||||
} else if (toolName === BuiltInTool.GET_INFO) {
|
||||
executionResult = executeBrowserInfoTool();
|
||||
} else if (toolName === BuiltInTool.READ_MEDIA) {
|
||||
executionResult = await ReadMediaService.executeTool(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { browser } from '$app/environment';
|
||||
import {
|
||||
buildBrowserInfoToolDefinition,
|
||||
buildGetDatetimeToolDefinition,
|
||||
buildReadMediaToolDefinition,
|
||||
DISABLED_TOOL_KEYS_LOCALSTORAGE_KEY,
|
||||
HOME_TILDE,
|
||||
@@ -176,7 +177,7 @@ class ToolsStore {
|
||||
}
|
||||
|
||||
get frontendTools(): OpenAIToolDefinition[] {
|
||||
const tools: OpenAIToolDefinition[] = [];
|
||||
const tools: OpenAIToolDefinition[] = [buildGetDatetimeToolDefinition()];
|
||||
|
||||
if (settingsStore.config.jsSandboxEnabled) {
|
||||
tools.push(buildSandboxToolDefinition(!!settingsStore.config.symbolicMathEnabled));
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Frontend executor for the `get_datetime` tool. It runs in the browser, so it
|
||||
* reports the user's own clock and time zone instead of the server's UTC time -
|
||||
* a chat about "tomorrow" means the user's tomorrow, not the host's.
|
||||
*
|
||||
* @see buildGetDatetimeToolDefinition in constants/get-datetime.ts - tool schema sent to the LLM
|
||||
*/
|
||||
|
||||
import type { ToolExecutionResult } from '$lib/types';
|
||||
|
||||
function pad(value: number): string {
|
||||
return String(value).padStart(2, '0');
|
||||
}
|
||||
|
||||
/** ISO 8601 in local time, e.g. `2026-08-17T14:05:09+02:00` */
|
||||
function localIsoString(date: Date): string {
|
||||
// getTimezoneOffset() counts minutes behind UTC, ISO 8601 counts them ahead
|
||||
const offset = -date.getTimezoneOffset();
|
||||
const sign = offset < 0 ? '-' : '+';
|
||||
const absOffset = Math.abs(offset);
|
||||
const day = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
||||
const time = `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
||||
|
||||
return `${day}T${time}${sign}${pad(Math.floor(absOffset / 60))}:${pad(absOffset % 60)}`;
|
||||
}
|
||||
|
||||
/** The `result` field keeps the shape the `get_datetime` renderer already reads. */
|
||||
export function executeGetDatetimeTool(): ToolExecutionResult {
|
||||
const now = new Date();
|
||||
|
||||
return {
|
||||
content: JSON.stringify({
|
||||
result: localIsoString(now),
|
||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
}),
|
||||
isError: false
|
||||
};
|
||||
}
|
||||
@@ -331,6 +331,9 @@ export { getChatCommands } from './chat-commands';
|
||||
// SANDBOX_TOOL_DEFINITION is deprecated; kept for backward compatibility.
|
||||
export { buildSandboxToolDefinition, SANDBOX_TOOL_DEFINITION } from './sandbox-tool';
|
||||
|
||||
// Frontend `get_datetime` executor (the browser clock, not the server's)
|
||||
export { executeGetDatetimeTool } from './get-datetime';
|
||||
|
||||
// Browser fallback for the server's get_info tool
|
||||
export { executeBrowserInfoTool } from './browser-info';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user