Merge branch 'upstream' into concedo_experimental

# Conflicts:
#	.ecrc
#	.github/actions/get-tag-name/action.yml
#	.github/actions/windows-setup-cuda/action.yml
#	.github/workflows/build-cuda-ubuntu.yml
#	.github/workflows/build-cuda-windows.yml
#	.github/workflows/build-self-hosted.yml
#	.github/workflows/release.yml
#	.github/workflows/server-self-hosted.yml
#	CONTRIBUTING.md
#	app/CMakeLists.txt
#	ci/run.sh
#	docs/backend/OPENVINO.md
#	docs/ops.md
#	docs/ops/CUDA.csv
#	examples/eval-callback/CMakeLists.txt
#	ggml/src/ggml-hexagon/htp/cpy-ops.c
#	ggml/src/ggml-opencl/ggml-opencl.cpp
#	ggml/src/ggml-opencl/kernels/moe_reorder_b.cl
#	ggml/src/ggml-opencl/kernels/ssm_scan.cl
#	ggml/src/ggml-openvino/ggml-decoder.cpp
#	ggml/src/ggml-openvino/ggml-decoder.h
#	ggml/src/ggml-openvino/ggml-openvino-extra.cpp
#	ggml/src/ggml-openvino/ggml-openvino-extra.h
#	ggml/src/ggml-openvino/ggml-openvino.cpp
#	ggml/src/ggml-openvino/ggml-quants.cpp
#	ggml/src/ggml-openvino/ggml-quants.h
#	ggml/src/ggml-openvino/openvino/frontend.cpp
#	ggml/src/ggml-openvino/openvino/node_context.h
#	ggml/src/ggml-openvino/openvino/op/add.cpp
#	ggml/src/ggml-openvino/openvino/op/diag.cpp
#	ggml/src/ggml-openvino/openvino/op/div.cpp
#	ggml/src/ggml-openvino/openvino/op/glu_geglu_quick.cpp
#	ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp
#	ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp
#	ggml/src/ggml-openvino/openvino/op/mulmat.cpp
#	ggml/src/ggml-openvino/openvino/op/norm.cpp
#	ggml/src/ggml-openvino/openvino/op/pad.cpp
#	ggml/src/ggml-openvino/openvino/op/permute.cpp
#	ggml/src/ggml-openvino/openvino/op/rope.cpp
#	ggml/src/ggml-openvino/openvino/op/set_rows.cpp
#	ggml/src/ggml-openvino/openvino/op/transpose.cpp
#	ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp
#	ggml/src/ggml-openvino/openvino/op_table.cpp
#	ggml/src/ggml-openvino/openvino/op_table.h
#	ggml/src/ggml-openvino/openvino/pass/squeeze_matmul.cpp
#	ggml/src/ggml-openvino/openvino/translate_session.cpp
#	ggml/src/ggml-openvino/utils.cpp
#	ggml/src/ggml-openvino/utils.h
#	scripts/hip/gcn-cdna-vgpr-check.py
#	tests/CMakeLists.txt
#	tests/test-backend-ops.cpp
#	tools/server/CMakeLists.txt
#	tools/tuning/CMakeLists.txt
This commit is contained in:
Concedo
2026-09-16 15:32:56 +08:00
32 changed files with 695 additions and 209 deletions
@@ -47,7 +47,7 @@ export function useToolsPanel(): UseToolsPanelReturn {
if (toolsStore.toolGroups.length > 0) return null;
// Tools endpoint is unreachable (404) — server started without --tools
// Tools endpoint unreachable (403) — server started without tools
if (toolsStore.isToolsEndpointUnreachable) {
return `The KoboldCpp MCP bridge may accessible on the same URL with /mcp at the end but must be added manually.`;
}
@@ -315,8 +315,14 @@ class AgenticStore {
// Clear any pending permissions/continue requests for this conversation when starting a new flow
this.gates.clear(conversationId);
// Ensure server tools are fetched before checking if agentic is enabled
if (toolsStore.serverTools.length === 0 && !toolsStore.loading) {
// Ensure server tools are fetched before checking if agentic is enabled.
// A disabled /tools endpoint stays disabled for the life of the server,
// so the tools panel is the only place that probes it again.
if (
toolsStore.serverTools.length === 0 &&
!toolsStore.loading &&
!toolsStore.isToolsEndpointUnreachable
) {
await toolsStore.fetchServerTools();
}
+3 -6
View File
@@ -32,7 +32,7 @@ import { mcpStore } from '$lib/stores/mcp/index.svelte';
import { modelsStore } from '$lib/stores/models/index.svelte';
import { settingsStore } from '$lib/stores/settings/index.svelte';
import type { OpenAIToolDefinition, ToolEntry, ToolGroup } from '$lib/types';
import { buildSandboxToolDefinition } from '$lib/utils';
import { ApiError, buildSandboxToolDefinition } from '$lib/utils';
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
/** Stable selection identity for a tool, shared by the disabled set and the permission store */
@@ -246,13 +246,10 @@ class ToolsStore {
toolInfos.filter((info) => info.uses_cwd).map((info) => info.tool)
);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
this._error = errorMessage;
this._error = err instanceof Error ? err.message : String(err);
// 403 from /tools means the server was started without --tools
// TODO: check status code instead of relying on message
if (errorMessage.includes('this feature is disabled')) {
if (err instanceof ApiError && err.status === 403) {
this._toolsEndpointUnreachable = true;
console.info('[ToolsStore] Server tools are disabled on the server');
} else {