2 Commits

Author SHA1 Message Date
b656859b10 chore: bump version to 0.4.13
Some checks failed
Create Release / release (push) Has been cancelled
2026-01-07 11:38:50 +01:00
d9b009ce0a feat: add test button for HTTP endpoint tools
Adds the ability to test HTTP endpoint custom tools directly in the
editor, matching the existing test functionality for Python and
JavaScript tools. Closes #6.
2026-01-07 11:38:33 +01:00
4 changed files with 76 additions and 5 deletions

View File

@@ -18,7 +18,7 @@ import (
)
// Version is set at build time via -ldflags, or defaults to dev
var Version = "0.4.12"
var Version = "0.4.13"
func getEnvOrDefault(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {

View File

@@ -1,6 +1,6 @@
{
"name": "vessel",
"version": "0.4.12",
"version": "0.4.13",
"private": true,
"type": "module",
"scripts": {

View File

@@ -513,6 +513,29 @@ print(json.dumps(result))`;
</label>
</div>
</div>
<!-- Test button for HTTP -->
<button
type="button"
onclick={() => showTest = !showTest}
class="flex items-center gap-2 text-sm {showTest ? 'text-emerald-400' : 'text-theme-muted hover:text-theme-secondary'}"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</svg>
{showTest ? 'Hide Test Panel' : 'Test Tool'}
</button>
<!-- Tool tester for HTTP -->
<ToolTester
{implementation}
code=""
{endpoint}
{httpMethod}
parameters={buildParameterSchema()}
isOpen={showTest}
onclose={() => showTest = false}
/>
</div>
{/if}

View File

@@ -10,11 +10,13 @@
implementation: ToolImplementation;
code: string;
parameters: JSONSchema;
endpoint?: string;
httpMethod?: 'GET' | 'POST';
isOpen?: boolean;
onclose?: () => void;
}
const { implementation, code, parameters, isOpen = false, onclose }: Props = $props();
const { implementation, code, parameters, endpoint = '', httpMethod = 'POST', isOpen = false, onclose }: Props = $props();
let testInput = $state('{}');
let testResult = $state<{ success: boolean; result?: unknown; error?: string } | null>(null);
@@ -116,8 +118,54 @@
error: error instanceof Error ? error.message : String(error)
};
}
} else if (implementation === 'http') {
// HTTP endpoint execution
if (!endpoint.trim()) {
testResult = { success: false, error: 'HTTP endpoint URL is required' };
isRunning = false;
return;
}
try {
const url = new URL(endpoint);
const options: RequestInit = {
method: httpMethod,
headers: {
'Content-Type': 'application/json'
}
};
if (httpMethod === 'GET') {
// Add args as query parameters
for (const [key, value] of Object.entries(args)) {
url.searchParams.set(key, String(value));
}
} else {
options.body = JSON.stringify(args);
}
const response = await fetch(url.toString(), options);
if (!response.ok) {
testResult = {
success: false,
error: `HTTP ${response.status}: ${response.statusText}`
};
} else {
const contentType = response.headers.get('content-type');
const result = contentType?.includes('application/json')
? await response.json()
: await response.text();
testResult = { success: true, result };
}
} catch (error) {
testResult = {
success: false,
error: error instanceof Error ? error.message : String(error)
};
}
} else {
testResult = { success: false, error: 'HTTP tools cannot be tested in the editor' };
testResult = { success: false, error: 'Unknown implementation type' };
}
} finally {
isRunning = false;
@@ -169,7 +217,7 @@
<button
type="button"
onclick={runTest}
disabled={isRunning || !code.trim()}
disabled={isRunning || (implementation === 'http' ? !endpoint.trim() : !code.trim())}
class="flex items-center gap-2 px-3 py-1.5 text-sm font-medium rounded-lg bg-emerald-600 text-white hover:bg-emerald-500 disabled:opacity-50 disabled:cursor-not-allowed"
>
{#if isRunning}