feat: Tools Atomic PR of #20243 (#20370)

* feat: Add read-only access support for Tools

- Backend: Add write_access field to ToolAccessResponse
- Backend: Update /tools/list to return tools with write_access
- Frontend: Display Read Only badge in Tools list
- Frontend: Disable inputs and save button when no write access
- Frontend: Add readOnly prop to CodeEditor component

* Update Tools.svelte

* fix: Return write_access from getToolById endpoint

fix: Return write_access from getToolById endpoint

- Use ToolAccessResponse instead of raw dict
- Remove inefficient getToolList call in edit page

* refactor: Rename write_access to disabled in ToolkitEditor

- Rename prop from write_access to disabled
- Invert logic where needed
- Update edit page to pass disabled instead of write_access

* rem

* Update +page.svelte

* fix

* Update ToolkitEditor.svelte

* Update CodeEditor.svelte

* Update ToolkitEditor.svelte
This commit is contained in:
Classic298
2026-01-06 03:00:48 +04:00
committed by GitHub
parent 5921a19519
commit c87031e9a6
3 changed files with 102 additions and 36 deletions
+74 -31
View File
@@ -37,6 +37,7 @@
import AddToolMenu from './Tools/AddToolMenu.svelte';
import ImportModal from '../ImportModal.svelte';
import ViewSelector from './common/ViewSelector.svelte';
import Badge from '$lib/components/common/Badge.svelte';
let shiftKey = false;
let loaded = false;
@@ -357,45 +358,86 @@
{#each filteredItems as tool}
<Tooltip content={tool?.meta?.description ?? tool?.id}>
<div
class=" flex space-x-4 cursor-pointer text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
class=" flex space-x-4 text-left w-full px-3 py-2.5 transition rounded-2xl {tool.write_access ? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50' : 'cursor-not-allowed opacity-60'}"
>
<a
class=" flex flex-1 space-x-3.5 cursor-pointer w-full"
href={`/workspace/tools/edit?id=${encodeURIComponent(tool.id)}`}
>
<div class="flex items-center text-left">
<div class=" flex-1 self-center">
<Tooltip content={tool.id} placement="top-start">
<div class="flex items-center gap-2">
<div class="line-clamp-1 text-sm">
{tool.name}
</div>
{#if tool?.meta?.manifest?.version}
<div class=" text-gray-500 text-xs font-medium shrink-0">
v{tool?.meta?.manifest?.version ?? ''}
{#if tool.write_access}
<a
class=" flex flex-1 space-x-3.5 cursor-pointer w-full"
href={`/workspace/tools/edit?id=${encodeURIComponent(tool.id)}`}
>
<div class="flex items-center text-left">
<div class=" flex-1 self-center">
<Tooltip content={tool.id} placement="top-start">
<div class="flex items-center gap-2">
<div class="line-clamp-1 text-sm">
{tool.name}
</div>
{/if}
{#if tool?.meta?.manifest?.version}
<div class=" text-gray-500 text-xs font-medium shrink-0">
v{tool?.meta?.manifest?.version ?? ''}
</div>
{/if}
</div>
</Tooltip>
<div class="px-0.5">
<div class="text-xs text-gray-500 shrink-0">
<Tooltip
content={tool?.user?.email ?? $i18n.t('Deleted User')}
className="flex shrink-0"
placement="top-start"
>
{$i18n.t('By {{name}}', {
name: capitalizeFirstLetter(
tool?.user?.name ?? tool?.user?.email ?? $i18n.t('Deleted User')
)
})}
</Tooltip>
</div>
</div>
</Tooltip>
<div class="px-0.5">
<div class="text-xs text-gray-500 shrink-0">
<Tooltip
content={tool?.user?.email ?? $i18n.t('Deleted User')}
className="flex shrink-0"
placement="top-start"
>
{$i18n.t('By {{name}}', {
name: capitalizeFirstLetter(
tool?.user?.name ?? tool?.user?.email ?? $i18n.t('Deleted User')
)
})}
</div>
</div>
</a>
{:else}
<div
class=" flex flex-1 space-x-3.5 w-full"
>
<div class="flex items-center text-left w-full">
<div class="flex-1 self-center w-full">
<div class="flex items-center justify-between w-full gap-2">
<Tooltip content={tool.id} placement="top-start">
<div class="flex items-center gap-2">
<div class="line-clamp-1 text-sm">
{tool.name}
</div>
{#if tool?.meta?.manifest?.version}
<div class=" text-gray-500 text-xs font-medium shrink-0">
v{tool?.meta?.manifest?.version ?? ''}
</div>
{/if}
</div>
</Tooltip>
<Badge type="muted" content={$i18n.t('Read Only')} />
</div>
<div class="px-0.5">
<div class="text-xs text-gray-500 shrink-0">
<Tooltip
content={tool?.user?.email ?? $i18n.t('Deleted User')}
className="flex shrink-0"
placement="top-start"
>
{$i18n.t('By {{name}}', {
name: capitalizeFirstLetter(
tool?.user?.name ?? tool?.user?.email ?? $i18n.t('Deleted User')
)
})}
</Tooltip>
</div>
</div>
</div>
</div>
</div>
</a>
{/if}
{#if tool.write_access}
<div class="flex flex-row gap-0.5 self-center">
{#if shiftKey}
<Tooltip content={$i18n.t('Delete')}>
@@ -484,6 +526,7 @@
</ToolMenu>
{/if}
</div>
{/if}
</div>
</Tooltip>
{/each}