@swarmclawai/swarmclaw 0.6.7 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -39
- package/next.config.ts +31 -6
- package/package.json +3 -2
- package/src/app/api/agents/[id]/thread/route.ts +1 -0
- package/src/app/api/agents/route.ts +19 -5
- package/src/app/api/approvals/route.ts +22 -0
- package/src/app/api/chatrooms/[id]/chat/route.ts +4 -0
- package/src/app/api/clawhub/install/route.ts +2 -2
- package/src/app/api/eval/run/route.ts +37 -0
- package/src/app/api/eval/scenarios/route.ts +24 -0
- package/src/app/api/eval/suite/route.ts +29 -0
- package/src/app/api/mcp-servers/[id]/conformance/route.ts +26 -0
- package/src/app/api/mcp-servers/[id]/invoke/route.ts +81 -0
- package/src/app/api/memory/graph/route.ts +46 -0
- package/src/app/api/memory/route.ts +36 -5
- package/src/app/api/notifications/route.ts +3 -0
- package/src/app/api/plugins/install/route.ts +57 -5
- package/src/app/api/plugins/marketplace/route.ts +73 -22
- package/src/app/api/plugins/route.ts +61 -1
- package/src/app/api/plugins/ui/route.ts +34 -0
- package/src/app/api/sessions/[id]/checkpoints/route.ts +31 -0
- package/src/app/api/sessions/[id]/restore/route.ts +36 -0
- package/src/app/api/settings/route.ts +62 -0
- package/src/app/api/setup/doctor/route.ts +22 -5
- package/src/app/api/souls/[id]/route.ts +65 -0
- package/src/app/api/souls/route.ts +70 -0
- package/src/app/api/tasks/[id]/approve/route.ts +4 -3
- package/src/app/api/tasks/[id]/route.ts +16 -3
- package/src/app/api/tasks/route.ts +10 -2
- package/src/app/api/usage/route.ts +9 -2
- package/src/app/globals.css +27 -0
- package/src/app/page.tsx +10 -5
- package/src/cli/index.js +37 -0
- package/src/components/activity/activity-feed.tsx +9 -2
- package/src/components/agents/agent-avatar.tsx +5 -1
- package/src/components/agents/agent-card.tsx +55 -9
- package/src/components/agents/agent-sheet.tsx +112 -34
- package/src/components/agents/inspector-panel.tsx +1 -1
- package/src/components/agents/soul-library-picker.tsx +84 -13
- package/src/components/auth/access-key-gate.tsx +63 -54
- package/src/components/auth/user-picker.tsx +37 -32
- package/src/components/chat/activity-moment.tsx +2 -0
- package/src/components/chat/chat-area.tsx +11 -0
- package/src/components/chat/chat-header.tsx +69 -25
- package/src/components/chat/chat-tool-toggles.tsx +2 -2
- package/src/components/chat/checkpoint-timeline.tsx +112 -0
- package/src/components/chat/code-block.tsx +3 -1
- package/src/components/chat/exec-approval-card.tsx +8 -1
- package/src/components/chat/message-bubble.tsx +164 -4
- package/src/components/chat/message-list.tsx +46 -4
- package/src/components/chat/session-approval-card.tsx +80 -0
- package/src/components/chat/session-debug-panel.tsx +106 -84
- package/src/components/chat/streaming-bubble.tsx +6 -5
- package/src/components/chat/task-approval-card.tsx +78 -0
- package/src/components/chat/thinking-indicator.tsx +48 -12
- package/src/components/chat/tool-call-bubble.tsx +3 -0
- package/src/components/chat/tool-request-banner.tsx +39 -20
- package/src/components/chatrooms/chatroom-list.tsx +11 -4
- package/src/components/chatrooms/chatroom-sheet.tsx +7 -2
- package/src/components/connectors/connector-list.tsx +33 -11
- package/src/components/connectors/connector-sheet.tsx +37 -7
- package/src/components/home/home-view.tsx +54 -24
- package/src/components/input/chat-input.tsx +22 -1
- package/src/components/knowledge/knowledge-list.tsx +17 -18
- package/src/components/knowledge/knowledge-sheet.tsx +9 -5
- package/src/components/layout/app-layout.tsx +87 -19
- package/src/components/mcp-servers/mcp-server-list.tsx +352 -50
- package/src/components/mcp-servers/mcp-server-sheet.tsx +25 -9
- package/src/components/memory/memory-browser.tsx +73 -45
- package/src/components/memory/memory-graph-view.tsx +203 -0
- package/src/components/memory/memory-list.tsx +20 -13
- package/src/components/plugins/plugin-list.tsx +214 -60
- package/src/components/plugins/plugin-sheet.tsx +119 -24
- package/src/components/projects/project-list.tsx +17 -9
- package/src/components/providers/provider-list.tsx +21 -6
- package/src/components/providers/provider-sheet.tsx +42 -25
- package/src/components/runs/run-list.tsx +17 -13
- package/src/components/schedules/schedule-card.tsx +10 -3
- package/src/components/schedules/schedule-list.tsx +2 -2
- package/src/components/schedules/schedule-sheet.tsx +28 -9
- package/src/components/secrets/secret-sheet.tsx +7 -2
- package/src/components/secrets/secrets-list.tsx +18 -5
- package/src/components/sessions/new-session-sheet.tsx +183 -376
- package/src/components/sessions/session-card.tsx +10 -2
- package/src/components/settings/gateway-connection-panel.tsx +9 -8
- package/src/components/shared/command-palette.tsx +13 -5
- package/src/components/shared/empty-state.tsx +20 -8
- package/src/components/shared/hint-tip.tsx +31 -0
- package/src/components/shared/notification-center.tsx +134 -86
- package/src/components/shared/profile-sheet.tsx +4 -0
- package/src/components/shared/settings/plugin-manager.tsx +360 -135
- package/src/components/shared/settings/section-capability-policy.tsx +3 -3
- package/src/components/shared/settings/section-runtime-loop.tsx +149 -4
- package/src/components/skills/clawhub-browser.tsx +1 -0
- package/src/components/skills/skill-list.tsx +31 -12
- package/src/components/skills/skill-sheet.tsx +20 -7
- package/src/components/tasks/approvals-panel.tsx +224 -0
- package/src/components/tasks/task-board.tsx +20 -12
- package/src/components/tasks/task-card.tsx +21 -7
- package/src/components/tasks/task-column.tsx +4 -3
- package/src/components/tasks/task-list.tsx +1 -1
- package/src/components/tasks/task-sheet.tsx +130 -1
- package/src/components/ui/dialog.tsx +1 -0
- package/src/components/ui/sheet.tsx +1 -0
- package/src/components/usage/metrics-dashboard.tsx +72 -48
- package/src/components/wallets/wallet-panel.tsx +65 -41
- package/src/components/wallets/wallet-section.tsx +9 -3
- package/src/components/webhooks/webhook-list.tsx +21 -12
- package/src/components/webhooks/webhook-sheet.tsx +13 -3
- package/src/lib/approval-display.test.ts +45 -0
- package/src/lib/approval-display.ts +62 -0
- package/src/lib/clipboard.ts +38 -0
- package/src/lib/memory.ts +8 -0
- package/src/lib/providers/claude-cli.ts +5 -3
- package/src/lib/providers/index.ts +67 -21
- package/src/lib/runtime-loop.ts +3 -2
- package/src/lib/server/approvals.ts +150 -0
- package/src/lib/server/chat-execution.ts +319 -74
- package/src/lib/server/chatroom-helpers.ts +63 -5
- package/src/lib/server/chatroom-orchestration.ts +74 -0
- package/src/lib/server/clawhub-client.ts +82 -6
- package/src/lib/server/connectors/manager.ts +27 -1
- package/src/lib/server/context-manager.ts +132 -50
- package/src/lib/server/cost.test.ts +73 -0
- package/src/lib/server/cost.ts +165 -34
- package/src/lib/server/daemon-state.ts +112 -1
- package/src/lib/server/data-dir.ts +18 -1
- package/src/lib/server/eval/runner.ts +126 -0
- package/src/lib/server/eval/scenarios.ts +218 -0
- package/src/lib/server/eval/scorer.ts +96 -0
- package/src/lib/server/eval/store.ts +37 -0
- package/src/lib/server/eval/types.ts +48 -0
- package/src/lib/server/execution-log.ts +12 -8
- package/src/lib/server/guardian.ts +34 -0
- package/src/lib/server/heartbeat-service.ts +53 -1
- package/src/lib/server/integrity-monitor.ts +208 -0
- package/src/lib/server/langgraph-checkpoint.ts +10 -0
- package/src/lib/server/link-understanding.ts +55 -0
- package/src/lib/server/llm-response-cache.test.ts +102 -0
- package/src/lib/server/llm-response-cache.ts +227 -0
- package/src/lib/server/main-agent-loop.ts +115 -16
- package/src/lib/server/main-session.ts +6 -3
- package/src/lib/server/mcp-conformance.test.ts +18 -0
- package/src/lib/server/mcp-conformance.ts +233 -0
- package/src/lib/server/memory-db.ts +193 -19
- package/src/lib/server/memory-retrieval.test.ts +56 -0
- package/src/lib/server/mmr.ts +73 -0
- package/src/lib/server/orchestrator-lg.ts +7 -1
- package/src/lib/server/orchestrator.ts +4 -3
- package/src/lib/server/plugins.ts +662 -132
- package/src/lib/server/process-manager.ts +18 -0
- package/src/lib/server/query-expansion.ts +57 -0
- package/src/lib/server/queue.ts +280 -11
- package/src/lib/server/runtime-settings.ts +9 -0
- package/src/lib/server/session-run-manager.test.ts +23 -0
- package/src/lib/server/session-run-manager.ts +32 -2
- package/src/lib/server/session-tools/canvas.ts +85 -50
- package/src/lib/server/session-tools/chatroom.ts +130 -127
- package/src/lib/server/session-tools/connector.ts +233 -454
- package/src/lib/server/session-tools/context-mgmt.ts +87 -105
- package/src/lib/server/session-tools/crud.ts +84 -7
- package/src/lib/server/session-tools/delegate.ts +351 -752
- package/src/lib/server/session-tools/discovery.ts +198 -0
- package/src/lib/server/session-tools/edit_file.ts +82 -0
- package/src/lib/server/session-tools/file-send.test.ts +39 -0
- package/src/lib/server/session-tools/file.ts +257 -425
- package/src/lib/server/session-tools/git.ts +87 -47
- package/src/lib/server/session-tools/http.ts +95 -33
- package/src/lib/server/session-tools/index.ts +217 -138
- package/src/lib/server/session-tools/memory.ts +154 -239
- package/src/lib/server/session-tools/monitor.ts +126 -0
- package/src/lib/server/session-tools/normalize-tool-args.test.ts +61 -0
- package/src/lib/server/session-tools/normalize-tool-args.ts +48 -0
- package/src/lib/server/session-tools/openclaw-nodes.ts +82 -99
- package/src/lib/server/session-tools/openclaw-workspace.ts +103 -93
- package/src/lib/server/session-tools/platform.ts +86 -0
- package/src/lib/server/session-tools/plugin-creator.ts +239 -0
- package/src/lib/server/session-tools/sample-ui.ts +97 -0
- package/src/lib/server/session-tools/sandbox.ts +175 -148
- package/src/lib/server/session-tools/schedule.ts +78 -0
- package/src/lib/server/session-tools/session-info.ts +104 -410
- package/src/lib/server/session-tools/shell-normalize.test.ts +43 -0
- package/src/lib/server/session-tools/shell.ts +171 -143
- package/src/lib/server/session-tools/subagent.ts +77 -77
- package/src/lib/server/session-tools/wallet.ts +182 -106
- package/src/lib/server/session-tools/web.ts +181 -327
- package/src/lib/server/storage.ts +36 -0
- package/src/lib/server/stream-agent-chat.ts +348 -242
- package/src/lib/server/task-quality-gate.test.ts +44 -0
- package/src/lib/server/task-quality-gate.ts +67 -0
- package/src/lib/server/task-validation.test.ts +78 -0
- package/src/lib/server/task-validation.ts +67 -2
- package/src/lib/server/tool-aliases.ts +68 -0
- package/src/lib/server/tool-capability-policy.ts +24 -5
- package/src/lib/server/tool-retry.ts +62 -0
- package/src/lib/server/transcript-repair.ts +72 -0
- package/src/lib/setup-defaults.ts +1 -0
- package/src/lib/tasks.ts +7 -1
- package/src/lib/tool-definitions.ts +24 -23
- package/src/lib/validation/schemas.ts +13 -0
- package/src/lib/view-routes.ts +2 -23
- package/src/stores/use-app-store.ts +23 -1
- package/src/types/index.ts +155 -10
|
@@ -4,6 +4,9 @@ import { execFile } from 'child_process'
|
|
|
4
4
|
import { promisify } from 'util'
|
|
5
5
|
import type { ToolBuildContext } from './context'
|
|
6
6
|
import { findBinaryOnPath, safePath, truncate, MAX_OUTPUT } from './context'
|
|
7
|
+
import type { Plugin, PluginHooks } from '@/types'
|
|
8
|
+
import { getPluginManager } from '../plugins'
|
|
9
|
+
import { normalizeToolInputArgs } from './normalize-tool-args'
|
|
7
10
|
|
|
8
11
|
const execFileAsync = promisify(execFile)
|
|
9
12
|
|
|
@@ -13,59 +16,96 @@ const GIT_ACTIONS = [
|
|
|
13
16
|
'tag', 'reset', 'show',
|
|
14
17
|
] as const
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Core Git Execution Logic
|
|
21
|
+
*/
|
|
22
|
+
async function executeGitAction(args: Record<string, unknown>, bctx: { cwd: string }) {
|
|
23
|
+
const normalized = normalizeToolInputArgs(args)
|
|
24
|
+
const action = typeof normalized.action === 'string' ? normalized.action : ''
|
|
25
|
+
const cmdArgsRaw = (normalized.args ?? normalized.commandArgs ?? normalized.cmdArgs) as string[] | undefined
|
|
26
|
+
const repoPath = (normalized.repoPath ?? normalized.path) as string | undefined
|
|
27
|
+
const timeoutSec = (normalized.timeoutSec ?? normalized.timeout) as number | undefined
|
|
19
28
|
const gitPath = findBinaryOnPath('git')
|
|
20
|
-
if (!gitPath) return
|
|
29
|
+
if (!gitPath) return JSON.stringify({ error: 'Git binary not found on system path' })
|
|
30
|
+
if (!action || !GIT_ACTIONS.includes(action as (typeof GIT_ACTIONS)[number])) {
|
|
31
|
+
return JSON.stringify({ error: `Invalid or missing git action. Allowed: ${GIT_ACTIONS.join(', ')}` })
|
|
32
|
+
}
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
try {
|
|
35
|
+
const cwd = repoPath ? safePath(bctx.cwd, repoPath) : bctx.cwd
|
|
36
|
+
const timeout = Math.max(5, Math.min(timeoutSec ?? 60, 300)) * 1000
|
|
37
|
+
|
|
38
|
+
if (action !== 'clone') {
|
|
39
|
+
try {
|
|
40
|
+
await execFileAsync(gitPath, ['rev-parse', '--is-inside-work-tree'], { cwd, timeout: 5000 })
|
|
41
|
+
} catch {
|
|
42
|
+
return JSON.stringify({ error: `Not a git repository: ${cwd}` })
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
const cmdArgs = [action, ...(cmdArgsRaw ?? [])]
|
|
47
|
+
const result = await execFileAsync(gitPath, cmdArgs, {
|
|
48
|
+
cwd,
|
|
49
|
+
timeout,
|
|
50
|
+
maxBuffer: MAX_OUTPUT,
|
|
51
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
52
|
+
})
|
|
53
|
+
return JSON.stringify({
|
|
54
|
+
exitCode: 0,
|
|
55
|
+
stdout: truncate(result.stdout ?? '', MAX_OUTPUT),
|
|
56
|
+
stderr: truncate(result.stderr ?? '', MAX_OUTPUT),
|
|
57
|
+
})
|
|
58
|
+
} catch (err: unknown) {
|
|
59
|
+
const execErr = err as { code?: number; stdout?: string; stderr?: string; message?: string }
|
|
60
|
+
return JSON.stringify({
|
|
61
|
+
exitCode: execErr.code ?? 1,
|
|
62
|
+
stdout: truncate(execErr.stdout ?? '', MAX_OUTPUT),
|
|
63
|
+
stderr: truncate(execErr.stderr ?? execErr.message ?? String(err), MAX_OUTPUT),
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
}
|
|
37
67
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Register as a Built-in Plugin
|
|
70
|
+
*/
|
|
71
|
+
const GitPlugin: Plugin = {
|
|
72
|
+
name: 'Core Git',
|
|
73
|
+
description: 'Structured git operations: status, commit, push, diff, and more.',
|
|
74
|
+
hooks: {} as PluginHooks,
|
|
75
|
+
tools: [
|
|
76
|
+
{
|
|
77
|
+
name: 'git',
|
|
78
|
+
description: 'Run git operations in the workspace.',
|
|
79
|
+
parameters: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: {
|
|
82
|
+
action: { type: 'string', enum: [...GIT_ACTIONS] },
|
|
83
|
+
args: { type: 'array', items: { type: 'string' } },
|
|
84
|
+
repoPath: { type: 'string' },
|
|
85
|
+
timeoutSec: { type: 'number' }
|
|
86
|
+
},
|
|
87
|
+
required: ['action']
|
|
58
88
|
},
|
|
89
|
+
execute: async (args, context) => executeGitAction(args, { cwd: context.session.cwd || process.cwd() })
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getPluginManager().registerBuiltin('git', GitPlugin)
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Legacy Bridge
|
|
98
|
+
*/
|
|
99
|
+
export function buildGitTools(bctx: ToolBuildContext): StructuredToolInterface[] {
|
|
100
|
+
if (!bctx.hasTool('git')) return []
|
|
101
|
+
return [
|
|
102
|
+
tool(
|
|
103
|
+
async (args) => executeGitAction(args, { cwd: bctx.cwd }),
|
|
59
104
|
{
|
|
60
105
|
name: 'git',
|
|
61
|
-
description:
|
|
62
|
-
schema: z.object({
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
repoPath: z.string().optional().describe('Relative path to git repo (defaults to working directory)'),
|
|
66
|
-
timeoutSec: z.number().optional().describe('Timeout in seconds (default 60, max 300)'),
|
|
67
|
-
}),
|
|
68
|
-
},
|
|
69
|
-
),
|
|
106
|
+
description: GitPlugin.tools![0].description,
|
|
107
|
+
schema: z.object({}).passthrough()
|
|
108
|
+
}
|
|
109
|
+
)
|
|
70
110
|
]
|
|
71
111
|
}
|
|
@@ -2,47 +2,109 @@ import { z } from 'zod'
|
|
|
2
2
|
import { tool, type StructuredToolInterface } from '@langchain/core/tools'
|
|
3
3
|
import type { ToolBuildContext } from './context'
|
|
4
4
|
import { truncate, MAX_OUTPUT } from './context'
|
|
5
|
+
import { withRetry } from '../tool-retry'
|
|
6
|
+
import type { Plugin, PluginHooks } from '@/types'
|
|
7
|
+
import { getPluginManager } from '../plugins'
|
|
8
|
+
import { normalizeToolInputArgs } from './normalize-tool-args'
|
|
5
9
|
|
|
10
|
+
interface HttpRequestArgs {
|
|
11
|
+
method: string
|
|
12
|
+
url: string
|
|
13
|
+
headers?: Record<string, string>
|
|
14
|
+
body?: string
|
|
15
|
+
timeoutSec?: number
|
|
16
|
+
followRedirects?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Core HTTP Execution Logic
|
|
21
|
+
*/
|
|
22
|
+
async function executeHttpAction(args: HttpRequestArgs) {
|
|
23
|
+
const normalized = normalizeToolInputArgs((args ?? {}) as unknown as Record<string, unknown>)
|
|
24
|
+
const requestArgs: HttpRequestArgs = {
|
|
25
|
+
method: String(normalized.method || '').toUpperCase(),
|
|
26
|
+
url: String(normalized.url || ''),
|
|
27
|
+
headers: normalized.headers as Record<string, string> | undefined,
|
|
28
|
+
body: typeof normalized.body === 'string' ? normalized.body : undefined,
|
|
29
|
+
timeoutSec: typeof normalized.timeoutSec === 'number' ? normalized.timeoutSec : undefined,
|
|
30
|
+
followRedirects: typeof normalized.followRedirects === 'boolean' ? normalized.followRedirects : undefined,
|
|
31
|
+
}
|
|
32
|
+
return withRetry(async (_a: HttpRequestArgs) => {
|
|
33
|
+
try {
|
|
34
|
+
const timeout = Math.max(1, Math.min(_a.timeoutSec ?? 30, 120)) * 1000
|
|
35
|
+
const init: RequestInit = {
|
|
36
|
+
method: _a.method,
|
|
37
|
+
headers: (_a.headers ?? undefined) as Record<string, string> | undefined,
|
|
38
|
+
signal: AbortSignal.timeout(timeout),
|
|
39
|
+
}
|
|
40
|
+
if (_a.body && _a.method !== 'GET' && _a.method !== 'HEAD') {
|
|
41
|
+
init.body = _a.body
|
|
42
|
+
}
|
|
43
|
+
if (_a.followRedirects === false) {
|
|
44
|
+
init.redirect = 'manual'
|
|
45
|
+
}
|
|
46
|
+
const res = await fetch(_a.url, init)
|
|
47
|
+
const resHeaders: Record<string, string> = {}
|
|
48
|
+
for (const key of ['content-type', 'location', 'x-request-id', 'retry-after', 'content-length']) {
|
|
49
|
+
const val = res.headers.get(key)
|
|
50
|
+
if (val) resHeaders[key] = val
|
|
51
|
+
}
|
|
52
|
+
let resBody: string
|
|
53
|
+
const ct = res.headers.get('content-type') ?? ''
|
|
54
|
+
if (ct.includes('image/') || ct.includes('audio/') || ct.includes('video/') || ct.includes('application/octet-stream')) {
|
|
55
|
+
resBody = `[binary content, ${res.headers.get('content-length') ?? 'unknown'} bytes]`
|
|
56
|
+
} else {
|
|
57
|
+
resBody = truncate(await res.text(), MAX_OUTPUT)
|
|
58
|
+
}
|
|
59
|
+
return JSON.stringify({ status: res.status, statusText: res.statusText, headers: resHeaders, body: resBody })
|
|
60
|
+
} catch (err: unknown) {
|
|
61
|
+
return JSON.stringify({ error: err instanceof Error ? err.message : String(err) })
|
|
62
|
+
}
|
|
63
|
+
}, requestArgs)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Register as a Built-in Plugin
|
|
68
|
+
*/
|
|
69
|
+
const HttpPlugin: Plugin = {
|
|
70
|
+
name: 'Core HTTP',
|
|
71
|
+
description: 'Make direct HTTP API calls with custom methods, headers, and bodies.',
|
|
72
|
+
hooks: {} as PluginHooks,
|
|
73
|
+
tools: [
|
|
74
|
+
{
|
|
75
|
+
name: 'http_request',
|
|
76
|
+
description: 'Make an HTTP API request.',
|
|
77
|
+
parameters: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
properties: {
|
|
80
|
+
method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] },
|
|
81
|
+
url: { type: 'string' },
|
|
82
|
+
headers: { type: 'object', additionalProperties: { type: 'string' } },
|
|
83
|
+
body: { type: 'string' },
|
|
84
|
+
timeoutSec: { type: 'number' },
|
|
85
|
+
followRedirects: { type: 'boolean' }
|
|
86
|
+
},
|
|
87
|
+
required: ['method', 'url']
|
|
88
|
+
},
|
|
89
|
+
execute: async (args) => executeHttpAction(args as unknown as HttpRequestArgs)
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getPluginManager().registerBuiltin('http', HttpPlugin)
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Legacy Bridge
|
|
98
|
+
*/
|
|
6
99
|
export function buildHttpTools(bctx: ToolBuildContext): StructuredToolInterface[] {
|
|
7
100
|
if (!bctx.hasTool('http_request')) return []
|
|
8
101
|
|
|
9
102
|
return [
|
|
10
103
|
tool(
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
const timeout = Math.max(1, Math.min(timeoutSec ?? 30, 120)) * 1000
|
|
14
|
-
const init: RequestInit = {
|
|
15
|
-
method,
|
|
16
|
-
headers: (headers ?? undefined) as Record<string, string> | undefined,
|
|
17
|
-
signal: AbortSignal.timeout(timeout),
|
|
18
|
-
}
|
|
19
|
-
if (body && method !== 'GET' && method !== 'HEAD') {
|
|
20
|
-
init.body = body
|
|
21
|
-
}
|
|
22
|
-
if (followRedirects === false) {
|
|
23
|
-
init.redirect = 'manual'
|
|
24
|
-
}
|
|
25
|
-
const res = await fetch(url, init)
|
|
26
|
-
const resHeaders: Record<string, string> = {}
|
|
27
|
-
for (const key of ['content-type', 'location', 'x-request-id', 'retry-after', 'content-length']) {
|
|
28
|
-
const val = res.headers.get(key)
|
|
29
|
-
if (val) resHeaders[key] = val
|
|
30
|
-
}
|
|
31
|
-
let resBody: string
|
|
32
|
-
const ct = res.headers.get('content-type') ?? ''
|
|
33
|
-
if (ct.includes('image/') || ct.includes('audio/') || ct.includes('video/') || ct.includes('application/octet-stream')) {
|
|
34
|
-
resBody = `[binary content, ${res.headers.get('content-length') ?? 'unknown'} bytes]`
|
|
35
|
-
} else {
|
|
36
|
-
resBody = truncate(await res.text(), MAX_OUTPUT)
|
|
37
|
-
}
|
|
38
|
-
return JSON.stringify({ status: res.status, statusText: res.statusText, headers: resHeaders, body: resBody })
|
|
39
|
-
} catch (err: unknown) {
|
|
40
|
-
return JSON.stringify({ error: err instanceof Error ? err.message : String(err) })
|
|
41
|
-
}
|
|
42
|
-
},
|
|
104
|
+
(args: HttpRequestArgs) => executeHttpAction(args),
|
|
43
105
|
{
|
|
44
106
|
name: 'http_request',
|
|
45
|
-
description:
|
|
107
|
+
description: HttpPlugin.tools![0].description,
|
|
46
108
|
schema: z.object({
|
|
47
109
|
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']).describe('HTTP method'),
|
|
48
110
|
url: z.string().describe('Full URL to request'),
|