chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import type { RedisCommandParams, RedisCommandResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisCommandTool: ToolConfig<RedisCommandParams, RedisCommandResponse> = {
|
||||
id: 'redis_command',
|
||||
name: 'Redis Command',
|
||||
description:
|
||||
'Execute a raw Redis command as a JSON array (e.g. ["HSET", "key", "field", "value"]).',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
command: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Redis command as a JSON array (e.g. ["SET", "key", "value"])',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => {
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(params.command)
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Invalid JSON in command: ${params.command}. Expected a JSON array like ["SET", "key", "value"].`
|
||||
)
|
||||
}
|
||||
const [cmd, ...args] = Array.isArray(parsed) ? parsed : [parsed]
|
||||
return {
|
||||
url: params.url,
|
||||
command: String(cmd),
|
||||
args: args.map(String),
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisCommandParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to execute Redis command')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
command: params?.command ?? '',
|
||||
result: data.result ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
command: { type: 'string', description: 'The command that was executed' },
|
||||
result: { type: 'json', description: 'The result of the command' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { RedisDeleteParams, RedisDeleteResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisDeleteTool: ToolConfig<RedisDeleteParams, RedisDeleteResponse> = {
|
||||
id: 'redis_delete',
|
||||
name: 'Redis Delete',
|
||||
description: 'Delete a key from Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'DEL',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisDeleteParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to delete key from Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
deletedCount: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was deleted' },
|
||||
deletedCount: {
|
||||
type: 'number',
|
||||
description: 'Number of keys deleted (0 if key did not exist, 1 if deleted)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { RedisExistsParams, RedisExistsResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisExistsTool: ToolConfig<RedisExistsParams, RedisExistsResponse> = {
|
||||
id: 'redis_exists',
|
||||
name: 'Redis EXISTS',
|
||||
description: 'Check if a key exists in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to check',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'EXISTS',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisExistsParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to check key existence in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
exists: data.result === 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was checked' },
|
||||
exists: { type: 'boolean', description: 'Whether the key exists (true) or not (false)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { RedisExpireParams, RedisExpireResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisExpireTool: ToolConfig<RedisExpireParams, RedisExpireResponse> = {
|
||||
id: 'redis_expire',
|
||||
name: 'Redis EXPIRE',
|
||||
description: 'Set an expiration time (in seconds) on a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to set expiration on',
|
||||
},
|
||||
seconds: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timeout in seconds',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'EXPIRE',
|
||||
args: [params.key, params.seconds],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisExpireParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to set expiration in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
result: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that expiration was set on' },
|
||||
result: {
|
||||
type: 'number',
|
||||
description: '1 if the timeout was set, 0 if the key does not exist',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { RedisGetParams, RedisGetResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisGetTool: ToolConfig<RedisGetParams, RedisGetResponse> = {
|
||||
id: 'redis_get',
|
||||
name: 'Redis Get',
|
||||
description: 'Get the value of a key from Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'GET',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisGetParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to get key from Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
value: data.result ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was retrieved' },
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'The value of the key, or null if the key does not exist',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { RedisHDelParams, RedisHDelResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisHDelTool: ToolConfig<RedisHDelParams, RedisHDelResponse> = {
|
||||
id: 'redis_hdel',
|
||||
name: 'Redis HDEL',
|
||||
description: 'Delete a field from a hash stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The hash key',
|
||||
},
|
||||
field: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The field name to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'HDEL',
|
||||
args: [params.key, params.field],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisHDelParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to delete hash field from Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
field: params?.field ?? '',
|
||||
deleted: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The hash key' },
|
||||
field: { type: 'string', description: 'The field that was deleted' },
|
||||
deleted: {
|
||||
type: 'number',
|
||||
description: 'Number of fields removed (1 if deleted, 0 if field did not exist)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import type { RedisHGetParams, RedisHGetResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisHGetTool: ToolConfig<RedisHGetParams, RedisHGetResponse> = {
|
||||
id: 'redis_hget',
|
||||
name: 'Redis HGET',
|
||||
description: 'Get the value of a field in a hash stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The hash key',
|
||||
},
|
||||
field: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The field name to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'HGET',
|
||||
args: [params.key, params.field],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisHGetParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to get hash field from Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
field: params?.field ?? '',
|
||||
value: data.result ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The hash key' },
|
||||
field: { type: 'string', description: 'The field that was retrieved' },
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'The field value, or null if the field or key does not exist',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { RedisHGetAllParams, RedisHGetAllResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisHGetAllTool: ToolConfig<RedisHGetAllParams, RedisHGetAllResponse> = {
|
||||
id: 'redis_hgetall',
|
||||
name: 'Redis HGETALL',
|
||||
description: 'Get all fields and values of a hash stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The hash key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'HGETALL',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisHGetAllParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to get hash from Redis')
|
||||
}
|
||||
|
||||
// ioredis .call() returns HGETALL as a flat array [field1, value1, field2, value2, ...]
|
||||
// We convert it to a key-value object for usability
|
||||
const raw = data.result
|
||||
let fields: Record<string, string> = {}
|
||||
|
||||
if (Array.isArray(raw)) {
|
||||
for (let i = 0; i < raw.length; i += 2) {
|
||||
fields[raw[i]] = raw[i + 1] ?? ''
|
||||
}
|
||||
} else if (raw && typeof raw === 'object') {
|
||||
fields = raw
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
fields,
|
||||
fieldCount: Object.keys(fields).length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The hash key' },
|
||||
fields: {
|
||||
type: 'object',
|
||||
description:
|
||||
'All field-value pairs in the hash as a key-value object. Empty object if the key does not exist.',
|
||||
},
|
||||
fieldCount: { type: 'number', description: 'Number of fields in the hash' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { RedisHSetParams, RedisHSetResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisHSetTool: ToolConfig<RedisHSetParams, RedisHSetResponse> = {
|
||||
id: 'redis_hset',
|
||||
name: 'Redis HSET',
|
||||
description: 'Set a field in a hash stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The hash key',
|
||||
},
|
||||
field: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The field name within the hash',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The value to set for the field',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'HSET',
|
||||
args: [params.key, params.field, params.value],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisHSetParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to set hash field in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
field: params?.field ?? '',
|
||||
result: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The hash key' },
|
||||
field: { type: 'string', description: 'The field that was set' },
|
||||
result: {
|
||||
type: 'number',
|
||||
description: 'Number of fields added (1 if new, 0 if updated)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { RedisIncrParams, RedisIncrResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisIncrTool: ToolConfig<RedisIncrParams, RedisIncrResponse> = {
|
||||
id: 'redis_incr',
|
||||
name: 'Redis INCR',
|
||||
description: 'Increment the integer value of a key by one in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to increment',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'INCR',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisIncrParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to increment key in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
value: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was incremented' },
|
||||
value: { type: 'number', description: 'The new value after increment' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { RedisIncrbyParams, RedisIncrbyResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisIncrbyTool: ToolConfig<RedisIncrbyParams, RedisIncrbyResponse> = {
|
||||
id: 'redis_incrby',
|
||||
name: 'Redis INCRBY',
|
||||
description: 'Increment the integer value of a key by a given amount in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to increment',
|
||||
},
|
||||
increment: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Amount to increment by (negative to decrement)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'INCRBY',
|
||||
args: [params.key, params.increment],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisIncrbyParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to increment key in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
value: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was incremented' },
|
||||
value: { type: 'number', description: 'The new value after increment' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
export { redisCommandTool } from '@/tools/redis/command'
|
||||
export { redisDeleteTool } from '@/tools/redis/delete'
|
||||
export { redisExistsTool } from '@/tools/redis/exists'
|
||||
export { redisExpireTool } from '@/tools/redis/expire'
|
||||
export { redisGetTool } from '@/tools/redis/get'
|
||||
export { redisHDelTool } from '@/tools/redis/hdel'
|
||||
export { redisHGetTool } from '@/tools/redis/hget'
|
||||
export { redisHGetAllTool } from '@/tools/redis/hgetall'
|
||||
export { redisHSetTool } from '@/tools/redis/hset'
|
||||
export { redisIncrTool } from '@/tools/redis/incr'
|
||||
export { redisIncrbyTool } from '@/tools/redis/incrby'
|
||||
export { redisKeysTool } from '@/tools/redis/keys'
|
||||
export { redisLLenTool } from '@/tools/redis/llen'
|
||||
export { redisLPopTool } from '@/tools/redis/lpop'
|
||||
export { redisLPushTool } from '@/tools/redis/lpush'
|
||||
export { redisLRangeTool } from '@/tools/redis/lrange'
|
||||
export { redisPersistTool } from '@/tools/redis/persist'
|
||||
export { redisRPopTool } from '@/tools/redis/rpop'
|
||||
export { redisRPushTool } from '@/tools/redis/rpush'
|
||||
export { redisSetTool } from '@/tools/redis/set'
|
||||
export { redisSetnxTool } from '@/tools/redis/setnx'
|
||||
export { redisTtlTool } from '@/tools/redis/ttl'
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { RedisKeysParams, RedisKeysResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisKeysTool: ToolConfig<RedisKeysParams, RedisKeysResponse> = {
|
||||
id: 'redis_keys',
|
||||
name: 'Redis Keys',
|
||||
description:
|
||||
'List all keys matching a pattern in Redis. Avoid using on large databases in production; use the Redis Command tool with SCAN for large key spaces.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
pattern: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pattern to match keys (default: * for all keys)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'KEYS',
|
||||
args: [params.pattern || '*'],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisKeysParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to list keys from Redis')
|
||||
}
|
||||
|
||||
const keys = data.result ?? []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
pattern: params?.pattern || '*',
|
||||
keys,
|
||||
count: keys.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
pattern: { type: 'string', description: 'The pattern used to match keys' },
|
||||
keys: {
|
||||
type: 'array',
|
||||
description: 'List of keys matching the pattern',
|
||||
items: { type: 'string', description: 'A Redis key' },
|
||||
},
|
||||
count: { type: 'number', description: 'Number of keys found' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { RedisLLenParams, RedisLLenResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisLLenTool: ToolConfig<RedisLLenParams, RedisLLenResponse> = {
|
||||
id: 'redis_llen',
|
||||
name: 'Redis LLEN',
|
||||
description: 'Get the length of a list stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The list key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'LLEN',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisLLenParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to get list length from Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
length: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The list key' },
|
||||
length: {
|
||||
type: 'number',
|
||||
description: 'The length of the list, or 0 if the key does not exist',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { RedisLPopParams, RedisLPopResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisLPopTool: ToolConfig<RedisLPopParams, RedisLPopResponse> = {
|
||||
id: 'redis_lpop',
|
||||
name: 'Redis LPOP',
|
||||
description: 'Remove and return the first element of a list stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The list key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'LPOP',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisLPopParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to pop from list in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
value: data.result ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The list key' },
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'The removed element, or null if the list is empty',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { RedisLPushParams, RedisLPushResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisLPushTool: ToolConfig<RedisLPushParams, RedisLPushResponse> = {
|
||||
id: 'redis_lpush',
|
||||
name: 'Redis LPUSH',
|
||||
description: 'Prepend a value to a list stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The list key',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The value to prepend',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'LPUSH',
|
||||
args: [params.key, params.value],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisLPushParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to push to list in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
length: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The list key' },
|
||||
length: { type: 'number', description: 'Length of the list after the push' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import type { RedisLRangeParams, RedisLRangeResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisLRangeTool: ToolConfig<RedisLRangeParams, RedisLRangeResponse> = {
|
||||
id: 'redis_lrange',
|
||||
name: 'Redis LRANGE',
|
||||
description: 'Get a range of elements from a list stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The list key',
|
||||
},
|
||||
start: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start index (0-based)',
|
||||
},
|
||||
stop: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Stop index (-1 for all elements)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'LRANGE',
|
||||
args: [params.key, params.start, params.stop],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisLRangeParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to get list range from Redis')
|
||||
}
|
||||
|
||||
const values = data.result ?? []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
values,
|
||||
count: values.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The list key' },
|
||||
values: {
|
||||
type: 'array',
|
||||
description: 'List elements in the specified range',
|
||||
items: { type: 'string', description: 'A list element' },
|
||||
},
|
||||
count: { type: 'number', description: 'Number of elements returned' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { RedisPersistParams, RedisPersistResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisPersistTool: ToolConfig<RedisPersistParams, RedisPersistResponse> = {
|
||||
id: 'redis_persist',
|
||||
name: 'Redis PERSIST',
|
||||
description: 'Remove the expiration from a key in Redis, making it persist indefinitely.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to persist',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'PERSIST',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisPersistParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to persist key in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
result: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was persisted' },
|
||||
result: {
|
||||
type: 'number',
|
||||
description:
|
||||
'1 if the expiration was removed, 0 if the key does not exist or has no expiration',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { RedisRPopParams, RedisRPopResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisRPopTool: ToolConfig<RedisRPopParams, RedisRPopResponse> = {
|
||||
id: 'redis_rpop',
|
||||
name: 'Redis RPOP',
|
||||
description: 'Remove and return the last element of a list stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The list key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'RPOP',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisRPopParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to pop from list in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
value: data.result ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The list key' },
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'The removed element, or null if the list is empty',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { RedisRPushParams, RedisRPushResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisRPushTool: ToolConfig<RedisRPushParams, RedisRPushResponse> = {
|
||||
id: 'redis_rpush',
|
||||
name: 'Redis RPUSH',
|
||||
description: 'Append a value to the end of a list stored at a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The list key',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The value to append',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'RPUSH',
|
||||
args: [params.key, params.value],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisRPushParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to push to list in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
length: data.result ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The list key' },
|
||||
length: { type: 'number', description: 'Length of the list after the push' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import type { RedisSetParams, RedisSetResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisSetTool: ToolConfig<RedisSetParams, RedisSetResponse> = {
|
||||
id: 'redis_set',
|
||||
name: 'Redis Set',
|
||||
description: 'Set the value of a key in Redis with an optional expiration time in seconds.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to set',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The value to store',
|
||||
},
|
||||
ex: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Expiration time in seconds (optional)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'SET',
|
||||
args: params.ex ? [params.key, params.value, 'EX', params.ex] : [params.key, params.value],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisSetParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to set key in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
result: data.result ?? 'OK',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was set' },
|
||||
result: { type: 'string', description: 'The result of the SET operation (typically "OK")' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { RedisSetnxParams, RedisSetnxResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisSetnxTool: ToolConfig<RedisSetnxParams, RedisSetnxResponse> = {
|
||||
id: 'redis_setnx',
|
||||
name: 'Redis SETNX',
|
||||
description: 'Set the value of a key in Redis only if the key does not already exist.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to set',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The value to store',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'SETNX',
|
||||
args: [params.key, params.value],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisSetnxParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to set key in Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
wasSet: data.result === 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was set' },
|
||||
wasSet: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the key was set (true) or already existed (false)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { RedisTtlParams, RedisTtlResponse } from '@/tools/redis/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const redisTtlTool: ToolConfig<RedisTtlParams, RedisTtlResponse> = {
|
||||
id: 'redis_ttl',
|
||||
name: 'Redis TTL',
|
||||
description: 'Get the remaining time to live (in seconds) of a key in Redis.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Redis connection URL (e.g. redis://user:password@host:port)',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The key to check TTL for',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/redis/execute',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
command: 'TTL',
|
||||
args: [params.key],
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: RedisTtlParams) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to get TTL from Redis')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
key: params?.key ?? '',
|
||||
ttl: data.result ?? -2,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
key: { type: 'string', description: 'The key that was checked' },
|
||||
ttl: {
|
||||
type: 'number',
|
||||
description:
|
||||
'Remaining TTL in seconds. Positive integer if TTL set, -1 if no expiration, -2 if key does not exist.',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
interface RedisBaseParams {
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface RedisGetParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisSetParams extends RedisBaseParams {
|
||||
key: string
|
||||
value: string
|
||||
ex?: number
|
||||
}
|
||||
|
||||
export interface RedisDeleteParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisKeysParams extends RedisBaseParams {
|
||||
pattern?: string
|
||||
}
|
||||
|
||||
export interface RedisCommandParams extends RedisBaseParams {
|
||||
command: string
|
||||
}
|
||||
|
||||
export interface RedisHSetParams extends RedisBaseParams {
|
||||
key: string
|
||||
field: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface RedisHGetParams extends RedisBaseParams {
|
||||
key: string
|
||||
field: string
|
||||
}
|
||||
|
||||
export interface RedisHGetAllParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisIncrParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisIncrbyParams extends RedisBaseParams {
|
||||
key: string
|
||||
increment: number
|
||||
}
|
||||
|
||||
export interface RedisExistsParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisSetnxParams extends RedisBaseParams {
|
||||
key: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface RedisExpireParams extends RedisBaseParams {
|
||||
key: string
|
||||
seconds: number
|
||||
}
|
||||
|
||||
export interface RedisTtlParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisLPushParams extends RedisBaseParams {
|
||||
key: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface RedisLRangeParams extends RedisBaseParams {
|
||||
key: string
|
||||
start: number
|
||||
stop: number
|
||||
}
|
||||
|
||||
export interface RedisRPushParams extends RedisBaseParams {
|
||||
key: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface RedisLPopParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisRPopParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisLLenParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisHDelParams extends RedisBaseParams {
|
||||
key: string
|
||||
field: string
|
||||
}
|
||||
|
||||
export interface RedisPersistParams extends RedisBaseParams {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface RedisGetResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
value: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisSetResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
result: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisDeleteResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
deletedCount: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisKeysResponse extends ToolResponse {
|
||||
output: {
|
||||
pattern: string
|
||||
keys: string[]
|
||||
count: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisCommandResponse extends ToolResponse {
|
||||
output: {
|
||||
command: string
|
||||
result: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisHSetResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
field: string
|
||||
result: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisHGetResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
field: string
|
||||
value: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisHGetAllResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
fields: Record<string, string>
|
||||
fieldCount: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisIncrResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
value: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisIncrbyResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
value: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisExistsResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
exists: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisSetnxResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
wasSet: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisExpireResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
result: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisTtlResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
ttl: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisLPushResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
length: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisLRangeResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
values: string[]
|
||||
count: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisRPushResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
length: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisLPopResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
value: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisRPopResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
value: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisLLenResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
length: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisHDelResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
field: string
|
||||
deleted: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface RedisPersistResponse extends ToolResponse {
|
||||
output: {
|
||||
key: string
|
||||
result: number
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user