mh-local 0.1.0__tar.gz

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.
Files changed (30) hide show
  1. mh_local-0.1.0/PKG-INFO +78 -0
  2. mh_local-0.1.0/README.md +69 -0
  3. mh_local-0.1.0/pyproject.toml +30 -0
  4. mh_local-0.1.0/src/mh_local/__init__.py +0 -0
  5. mh_local-0.1.0/src/mh_local/__main__.py +3 -0
  6. mh_local-0.1.0/src/mh_local/app.py +216 -0
  7. mh_local-0.1.0/src/mh_local/auth.py +37 -0
  8. mh_local-0.1.0/src/mh_local/main.py +85 -0
  9. mh_local-0.1.0/src/mh_local/static/assets/AgentManagementPage-DUOZSqNs.js +1 -0
  10. mh_local-0.1.0/src/mh_local/static/assets/AgentManagementPage-KqRVCS47.css +1 -0
  11. mh_local-0.1.0/src/mh_local/static/assets/ManagementNav-B04kM4lZ.css +1 -0
  12. mh_local-0.1.0/src/mh_local/static/assets/ManagementNav-DXmOEWXa.js +1 -0
  13. mh_local-0.1.0/src/mh_local/static/assets/ProviderManagementPage-8bXp0e9V.js +1 -0
  14. mh_local-0.1.0/src/mh_local/static/assets/ProviderManagementPage-hhRPoUOy.css +1 -0
  15. mh_local-0.1.0/src/mh_local/static/assets/SceneManagementPage-By_fC3Kg.js +1 -0
  16. mh_local-0.1.0/src/mh_local/static/assets/SceneManagementPage-ChRTKhoK.css +1 -0
  17. mh_local-0.1.0/src/mh_local/static/assets/ToolManagementPage-CNuLgZ0K.css +1 -0
  18. mh_local-0.1.0/src/mh_local/static/assets/ToolManagementPage-CjRq41m3.js +1 -0
  19. mh_local-0.1.0/src/mh_local/static/assets/index-BGUaSXe5.css +1 -0
  20. mh_local-0.1.0/src/mh_local/static/assets/index-DVOv8YZP.js +115 -0
  21. mh_local-0.1.0/src/mh_local/static/component/mh-extra-components.umd.js +9 -0
  22. mh_local-0.1.0/src/mh_local/static/component/mh-tool-components.umd.js +1 -0
  23. mh_local-0.1.0/src/mh_local/static/favicon.svg +3 -0
  24. mh_local-0.1.0/src/mh_local/static/index.html +23 -0
  25. mh_local-0.1.0/src/mh_local/storage/__init__.py +0 -0
  26. mh_local-0.1.0/src/mh_local/storage/paths.py +64 -0
  27. mh_local-0.1.0/src/mh_local/storage/provider_store.py +120 -0
  28. mh_local-0.1.0/src/mh_local/storage/registry_store.py +900 -0
  29. mh_local-0.1.0/src/mh_local/storage/script_store.py +40 -0
  30. mh_local-0.1.0/src/mh_local/storage/session_store.py +306 -0
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.3
2
+ Name: mh-local
3
+ Version: 0.1.0
4
+ Summary: Minimal Harness Client — pure local Agent assistant
5
+ Requires-Dist: uvicorn[standard]>=0.30.0
6
+ Requires-Dist: mh-gateway>=0.1.0
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+
10
+ # mh-local
11
+
12
+ A self-contained local Agent assistant powered by [minimal-harness](https://github.com/J0ey1iu/minimal-harness). It bundles a FastAPI backend with a built-in Vue 3 SPA frontend — no database, no external service dependencies.
13
+
14
+ Latest version: **0.1.0**
15
+
16
+ ## Features
17
+
18
+ - **No cloud required** — runs entirely on localhost, single-user
19
+ - **Built-in web UI** — chat interface with agent, scene, tool, and LLM provider management
20
+ - **No database** — file-based sessions and registries under `~/.config/mh-local/`
21
+ - **Auto-discovery** — automatically creates a workspace scene from the current directory
22
+ - **Custom tool scripts** — drag-and-drop upload `.py` files; the gateway validates required metadata and the shebang interpreter, then runs `execute()` in a child process with streamed `ToolProgress` events
23
+
24
+ ## Quick start
25
+
26
+ ```bash
27
+ uv add mh-local
28
+ uv run mh-local
29
+ ```
30
+
31
+ Your browser will open automatically to `http://127.0.0.1:<port>`.
32
+
33
+ On first run, you'll be prompted to configure an LLM provider (API key, base URL) via the web UI's Provider management page.
34
+
35
+ ## Usage
36
+
37
+ After starting, mh-local serves a full-featured chat UI at the local URL with:
38
+
39
+ - **Chat** — converse with AI agents with streaming responses
40
+ - **Manage Agents** — view and configure built-in agents (General Assistant `triage`, Tool Maker `tool-maker`)
41
+ - **Manage Tools** — inspect built-in tools (`bash`, `handoff`, `discover_agents`, `local_file_operator`) or upload custom tool scripts
42
+ - **Manage Scenes** — workspace management for different projects (one auto-created per `cwd` on first launch)
43
+ - **Manage Providers** — configure LLM providers (OpenAI, Anthropic, etc.)
44
+
45
+ ## How it works
46
+
47
+ ```
48
+ mh-local
49
+ ├── FastAPI app (mh_gateway-based) — serves API + static files
50
+ ├── Vue 3 SPA — chat UI served at /
51
+ ├── File-based stores:
52
+ │ ├── sessions/ — conversation history
53
+ │ ├── providers.json — LLM provider config
54
+ │ └── registry.json — agents, tools, scenes
55
+ └── Local auth — auto-grants admin access
56
+ ```
57
+
58
+ ## Configuration
59
+
60
+ All configuration is done through the web UI. Persistent data lives at:
61
+
62
+ | Path | Contents |
63
+ |------|----------|
64
+ | `~/.config/mh-local/providers.json` | LLM provider credentials |
65
+ | `~/.config/mh-local/registry.json` | Agent/tool/scene registrations |
66
+ | `~/.config/mh-local/sessions/` | Chat session files |
67
+ | `~/.config/mh-local/logs/` | Runtime logs |
68
+
69
+ ## Development
70
+
71
+ ```bash
72
+ # Build frontend (SPA + component UMD bundles)
73
+ powershell scripts/build-mh-local-frontend.ps1 # Windows
74
+ bash scripts/build-mh-local-frontend.sh # Linux/macOS
75
+
76
+ # Run
77
+ uv run mh-local
78
+ ```
@@ -0,0 +1,69 @@
1
+ # mh-local
2
+
3
+ A self-contained local Agent assistant powered by [minimal-harness](https://github.com/J0ey1iu/minimal-harness). It bundles a FastAPI backend with a built-in Vue 3 SPA frontend — no database, no external service dependencies.
4
+
5
+ Latest version: **0.1.0**
6
+
7
+ ## Features
8
+
9
+ - **No cloud required** — runs entirely on localhost, single-user
10
+ - **Built-in web UI** — chat interface with agent, scene, tool, and LLM provider management
11
+ - **No database** — file-based sessions and registries under `~/.config/mh-local/`
12
+ - **Auto-discovery** — automatically creates a workspace scene from the current directory
13
+ - **Custom tool scripts** — drag-and-drop upload `.py` files; the gateway validates required metadata and the shebang interpreter, then runs `execute()` in a child process with streamed `ToolProgress` events
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ uv add mh-local
19
+ uv run mh-local
20
+ ```
21
+
22
+ Your browser will open automatically to `http://127.0.0.1:<port>`.
23
+
24
+ On first run, you'll be prompted to configure an LLM provider (API key, base URL) via the web UI's Provider management page.
25
+
26
+ ## Usage
27
+
28
+ After starting, mh-local serves a full-featured chat UI at the local URL with:
29
+
30
+ - **Chat** — converse with AI agents with streaming responses
31
+ - **Manage Agents** — view and configure built-in agents (General Assistant `triage`, Tool Maker `tool-maker`)
32
+ - **Manage Tools** — inspect built-in tools (`bash`, `handoff`, `discover_agents`, `local_file_operator`) or upload custom tool scripts
33
+ - **Manage Scenes** — workspace management for different projects (one auto-created per `cwd` on first launch)
34
+ - **Manage Providers** — configure LLM providers (OpenAI, Anthropic, etc.)
35
+
36
+ ## How it works
37
+
38
+ ```
39
+ mh-local
40
+ ├── FastAPI app (mh_gateway-based) — serves API + static files
41
+ ├── Vue 3 SPA — chat UI served at /
42
+ ├── File-based stores:
43
+ │ ├── sessions/ — conversation history
44
+ │ ├── providers.json — LLM provider config
45
+ │ └── registry.json — agents, tools, scenes
46
+ └── Local auth — auto-grants admin access
47
+ ```
48
+
49
+ ## Configuration
50
+
51
+ All configuration is done through the web UI. Persistent data lives at:
52
+
53
+ | Path | Contents |
54
+ |------|----------|
55
+ | `~/.config/mh-local/providers.json` | LLM provider credentials |
56
+ | `~/.config/mh-local/registry.json` | Agent/tool/scene registrations |
57
+ | `~/.config/mh-local/sessions/` | Chat session files |
58
+ | `~/.config/mh-local/logs/` | Runtime logs |
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ # Build frontend (SPA + component UMD bundles)
64
+ powershell scripts/build-mh-local-frontend.ps1 # Windows
65
+ bash scripts/build-mh-local-frontend.sh # Linux/macOS
66
+
67
+ # Run
68
+ uv run mh-local
69
+ ```
@@ -0,0 +1,30 @@
1
+ [project]
2
+ name = "mh-local"
3
+ version = "0.1.0"
4
+ description = "Minimal Harness Client — pure local Agent assistant"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "uvicorn[standard]>=0.30.0",
9
+ "mh-gateway>=0.1.0",
10
+ ]
11
+
12
+ [project.scripts]
13
+ mh-local = "mh_local.main:run"
14
+
15
+ [build-system]
16
+ requires = ["uv_build>=0.10.12,<0.12"]
17
+ build-backend = "uv_build"
18
+
19
+ [tool.setuptools.packages.find]
20
+ where = ["src"]
21
+
22
+ [tool.setuptools.package-data]
23
+ mh_local = ["static/**/*"]
24
+
25
+ [tool.uv.sources]
26
+ mh-gateway = { workspace = true }
27
+
28
+ [[tool.uv.index]]
29
+ url = "https://mirrors.aliyun.com/pypi/simple/"
30
+ default = true
File without changes
@@ -0,0 +1,3 @@
1
+ from mh_local.main import run
2
+
3
+ run()
@@ -0,0 +1,216 @@
1
+ """Local FastAPI app for ``mh-local``.
2
+
3
+ The app is wired through a single
4
+ :class:`mh_gateway.app.AdapterLifespan` that returns the gateway's
5
+ :class:`GatewayAdapters` bundle. All persistence is local-file
6
+ based.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import logging
12
+ from collections.abc import AsyncIterator
13
+ from contextlib import asynccontextmanager
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ from fastapi import FastAPI
18
+ from fastapi.responses import FileResponse
19
+ from fastapi.staticfiles import StaticFiles
20
+ from minimal_harness.llm.factory import register_builtin_providers
21
+ from minimal_harness.llm.llm import ProviderFactory
22
+
23
+ from mh_gateway.adapters import (
24
+ AuthorizationProvider,
25
+ M2MAuthenticator,
26
+ MetadataRepository,
27
+ OutboundAuthProvider,
28
+ SessionRepository,
29
+ ToolScriptStore,
30
+ UserAuthenticator,
31
+ )
32
+ from mh_gateway.app import AdapterLifespan, GatewayAdapters, create_app
33
+ from mh_gateway.config import ConfigSchema
34
+ from mh_gateway.llm import DefaultLLMProviderService
35
+
36
+ from mh_local.auth import LocalAuthProvider
37
+ from mh_local.storage.provider_store import FileLLMConfigBackend
38
+ from mh_local.storage.registry_store import FileMetadataRepository
39
+ from mh_local.storage.session_store import JSONLSessionStore
40
+
41
+ logger = logging.getLogger("mh_local")
42
+
43
+
44
+ class _M2MAuth(M2MAuthenticator):
45
+ async def authenticate(self, request: Any) -> str | None:
46
+ return "local"
47
+
48
+ async def get_identity_headers(
49
+ self, request: Any, identity: str
50
+ ) -> dict[str, str]:
51
+ return {}
52
+
53
+ async def close(self) -> None:
54
+ return None
55
+
56
+
57
+ class _OutboundAuth(OutboundAuthProvider):
58
+ async def get_headers(
59
+ self, request: Any, target_url: str, target_type: str
60
+ ) -> dict[str, str]:
61
+ return {}
62
+
63
+ async def close(self) -> None:
64
+ return None
65
+
66
+
67
+ def _build_settings() -> ConfigSchema:
68
+ return ConfigSchema(
69
+ dev_mode=False,
70
+ log_level="INFO",
71
+ db_path="",
72
+ db_auto_schema=False,
73
+ enable_eval=False,
74
+ metrics_enabled=False,
75
+ cors_origins=[],
76
+ eval_results_dir="",
77
+ )
78
+
79
+
80
+ def build_adapter_lifespan(
81
+ *,
82
+ user_auth: UserAuthenticator | None = None,
83
+ authorization: AuthorizationProvider | None = None,
84
+ metadata: MetadataRepository | None = None,
85
+ sessions: SessionRepository | None = None,
86
+ llm_provider: Any = None,
87
+ m2m_auth: M2MAuthenticator | None = None,
88
+ outbound_auth: OutboundAuthProvider | None = None,
89
+ tool_script_store: ToolScriptStore | None = None,
90
+ ) -> AdapterLifespan:
91
+ """Construct the default :class:`AdapterLifespan` for ``mh-local``."""
92
+
93
+ settings = _build_settings()
94
+ factory = ProviderFactory()
95
+ register_builtin_providers(factory)
96
+ backend = FileLLMConfigBackend()
97
+ default_llm = llm_provider or DefaultLLMProviderService.from_components(
98
+ factory=factory, backend=backend
99
+ )
100
+ default_user_auth = user_auth or LocalAuthProvider()
101
+ default_authorization = authorization or default_user_auth
102
+
103
+ @asynccontextmanager
104
+ async def _lifespan(app: FastAPI) -> AsyncIterator[GatewayAdapters]:
105
+ metadata_repo = metadata or FileMetadataRepository()
106
+ await metadata_repo.sync_cwd_scene()
107
+ sessions_repo = sessions or JSONLSessionStore()
108
+
109
+ script_store_impl = tool_script_store
110
+ if script_store_impl is None:
111
+ from mh_local.storage.script_store import LocalScriptStore
112
+
113
+ script_store_impl = LocalScriptStore()
114
+
115
+ yield GatewayAdapters(
116
+ settings=settings,
117
+ user_auth=default_user_auth,
118
+ authorization=default_authorization,
119
+ m2m_auth=m2m_auth or _M2MAuth(),
120
+ outbound_auth=outbound_auth or _OutboundAuth(),
121
+ metadata=metadata_repo,
122
+ llm=default_llm,
123
+ sessions=sessions_repo,
124
+ eval_results=None,
125
+ tool_script_store=script_store_impl,
126
+ )
127
+ await metadata_repo.close()
128
+ await sessions_repo.close()
129
+ await default_llm.close()
130
+ await script_store_impl.close()
131
+
132
+ return _lifespan
133
+
134
+
135
+ def create_local_app() -> FastAPI:
136
+ app = create_app(
137
+ settings=_build_settings(),
138
+ adapters=build_adapter_lifespan(),
139
+ )
140
+ _mount_mh_local_static(app)
141
+ return app
142
+
143
+
144
+ def _mount_mh_local_static(app: FastAPI) -> None:
145
+ static_dir = Path(__file__).resolve().parent / "static"
146
+ if not static_dir.is_dir():
147
+ logger.warning("MH-Local static directory not found at %s", static_dir)
148
+ return
149
+
150
+ subdirs = [
151
+ ("/assets", static_dir / "assets"),
152
+ ("/component", static_dir / "component"),
153
+ ]
154
+ for url_path, fs_path in subdirs:
155
+ if fs_path.is_dir():
156
+ app.mount(
157
+ url_path,
158
+ StaticFiles(directory=str(fs_path)),
159
+ name=f"mh_local_{url_path.lstrip('/')}",
160
+ )
161
+
162
+ favicon = static_dir / "favicon.svg"
163
+ if favicon.is_file():
164
+
165
+ @app.get("/favicon.svg", include_in_schema=False)
166
+ async def _favicon():
167
+ return FileResponse(str(favicon))
168
+
169
+ @app.middleware("http")
170
+ async def _mh_local_spa_fallback(request: Any, call_next: Any) -> Any:
171
+ response = await call_next(request)
172
+ if (
173
+ response.status_code == 404
174
+ and request.method == "GET"
175
+ and request.url.path != "/api"
176
+ and not request.url.path.startswith("/api/")
177
+ and not request.url.path.startswith("/docs")
178
+ and not request.url.path.startswith("/openapi")
179
+ and not request.url.path.startswith("/redoc")
180
+ and not request.url.path.startswith("/assets")
181
+ and not request.url.path.startswith("/component")
182
+ ):
183
+ index_path = static_dir / "index.html"
184
+ if index_path.is_file():
185
+ return FileResponse(str(index_path))
186
+ return response
187
+
188
+ _mount_component_sources(app)
189
+
190
+
191
+ def _mount_component_sources(app: FastAPI) -> None:
192
+ static_dir = Path(__file__).resolve().parent / "static"
193
+ components = static_dir / "component"
194
+ if not components.is_dir():
195
+ return
196
+
197
+ from fastapi import APIRouter
198
+
199
+ router = APIRouter(prefix="/api/v1/component-sources", tags=["component-sources"])
200
+
201
+ sources = []
202
+ for f in components.iterdir():
203
+ if f.suffix == ".js":
204
+ sources.append(
205
+ {
206
+ "id": f.stem,
207
+ "label": f.stem.replace("mh-", "").replace("-", " ").title(),
208
+ "url": f"/component/{f.name}",
209
+ }
210
+ )
211
+
212
+ @router.get("")
213
+ async def get_component_sources():
214
+ return sources
215
+
216
+ app.include_router(router)
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from mh_gateway.adapters import (
6
+ AuthorizationProvider,
7
+ UserAuthenticator,
8
+ UserIdentity,
9
+ )
10
+
11
+
12
+ class LocalAuthProvider(UserAuthenticator, AuthorizationProvider):
13
+ """Single-user auth provider used by ``mh-local``.
14
+
15
+ Always resolves to the local admin identity. Production
16
+ deployments that need real authentication should swap this
17
+ for a custom :class:`UserAuthenticator` /
18
+ :class:`AuthorizationProvider` pair.
19
+ """
20
+
21
+ async def verify(self, request: Any) -> UserIdentity:
22
+ return UserIdentity(
23
+ user_id="local",
24
+ username="Local User",
25
+ roles=["admin"],
26
+ )
27
+
28
+ async def logout(self, request: Any, response: Any) -> None:
29
+ response.set_cookie(
30
+ key="x-user-id", value="", httponly=True, max_age=0, path="/"
31
+ )
32
+
33
+ async def get_permissions(self, user_id: str) -> list[str]:
34
+ return ["*", "*:*:*"]
35
+
36
+ async def check(self, user_id: str, permission: str) -> bool:
37
+ return True
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import logging
5
+ import os
6
+ import socket
7
+ import sys
8
+ import webbrowser
9
+ from logging.handlers import TimedRotatingFileHandler
10
+
11
+ import uvicorn
12
+
13
+ from mh_local.app import create_local_app
14
+ from mh_local.storage.paths import LOGS_DIR, PROVIDERS_FILE, ensure_dirs
15
+ from mh_local.storage.registry_store import compute_scene_id
16
+
17
+ logger = logging.getLogger("mh_local")
18
+
19
+
20
+ def _find_free_port() -> int:
21
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
22
+ s.bind(("127.0.0.1", 0))
23
+ return s.getsockname()[1]
24
+
25
+
26
+ def _has_providers() -> bool:
27
+ if not PROVIDERS_FILE.exists():
28
+ return False
29
+ data = json.loads(PROVIDERS_FILE.read_text("utf-8"))
30
+ return any(p.get("api_key", "").strip() for p in data)
31
+
32
+
33
+ def _open_url(port: int) -> str:
34
+ cwd = os.getcwd()
35
+ scene_id = compute_scene_id(cwd)
36
+ url = f"http://127.0.0.1:{port}/#/?scene={scene_id}"
37
+ webbrowser.open(url)
38
+ return url
39
+
40
+
41
+ def run() -> None:
42
+ ensure_dirs()
43
+
44
+ log_file = LOGS_DIR / "mh_local.log"
45
+ file_handler = TimedRotatingFileHandler(
46
+ str(log_file), when="midnight", interval=1, backupCount=7, encoding="utf-8"
47
+ )
48
+ file_handler.setFormatter(
49
+ logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
50
+ )
51
+
52
+ logging.basicConfig(
53
+ level=logging.INFO,
54
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
55
+ handlers=[logging.StreamHandler(sys.stderr), file_handler],
56
+ )
57
+ logging.getLogger("uvicorn.access").handlers.clear()
58
+ logging.getLogger("uvicorn.access").propagate = False
59
+
60
+ first_run = not _has_providers()
61
+ if first_run:
62
+ logger.info(
63
+ "No LLM provider configured. "
64
+ "A template has been created at %s. "
65
+ "Please configure your API key via the web UI (Manage -> Providers).",
66
+ PROVIDERS_FILE,
67
+ )
68
+
69
+ app = create_local_app()
70
+ port = _find_free_port()
71
+
72
+ url = _open_url(port)
73
+ logger.info("Starting mh-local on %s", url)
74
+
75
+ uvicorn.run(
76
+ app,
77
+ host="127.0.0.1",
78
+ port=port,
79
+ log_level="info",
80
+ access_log=False,
81
+ )
82
+
83
+
84
+ if __name__ == "__main__":
85
+ run()
@@ -0,0 +1 @@
1
+ import{n as $e,U as Me,Q as Oe,$ as se,z as Te,A as m,g as v,m as N,d as l,J as n,K as a,a1 as p,Z as g,a2 as Ne,F as A,G as X,S as D,e as ne,a3 as ie,X as Ae,l as y,f as I,T as ce,y as Fe,c as M,C as _,s as Pe,u as Je,t as Le,L as Be,h as We,o as De,_ as Ie}from"./index-DVOv8YZP.js";import{M as Ke}from"./ManagementNav-DXmOEWXa.js";const je={class:"mgmt-page"},Ee={class:"mgmt-page-content"},Qe={class:"mgmt-header"},qe={class:"mgmt-toolbar"},Ge=["placeholder"],Xe={key:0,class:"table-wrap"},Ze={class:"mgmt-table"},He={key:1,class:"mgmt-empty"},Re={key:2},Ye={class:"table-wrap"},el={class:"mgmt-table"},ll=["title"],tl=["title"],ol=["title"],al=["title"],sl=["title"],nl={class:"cell-actions"},il=["onClick"],cl=["onClick"],dl={class:"mgmt-pagination"},ul=["disabled"],ml={class:"mgmt-page-info"},rl=["disabled"],pl={class:"dialog dialog-wide"},_l={class:"form-group"},vl=["disabled","placeholder"],gl={class:"form-group"},yl=["placeholder"],hl={class:"form-group"},fl={class:"tc-label-row"},bl=["title"],kl={class:"form-group"},zl={class:"tc-label-row"},wl=["title"],Vl={class:"form-group"},Cl={class:"form-group"},xl={class:"form-group"},Ul={key:0,class:"locale-section",open:""},Sl={key:0,class:"checkbox-label"},$l=["onUpdate:modelValue"],Ml={class:"tc-label-row"},Ol=["onClick","title"],Tl=["onUpdate:modelValue","placeholder"],Nl=["onUpdate:modelValue","min","max","step","placeholder"],Al=["onUpdate:modelValue","placeholder"],Fl={key:0,class:"locale-field"},Pl={class:"locale-field-label"},Jl={class:"locale-input-row"},Ll={class:"locale-lang"},Bl=["title"],Wl={class:"locale-lang"},Dl=["title"],Il={class:"locale-section"},Kl={class:"form-group"},jl={class:"tc-label-row"},El=["title"],Ql=["placeholder"],ql={class:"locale-section"},Gl={class:"locale-field"},Xl={class:"locale-field-label"},Zl={class:"locale-input-row"},Hl={class:"locale-lang"},Rl={class:"locale-lang"},Yl=["placeholder"],et={class:"locale-field"},lt={class:"locale-field-label"},tt={class:"locale-input-row"},ot={class:"locale-lang"},at=["title"],st={class:"locale-lang"},nt=["title"],it=["placeholder"],ct={class:"locale-field"},dt={class:"locale-field-label"},ut={class:"locale-input-row"},mt={class:"locale-lang"},rt=["title"],pt={class:"locale-lang"},_t=["title"],vt=["placeholder"],gt={class:"dialog-actions"},yt=["disabled"],ht={class:"tc-overlay-content"},ft={class:"tc-overlay-header"},bt={class:"tc-overlay-title"},kt={class:"tc-overlay-body"},zt=$e({__name:"AgentManagementPage",setup(wt){const{t:s,localeVal:C}=Me(),O=Oe(),F=_([]),de=M(()=>F.value.map(o=>({value:o.name,label:o.name}))),ue=M(()=>F.value.find(o=>o.name===i.value.provider)),Z=M(()=>{const o=ue.value;return!o||!o.models||o.models.length===0?[]:o.models.map(e=>({value:e.code||e.id,label:e.display_name||e.code||e.id}))}),K=_([]),j=_(!1),U=_(!1),T=_(!1),i=_({name:"",display_name:"",display_name_locale:"",description:"",description_locale:"",system_prompt:"",system_prompt_locale:"",provider:"openai",model:"",llm_config:{},agent_type:"simple"});se(()=>i.value.provider,()=>{const o=Z.value;o.length>0&&!o.some(e=>e.value===i.value.model)&&(i.value.model=o[0].value)});const c=_({display_zh:"",display_en:"",desc_zh:"",desc_en:"",prompt_zh:"",prompt_en:""});function E(o){if(!o)return{zh:"",en:""};try{const e=JSON.parse(o);return{zh:e.zh??"",en:e.en??""}}catch{return{zh:"",en:""}}}function Q(o,e){return!o&&!e?"":JSON.stringify({zh:o,en:e})}function me(){const o=E(i.value.display_name_locale);c.value.display_zh=o.zh,c.value.display_en=o.en;const e=E(i.value.description_locale);c.value.desc_zh=e.zh,c.value.desc_en=e.en;const d=E(i.value.system_prompt_locale);c.value.prompt_zh=d.zh,c.value.prompt_en=d.en}function re(){i.value.display_name_locale=Q(c.value.display_zh,c.value.display_en),i.value.description_locale=Q(c.value.desc_zh,c.value.desc_en),i.value.system_prompt_locale=Q(c.value.prompt_zh,c.value.prompt_en)}const P=_(""),w=_(1),J=_(15),H=_(0),pe=[{value:10,label:"10"},{value:15,label:"15"},{value:20,label:"20"},{value:50,label:"50"}],R=M(()=>Math.max(1,Math.ceil(H.value/J.value))),L=_(!1),x=_(""),S=_({});function _e(o){return C(JSON.stringify({zh:o.display_name_zh,en:o.display_name}),o.display_name)}function ve(o){return o.settings_title||o.settings_title_zh?C(JSON.stringify({zh:o.settings_title_zh,en:o.settings_title}),o.settings_title||""):""}function B(o){return C(JSON.stringify({zh:o.display_name_zh,en:o.display_name}),o.display_name)}function q(o){return!o.placeholder&&!o.placeholder_zh?"":C(JSON.stringify({zh:o.placeholder_zh,en:o.placeholder}),o.placeholder||"")}async function ge(){try{const o=await Pe(),e={};for(const d of o)e[d.value]=d;S.value=e}catch{S.value={}}}const u=_({}),h=_({zh:"",en:""});function ye(o){if(!o)return{zh:"",en:""};try{const e=JSON.parse(o);return{zh:e.zh??"",en:e.en??""}}catch{return{zh:"",en:""}}}function he(o,e){return!o&&!e?"":JSON.stringify({zh:o,en:e})}function fe(){const o=u.value.compaction_prompt_locale,e=ye(o);h.value.zh=e.zh,h.value.en=e.en}function be(){const o=he(h.value.zh,h.value.en);o?u.value.compaction_prompt_locale=o:delete u.value.compaction_prompt_locale}const V=M(()=>S.value[i.value.agent_type??"simple"]??S.value.simple??null),ke=M(()=>Object.values(S.value).map(o=>({value:o.value,label:_e(o)})));function Y(){const o=V.value;if(o&&o.settings_key&&o.settings_fields){const e=i.value[o.settings_key]??{},d={};for(const b of o.settings_fields)d[b.key]=e[b.key]??void 0;e.compaction_prompt_locale!==void 0&&(d.compaction_prompt_locale=e.compaction_prompt_locale),u.value=d,fe()}else u.value={}}function ze(){be();for(const e of Object.values(S.value))e.settings_key&&delete i.value[e.settings_key];const o=V.value;if(o&&o.settings_key&&o.settings_fields){const e={};for(const d of o.settings_fields){const b=u.value[d.key];b!=null&&b!==""&&(e[d.key]=d.type==="number"?Number(b):b)}u.value.compaction_prompt_locale&&(e.compaction_prompt_locale=u.value.compaction_prompt_locale),Object.keys(e).length>0&&(i.value[o.settings_key]=e)}}se(()=>i.value.agent_type,()=>{u.value={},h.value={zh:"",en:""},Y()});const G=_(!1),ee=_(""),f=_("");let r=null;function k(o,e,d){ee.value=o,f.value=e,r=d,G.value=!0}function le(){if(r==="description")i.value.description=f.value;else if(r==="system_prompt")i.value.system_prompt=f.value;else if(r==="llm_config")x.value=f.value;else if(r==="locale_desc_zh")c.value.desc_zh=f.value;else if(r==="locale_desc_en")c.value.desc_en=f.value;else if(r==="locale_prompt_zh")c.value.prompt_zh=f.value;else if(r==="locale_prompt_en")c.value.prompt_en=f.value;else if(r==="compaction_prompt_locale_zh")h.value.zh=f.value;else if(r==="compaction_prompt_locale_en")h.value.en=f.value;else if(r&&r.startsWith("settings:")){const o=r.slice(9);u.value[o]=f.value}G.value=!1,r=null}async function we(){try{const o=await Je({page_size:100});F.value=o.items}catch{F.value=[{name:"openai",provider_type:"openai"},{name:"anthropic",provider_type:"anthropic"}]}}async function $(){j.value=!0;try{const o=await Le({q:P.value,page:w.value,page_size:J.value});K.value=o.items,H.value=o.total}catch(o){O.show("Failed to load agents: "+o.message)}finally{j.value=!1}}function te(){w.value=1,$()}function oe(o){w.value=o,$()}function Ve(){w.value=1,$()}function Ce(){T.value=!1,i.value={name:"",display_name:"",display_name_locale:"",description:"",description_locale:"",system_prompt:"",system_prompt_locale:"",provider:"openai",model:"",llm_config:{},agent_type:"simple"},c.value={display_zh:"",display_en:"",desc_zh:"",desc_en:"",prompt_zh:"",prompt_en:""},x.value="",u.value={},h.value={zh:"",en:""},U.value=!0}function xe(o){T.value=!0,i.value={...o},x.value=o.llm_config?JSON.stringify(o.llm_config,null,2):"",me(),Y(),U.value=!0}async function Ue(){if(re(),ze(),x.value.trim())try{i.value.llm_config=JSON.parse(x.value)}catch{O.show("Invalid JSON in model config");return}else i.value.llm_config={};L.value=!0;try{T.value&&i.value.name?await Be(i.value.name,i.value):await We(i.value),U.value=!1,await $()}catch(o){O.show("Failed to save: "+o.message)}finally{L.value=!1}}function W(o,e){if(!o)return"-";const d=o.replace("T"," ").substring(0,16);return e?`${d} by ${e}`:d}async function Se(o){if(await O.confirm(s("alert_confirm_delete_agent",{name:o})))try{await De(o),await $()}catch(e){O.show("Failed to delete: "+e.message)}}return Te(()=>{ge(),we(),$()}),(o,e)=>{var d,b,ae;return m(),v("div",je,[N(Ke),l("div",Ee,[l("header",Qe,[l("h1",null,n(a(s)("mgmt_agents")),1),l("button",{class:"btn-primary",onClick:Ce},n(a(s)("mgmt_new_agent")),1)]),l("div",null,[l("div",qe,[p(l("input",{"onUpdate:modelValue":e[0]||(e[0]=t=>P.value=t),class:"mgmt-search",placeholder:a(s)("mgmt_search_placeholder"),onKeyup:Ne(te,["enter"])},null,40,Ge),[[g,P.value]]),l("button",{class:"btn-search",onClick:te},n(a(s)("mgmt_search")),1)]),j.value?(m(),v("div",Xe,[l("table",Ze,[l("thead",null,[l("tr",null,[l("th",null,n(a(s)("mgmt_name")),1),l("th",null,n(a(s)("mgmt_display_name")),1),l("th",null,n(a(s)("mgmt_description")),1),l("th",null,n(a(s)("mgmt_created_at")),1),l("th",null,n(a(s)("mgmt_updated_at")),1),l("th",null,n(a(s)("mgmt_actions")),1)])]),l("tbody",null,[(m(),v(A,null,X(5,t=>l("tr",{key:t,class:"mgmt-skeleton-row"},[...e[32]||(e[32]=[l("td",null,[l("div",{class:"mgmt-skeleton-cell",style:{width:"60%"}})],-1),l("td",null,[l("div",{class:"mgmt-skeleton-cell",style:{width:"50%"}})],-1),l("td",null,[l("div",{class:"mgmt-skeleton-cell",style:{width:"70%"}})],-1),l("td",null,[l("div",{class:"mgmt-skeleton-cell",style:{width:"50%"}})],-1),l("td",null,[l("div",{class:"mgmt-skeleton-cell mgmt-skeleton-cell-sm",style:{width:"65%"}})],-1),l("td",null,[l("div",{class:"mgmt-skeleton-cell mgmt-skeleton-cell-sm",style:{width:"65%"}})],-1),l("td",null,[l("div",{class:"mgmt-skeleton-cell",style:{width:"50%"}})],-1)])])),64))])])])):K.value.length===0?(m(),v("div",He,n(P.value?a(s)("mgmt_no_results"):a(s)("mgmt_no_agents")),1)):(m(),v("div",Re,[l("div",Ye,[l("table",el,[l("thead",null,[l("tr",null,[l("th",null,n(a(s)("mgmt_name")),1),l("th",null,n(a(s)("mgmt_display_name")),1),l("th",null,n(a(s)("mgmt_description")),1),l("th",null,n(a(s)("mgmt_created_at")),1),l("th",null,n(a(s)("mgmt_updated_at")),1),l("th",null,n(a(s)("mgmt_actions")),1)])]),l("tbody",null,[(m(!0),v(A,null,X(K.value,t=>(m(),v("tr",{key:t.name},[l("td",{title:t.name},[l("code",null,n(t.name),1)],8,ll),l("td",{title:a(C)(t.display_name_locale,t.display_name)},n(a(C)(t.display_name_locale,t.display_name)),9,tl),l("td",{class:"cell-desc",title:a(C)(t.description_locale,t.description)},n(a(C)(t.description_locale,t.description)),9,ol),l("td",{class:"cell-audit",title:W(t.created_at,t.created_by)},n(W(t.created_at,t.created_by)),9,al),l("td",{class:"cell-audit",title:W(t.updated_at,t.updated_by)},n(W(t.updated_at,t.updated_by)),9,sl),l("td",nl,[l("button",{class:"btn-action",onClick:z=>xe(t)},n(a(s)("mgmt_edit")),9,il),l("button",{class:"btn-action btn-danger",onClick:z=>Se(t.name)},n(a(s)("mgmt_delete")),9,cl)])]))),128))])])]),l("div",dl,[l("button",{class:"btn-page",disabled:w.value<=1,onClick:e[1]||(e[1]=t=>oe(w.value-1))},n(a(s)("mgmt_prev_page")),9,ul),l("span",ml,n(w.value)+" / "+n(R.value),1),l("button",{class:"btn-page",disabled:w.value>=R.value,onClick:e[2]||(e[2]=t=>oe(w.value+1))},n(a(s)("mgmt_next_page")),9,rl),N(D,{modelValue:J.value,"onUpdate:modelValue":e[3]||(e[3]=t=>J.value=t),modelModifiers:{number:!0},options:pe,searchable:!1,onChange:Ve},null,8,["modelValue"])])])),(m(),ne(ce,{to:"body"},[U.value?(m(),v("div",{key:0,class:"dialog-overlay",onMousedown:e[30]||(e[30]=ie(t=>U.value=!1,["self"]))},[l("div",pl,[l("h2",null,n(T.value?a(s)("mgmt_edit_agent"):a(s)("mgmt_new_agent_title")),1),l("div",_l,[l("label",null,n(a(s)("mgmt_name")),1),p(l("input",{"onUpdate:modelValue":e[4]||(e[4]=t=>i.value.name=t),disabled:T.value,placeholder:a(s)("mgmt_placeholder_id")},null,8,vl),[[g,i.value.name]])]),l("div",gl,[l("label",null,n(a(s)("mgmt_display_name")),1),p(l("input",{"onUpdate:modelValue":e[5]||(e[5]=t=>i.value.display_name=t),placeholder:a(s)("mgmt_placeholder_display_name")},null,8,yl),[[g,i.value.display_name]])]),l("div",hl,[l("div",fl,[l("label",null,n(a(s)("mgmt_description")),1),l("button",{class:"tc-fullscreen-btn",onClick:e[6]||(e[6]=t=>k(a(s)("mgmt_description"),i.value.description??"","description")),title:a(s)("mgmt_tc_source_code")},"⛶",8,bl)]),p(l("textarea",{"onUpdate:modelValue":e[7]||(e[7]=t=>i.value.description=t),rows:"2"},null,512),[[g,i.value.description]])]),l("div",kl,[l("div",zl,[l("label",null,n(a(s)("mgmt_system_prompt")),1),l("button",{class:"tc-fullscreen-btn",onClick:e[8]||(e[8]=t=>k(a(s)("mgmt_system_prompt"),i.value.system_prompt??"","system_prompt")),title:a(s)("mgmt_tc_source_code")},"⛶",8,wl)]),p(l("textarea",{"onUpdate:modelValue":e[9]||(e[9]=t=>i.value.system_prompt=t),rows:"6",class:"mono"},null,512),[[g,i.value.system_prompt]])]),l("div",Vl,[l("label",null,n(a(s)("mgmt_provider")),1),N(D,{modelValue:i.value.provider,"onUpdate:modelValue":e[10]||(e[10]=t=>i.value.provider=t),options:de.value,searchable:!1},null,8,["modelValue","options"])]),l("div",Cl,[l("label",null,n(a(s)("mgmt_model")),1),N(D,{modelValue:i.value.model,"onUpdate:modelValue":e[11]||(e[11]=t=>i.value.model=t),options:Z.value,searchable:!0,placeholder:a(s)("mgmt_model_placeholder")},null,8,["modelValue","options","placeholder"])]),l("div",xl,[l("label",null,n(a(s)("mgmt_agent_type")),1),N(D,{modelValue:i.value.agent_type,"onUpdate:modelValue":e[12]||(e[12]=t=>i.value.agent_type=t),options:ke.value,searchable:!1},null,8,["modelValue","options"])]),V.value&&V.value.settings_fields&&V.value.settings_fields.length>0?(m(),v("details",Ul,[l("summary",null,n(ve(V.value)),1),(m(!0),v(A,null,X(V.value.settings_fields,t=>(m(),v("div",{class:"form-group",key:t.key},[t.type==="boolean"?(m(),v("label",Sl,[p(l("input",{"onUpdate:modelValue":z=>u.value[t.key]=z,type:"checkbox"},null,8,$l),[[Ae,u.value[t.key]]]),y(" "+n(B(t)),1)])):t.type==="longtext"?(m(),v(A,{key:1},[l("div",Ml,[l("label",null,n(B(t)),1),l("button",{class:"tc-fullscreen-btn",onClick:z=>k(B(t),u.value[t.key]??"","settings:"+t.key),title:a(s)("mgmt_tc_source_code")},"⛶",8,Ol)]),p(l("textarea",{"onUpdate:modelValue":z=>u.value[t.key]=z,rows:"6",class:"mono",placeholder:q(t)},null,8,Tl),[[g,u.value[t.key]]])],64)):(m(),v(A,{key:2},[l("label",null,n(B(t)),1),t.type==="number"?p((m(),v("input",{key:0,"onUpdate:modelValue":z=>u.value[t.key]=z,type:"number",min:t.min,max:t.max,step:t.step??1,placeholder:q(t)},null,8,Nl)),[[g,u.value[t.key],void 0,{number:!0}]]):p((m(),v("input",{key:1,"onUpdate:modelValue":z=>u.value[t.key]=z,placeholder:q(t)},null,8,Al)),[[g,u.value[t.key]]])],64))]))),128)),V.value.settings_key==="compaction"||V.value.settings_key==="tool_compaction"?(m(),v("div",Fl,[l("div",Pl,n(a(s)("mgmt_compaction_prompt_locale")),1),l("div",Jl,[l("label",Ll,[e[33]||(e[33]=y("zh ",-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[13]||(e[13]=t=>k("zh "+a(s)("mgmt_compaction_prompt_locale"),h.value.zh,"compaction_prompt_locale_zh")),title:a(s)("mgmt_tc_source_code")},"⛶",8,Bl),e[34]||(e[34]=y()),p(l("textarea",{"onUpdate:modelValue":e[14]||(e[14]=t=>h.value.zh=t),rows:"3",placeholder:"中文压缩提示词"},null,512),[[g,h.value.zh]])]),l("label",Wl,[e[35]||(e[35]=y("en ",-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[15]||(e[15]=t=>k("en "+a(s)("mgmt_compaction_prompt_locale"),h.value.en,"compaction_prompt_locale_en")),title:a(s)("mgmt_tc_source_code")},"⛶",8,Dl),e[36]||(e[36]=y()),p(l("textarea",{"onUpdate:modelValue":e[16]||(e[16]=t=>h.value.en=t),rows:"3",placeholder:"Compaction prompt"},null,512),[[g,h.value.en]])])])])):I("",!0)])):I("",!0),l("details",Il,[l("summary",null,n(a(s)("mgmt_llm_config")),1),l("div",Kl,[l("div",jl,[e[37]||(e[37]=l("span",null,null,-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[17]||(e[17]=t=>k(a(s)("mgmt_llm_config"),x.value,"llm_config")),title:a(s)("mgmt_tc_source_code")},"⛶",8,El)]),p(l("textarea",{"onUpdate:modelValue":e[18]||(e[18]=t=>x.value=t),rows:"4",class:"mono",placeholder:a(s)("mgmt_llm_config_placeholder")},null,8,Ql),[[g,x.value]])])]),l("details",ql,[l("summary",null,n(a(s)("mgmt_translations")),1),l("div",Gl,[l("div",Xl,n(a(s)("mgmt_locale_display")),1),l("div",Zl,[l("label",Hl,[e[38]||(e[38]=y("zh ",-1)),p(l("input",{"onUpdate:modelValue":e[19]||(e[19]=t=>c.value.display_zh=t),placeholder:"中文名称"},null,512),[[g,c.value.display_zh]])]),l("label",Rl,[e[39]||(e[39]=y("en ",-1)),p(l("input",{"onUpdate:modelValue":e[20]||(e[20]=t=>c.value.display_en=t),placeholder:a(s)("mgmt_placeholder_display_name")},null,8,Yl),[[g,c.value.display_en]])])])]),l("div",et,[l("div",lt,n(a(s)("mgmt_locale_desc")),1),l("div",tt,[l("label",ot,[e[40]||(e[40]=y("zh ",-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[21]||(e[21]=t=>k("zh "+a(s)("mgmt_locale_desc"),c.value.desc_zh,"locale_desc_zh")),title:a(s)("mgmt_tc_source_code")},"⛶",8,at),e[41]||(e[41]=y()),p(l("textarea",{"onUpdate:modelValue":e[22]||(e[22]=t=>c.value.desc_zh=t),rows:"2",placeholder:"中文描述"},null,512),[[g,c.value.desc_zh]])]),l("label",st,[e[42]||(e[42]=y("en ",-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[23]||(e[23]=t=>k("en "+a(s)("mgmt_locale_desc"),c.value.desc_en,"locale_desc_en")),title:a(s)("mgmt_tc_source_code")},"⛶",8,nt),e[43]||(e[43]=y()),p(l("textarea",{"onUpdate:modelValue":e[24]||(e[24]=t=>c.value.desc_en=t),rows:"2",placeholder:a(s)("mgmt_placeholder_desc")},null,8,it),[[g,c.value.desc_en]])])])]),l("div",ct,[l("div",dt,n(a(s)("mgmt_locale_prompt")),1),l("div",ut,[l("label",mt,[e[44]||(e[44]=y("zh ",-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[25]||(e[25]=t=>k("zh "+a(s)("mgmt_locale_prompt"),c.value.prompt_zh,"locale_prompt_zh")),title:a(s)("mgmt_tc_source_code")},"⛶",8,rt),e[45]||(e[45]=y()),p(l("textarea",{"onUpdate:modelValue":e[26]||(e[26]=t=>c.value.prompt_zh=t),rows:"3",placeholder:"中文系统提示"},null,512),[[g,c.value.prompt_zh]])]),l("label",pt,[e[46]||(e[46]=y("en ",-1)),l("button",{class:"tc-fullscreen-btn",onClick:e[27]||(e[27]=t=>k("en "+a(s)("mgmt_locale_prompt"),c.value.prompt_en,"locale_prompt_en")),title:a(s)("mgmt_tc_source_code")},"⛶",8,_t),e[47]||(e[47]=y()),p(l("textarea",{"onUpdate:modelValue":e[28]||(e[28]=t=>c.value.prompt_en=t),rows:"3",placeholder:a(s)("mgmt_placeholder_prompt")},null,8,vt),[[g,c.value.prompt_en]])])])])]),l("div",gt,[l("button",{class:"btn-cancel",onClick:e[29]||(e[29]=t=>U.value=!1)},n(a(s)("mgmt_cancel")),1),l("button",{class:"btn-primary",disabled:L.value||!i.value.name,onClick:Ue},n(L.value?a(s)("mgmt_saving"):a(s)("mgmt_save")),9,yt)])])],32)):I("",!0)])),(m(),ne(ce,{to:"body"},[G.value?(m(),v("div",{key:0,class:"tc-overlay",onMousedown:ie(le,["self"])},[l("div",ht,[l("div",ft,[l("span",bt,n(ee.value),1),l("div",{class:"tc-overlay-header-actions"},[l("button",{class:"tc-fullscreen-close",onClick:le},"✕")])]),l("div",kt,[p(l("textarea",{"onUpdate:modelValue":e[31]||(e[31]=t=>f.value=t),class:Fe(a(r)==="system_prompt"||a(r)==="llm_config"||(d=a(r))!=null&&d.startsWith("locale_prompt")||(b=a(r))!=null&&b.startsWith("compaction_prompt_locale")||(ae=a(r))!=null&&ae.startsWith("settings:")?"tc-overlay-textarea":"tc-overlay-textarea tc-overlay-textarea-text"),spellcheck:"false"},null,2),[[g,f.value]])])])],32)):I("",!0)]))])])])}}}),xt=Ie(zt,[["__scopeId","data-v-6bafe8a7"]]);export{xt as default};
@@ -0,0 +1 @@
1
+ .ta-messages[data-v-6bafe8a7]{flex:1;overflow-y:auto;margin-bottom:12px;display:flex;flex-direction:column;gap:10px;min-height:200px;max-height:400px}.ta-empty[data-v-6bafe8a7]{color:var(--text-muted);font-size:13px;text-align:center;padding:48px 16px}.ta-msg[data-v-6bafe8a7]{padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.5}.ta-msg-user[data-v-6bafe8a7]{background:var(--accent-dim);align-self:flex-end;max-width:85%}.ta-msg-assistant[data-v-6bafe8a7]{background:var(--glass-highlight);border:1px solid var(--glass-border);align-self:flex-start;max-width:85%}.ta-msg-label[data-v-6bafe8a7]{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;color:var(--text-secondary);margin-bottom:4px}.ta-msg-content[data-v-6bafe8a7]{white-space:pre-wrap;word-break:break-word}.ta-msg-thinking[data-v-6bafe8a7]{color:var(--text-muted);font-style:italic}.ta-input-row[data-v-6bafe8a7]{display:flex;gap:8px}.ta-input[data-v-6bafe8a7]{flex:1;padding:9px 12px;background:var(--glass-highlight);border:1px solid var(--glass-border);border-radius:8px;color:var(--text-primary);font-size:13px;box-sizing:border-box;transition:border-color .15s}.ta-input[data-v-6bafe8a7]:focus{outline:none;border-color:var(--accent)}.ta-input[data-v-6bafe8a7]:disabled{opacity:.5}.btn-send[data-v-6bafe8a7]{padding:9px 18px;background:var(--accent);border:none;border-radius:8px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;transition:opacity .15s;white-space:nowrap}.btn-send[data-v-6bafe8a7]:hover:not(:disabled){opacity:.9}.btn-send[data-v-6bafe8a7]:disabled{opacity:.5;cursor:not-allowed}.checkbox-label[data-v-6bafe8a7]{display:inline-flex!important;align-items:center!important;gap:8px!important;cursor:pointer!important;margin-bottom:0!important}.checkbox-label input[type=checkbox][data-v-6bafe8a7]{width:auto!important;flex-shrink:0!important}
@@ -0,0 +1 @@
1
+ .mgmt-nav[data-v-aa311c53]{position:sticky;top:0;z-index:200;background:var(--glass-bg);border-bottom:1px solid var(--glass-border);flex-shrink:0}.mgmt-nav-inner[data-v-aa311c53]{max-width:1160px;margin:0 auto;display:flex;align-items:center;gap:14px;padding:10px 16px;height:56px}.nav-back[data-v-aa311c53]{display:flex;align-items:center;justify-content:center;width:36px;height:36px;background:var(--glass-highlight);border:1px solid var(--glass-border);border-radius:10px;color:var(--text-secondary);cursor:pointer;flex-shrink:0;transition:all var(--transition-duration)}.nav-back[data-v-aa311c53]:hover{background:var(--accent-dim);border-color:var(--accent);color:var(--accent);transform:scale(1.05)}.nav-back[data-v-aa311c53]:active{transform:scale(.95)}.nav-tabs[data-v-aa311c53]{display:flex;gap:2px;flex:1;background:var(--glass-highlight);border-radius:12px;padding:4px;border:1px solid var(--glass-border)}.nav-tab[data-v-aa311c53]{display:flex;align-items:center;gap:7px;padding:7px 16px;border-radius:10px;font-size:13px;font-weight:600;color:var(--text-secondary);text-decoration:none;transition:all .25s cubic-bezier(.4,0,.2,1);position:relative}.nav-tab[data-v-aa311c53]:hover{background:var(--surface-bg);color:var(--text-primary)}.nav-tab.active[data-v-aa311c53]{background:var(--accent);color:#fff;box-shadow:0 2px 12px #0003}.nav-tab svg[data-v-aa311c53]{flex-shrink:0}.nav-controls[data-v-aa311c53]{display:flex;align-items:center;gap:8px}.nav-select[data-v-aa311c53]{padding:6px 10px;border:1px solid var(--glass-border);border-radius:8px;background:var(--glass-highlight);color:var(--text-primary);font-size:12px;cursor:pointer;font-family:inherit;font-weight:500;transition:border-color var(--transition-duration),box-shadow var(--transition-duration)}.nav-select[data-v-aa311c53]:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-dim)}.nav-lang-btn[data-v-aa311c53]{background:var(--glass-highlight);border:1px solid var(--glass-border);color:var(--text-primary);padding:6px 12px;border-radius:8px;cursor:pointer;font-size:12px;font-weight:600;font-family:inherit;min-width:36px;text-align:center;transition:all var(--transition-duration)}.nav-lang-btn[data-v-aa311c53]:hover{background:var(--accent-dim);border-color:var(--accent);color:var(--accent);transform:scale(1.05)}.nav-lang-btn[data-v-aa311c53]:active{transform:scale(.95)}@media(max-width:768px){.mgmt-nav-inner[data-v-aa311c53]{padding:0 12px;gap:8px}.nav-tab[data-v-aa311c53]{padding:7px 10px;font-size:12px;gap:4px}.nav-tab svg[data-v-aa311c53]{width:13px;height:13px}}@media(max-width:480px){.nav-tab span[data-v-aa311c53]{display:none}.nav-tab[data-v-aa311c53]{padding:7px 12px;gap:0}.nav-tab svg[data-v-aa311c53]{width:16px;height:16px;margin:0 auto}.nav-tabs[data-v-aa311c53]{justify-content:center}}
@@ -0,0 +1 @@
1
+ import{n as I,V as H,W as K,R as P,I as y,U as R,C as T,$ as E,z as U,H as W,A as i,g as L,d as e,m as b,B as $,K as n,e as h,a0 as d,J as c,y as m,f as g,S as D,c as v,_ as J}from"./index-DVOv8YZP.js";const O={class:"mgmt-nav"},q={class:"mgmt-nav-inner"},F=["title"],G={class:"nav-tabs"},Q={class:"nav-controls"},X=I({__name:"ManagementNav",setup(Y){const C=H(),B=K(),p=P(),{user:S}=y(p),w=R(),{t:o,setLocale:M}=w,{locale:x}=y(w);function k(s){var a;const t=(a=S.value)==null?void 0:a.permissions;return t?t.some(l=>l==="*"||l.startsWith(s)):!1}const A=v(()=>k("manage:scene:")),f=v(()=>k("manage:agent:")),V=v(()=>k("manage:tool:")),z=[{value:"light",labelKey:"theme_light"},{value:"dark",labelKey:"theme_dark"}],N=v(()=>z.map(s=>({value:s.value,label:o(s.labelKey)}))),r=T(localStorage.getItem("theme")||"light");function _(s){r.value=s,document.documentElement.setAttribute("data-theme",s),localStorage.setItem("theme",s)}E(r,_),U(async()=>{await p.checkAuth(),_(r.value)});function u(s){return C.path.startsWith(s)}function j(){M(x.value==="zh"?"en":"zh")}return(s,t)=>{const a=W("router-link");return i(),L("nav",O,[e("div",q,[b($),e("button",{class:"nav-back",onClick:t[0]||(t[0]=l=>n(B).back()),title:n(o)("mgmt_back")},[...t[2]||(t[2]=[e("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.2","stroke-linecap":"round","stroke-linejoin":"round"},[e("path",{d:"M19 12H5M12 19l-7-7 7-7"})],-1)])],8,F),e("div",G,[A.value?(i(),h(a,{key:0,to:"/manage/scenes",class:m(["nav-tab",{active:u("/manage/scenes")}])},{default:d(()=>[t[3]||(t[3]=e("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e("rect",{x:"3",y:"3",width:"7",height:"7",rx:"1"}),e("rect",{x:"14",y:"3",width:"7",height:"7",rx:"1"}),e("rect",{x:"3",y:"14",width:"7",height:"7",rx:"1"}),e("rect",{x:"14",y:"14",width:"7",height:"7",rx:"1"})],-1)),e("span",null,c(n(o)("mgmt_scenes")),1)]),_:1},8,["class"])):g("",!0),f.value?(i(),h(a,{key:1,to:"/manage/agents",class:m(["nav-tab",{active:u("/manage/agents")}])},{default:d(()=>[t[4]||(t[4]=e("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e("path",{d:"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"}),e("circle",{cx:"12",cy:"7",r:"4"})],-1)),e("span",null,c(n(o)("mgmt_agents")),1)]),_:1},8,["class"])):g("",!0),V.value?(i(),h(a,{key:2,to:"/manage/tools",class:m(["nav-tab",{active:u("/manage/tools")}])},{default:d(()=>[t[5]||(t[5]=e("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e("path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"})],-1)),e("span",null,c(n(o)("mgmt_tools")),1)]),_:1},8,["class"])):g("",!0),f.value?(i(),h(a,{key:3,to:"/manage/providers",class:m(["nav-tab",{active:u("/manage/providers")}])},{default:d(()=>[t[6]||(t[6]=e("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e("rect",{x:"3",y:"3",width:"7",height:"7",rx:"1"}),e("rect",{x:"14",y:"3",width:"7",height:"7",rx:"1"}),e("rect",{x:"3",y:"14",width:"7",height:"7",rx:"1"}),e("rect",{x:"14",y:"14",width:"7",height:"7",rx:"1"})],-1)),e("span",null,c(n(o)("mgmt_providers")),1)]),_:1},8,["class"])):g("",!0)]),e("div",Q,[b(D,{modelValue:r.value,"onUpdate:modelValue":t[1]||(t[1]=l=>r.value=l),options:N.value,searchable:!1},null,8,["modelValue","options"]),e("button",{class:"nav-lang-btn",onClick:j},c(n(x)==="zh"?"EN":"中"),1)])])])}}}),ee=J(X,[["__scopeId","data-v-aa311c53"]]);export{ee as M};
@@ -0,0 +1 @@
1
+ import{n as W,U as X,Q as ee,z as le,A as i,g as m,m as D,d as e,J as o,K as a,a1 as c,Z as _,a2 as te,F as V,G as S,S as ae,e as N,a3 as E,Y as oe,f as $,T as I,C as r,c as se,u as ne,M as de,i as ie,p as ue,_ as me}from"./index-DVOv8YZP.js";import{M as re}from"./ManagementNav-DXmOEWXa.js";const ce={class:"mgmt-page"},_e={class:"mgmt-page-content"},ve={class:"mgmt-header"},ge={class:"mgmt-toolbar"},pe=["placeholder"],he={key:0,class:"table-wrap"},be={class:"mgmt-table"},fe={key:1,class:"mgmt-empty"},ye={key:2},ke={class:"table-wrap"},we={class:"mgmt-table"},Ce=["title"],xe=["title"],Me=["title"],Ve={class:"cell-actions"},Se=["onClick"],Ue=["onClick"],Pe={class:"mgmt-pagination"},$e=["disabled"],ze={class:"mgmt-page-info"},Fe=["disabled"],Te={class:"dialog dialog-wide"},Ae={class:"form-group"},Be=["placeholder","disabled"],De={class:"form-group"},Ne=["value"],Ee={class:"form-group"},Ie=["placeholder"],Ke={class:"form-group"},Le=["placeholder"],Qe={class:"form-group"},qe=["placeholder"],Ge={class:"form-group"},Je={class:"locale-section",open:""},Oe={key:0,class:"mgmt-empty",style:{padding:"8px 0","font-size":"13px"}},Ye={key:1,class:"model-list"},Ze={class:"model-item-info"},je={class:"model-item-code"},He={key:0,class:"model-item-ctx"},Re={class:"model-item-actions"},We=["onClick"],Xe=["onClick"],el={class:"dialog-actions"},ll=["disabled"],tl={class:"dialog"},al={class:"form-group"},ol=["placeholder","disabled"],sl={class:"form-group"},nl=["placeholder"],dl={class:"form-group"},il=["placeholder"],ul={class:"form-group"},ml=["placeholder"],rl={class:"dialog-actions"},cl=["disabled"],_l=W({__name:"ProviderManagementPage",setup(vl){const{t}=X(),f=ee(),K=["openai","anthropic"],U=r([]),P=r(!1),w=r(!1),g=r(!1),y=r(!1),n=r({name:"",provider_type:"openai",api_key:"",base_url:"",default_model:"",description:"",models:[]}),p=r(!1),k=r(!1),u=r({id:"",code:"",display_name:"",max_context:0}),C=r(-1),x=r(""),v=r(1),M=r(15),z=r(0),L=[{value:10,label:"10"},{value:15,label:"15"},{value:20,label:"20"},{value:50,label:"50"}],F=se(()=>Math.max(1,Math.ceil(z.value/M.value)));async function h(){P.value=!0;try{const d=await ne({q:x.value,page:v.value,page_size:M.value});U.value=d.items,z.value=d.total}catch(d){f.show("Failed to load providers: "+d.message)}finally{P.value=!1}}function T(){v.value=1,h()}function A(d){v.value=d,h()}function Q(){v.value=1,h()}function q(){y.value=!1,n.value={name:"",provider_type:"openai",api_key:"",base_url:"",default_model:"",description:""},g.value=!0}function G(d){y.value=!0,n.value={...d},g.value=!0}async function J(){if(n.value.name){w.value=!0;try{y.value&&n.value.name?await de(n.value.name,n.value):await ie(n.value),g.value=!1,await h()}catch(d){f.show("Failed to save: "+d.message)}finally{w.value=!1}}}async function O(d){if(await f.confirm(t("mgmt_confirm_delete")))try{await ue(d),await h()}catch(s){f.show("Failed to delete: "+s.message)}}function B(d,s){if(!d)return"-";const l=d.replace("T"," ").substring(0,16);return s?`${l} by ${s}`:l}function Y(){k.value=!1,C.value=-1,u.value={id:"",code:"",display_name:"",max_context:0},p.value=!0}function Z(d){k.value=!0,C.value=d,u.value={...(n.value.models??[])[d]},p.value=!0}function j(){if(u.value.id){if(k.value&&C.value>=0){const d=n.value.models??[];d[C.value]={...u.value},n.value.models=[...d]}else{const d=n.value.models??[];if(d.some(s=>s.id===u.value.id)){f.show(t("mgmt_confirm_delete"));return}n.value.models=[...d,{...u.value}]}p.value=!1}}function H(d){const s=n.value.models??[];n.value.models=s.filter((l,b)=>b!==d)}return le(h),(d,s)=>(i(),m("div",ce,[D(re),e("div",_e,[e("header",ve,[e("h1",null,o(a(t)("mgmt_providers")),1),e("button",{class:"btn-primary",onClick:q},o(a(t)("mgmt_new_provider")),1)]),e("div",ge,[c(e("input",{"onUpdate:modelValue":s[0]||(s[0]=l=>x.value=l),class:"mgmt-search",placeholder:a(t)("mgmt_search_placeholder"),onKeyup:te(T,["enter"])},null,40,pe),[[_,x.value]]),e("button",{class:"btn-search",onClick:T},o(a(t)("mgmt_search")),1)]),P.value?(i(),m("div",he,[e("table",be,[e("thead",null,[e("tr",null,[e("th",null,o(a(t)("mgmt_name")),1),e("th",null,o(a(t)("mgmt_provider_type")),1),e("th",null,o(a(t)("mgmt_base_url")),1),e("th",null,o(a(t)("mgmt_default_model")),1),e("th",null,o(a(t)("mgmt_created_at")),1),e("th",null,o(a(t)("mgmt_actions")),1)])]),e("tbody",null,[(i(),m(V,null,S(5,l=>e("tr",{key:l,class:"mgmt-skeleton-row"},[...s[18]||(s[18]=[e("td",null,[e("div",{class:"mgmt-skeleton-cell",style:{width:"60%"}})],-1),e("td",null,[e("div",{class:"mgmt-skeleton-cell",style:{width:"40%"}})],-1),e("td",null,[e("div",{class:"mgmt-skeleton-cell",style:{width:"50%"}})],-1),e("td",null,[e("div",{class:"mgmt-skeleton-cell",style:{width:"40%"}})],-1),e("td",null,[e("div",{class:"mgmt-skeleton-cell mgmt-skeleton-cell-sm",style:{width:"65%"}})],-1),e("td",null,[e("div",{class:"mgmt-skeleton-cell",style:{width:"50%"}})],-1)])])),64))])])])):U.value.length===0?(i(),m("div",fe,o(x.value?a(t)("mgmt_no_results"):a(t)("mgmt_no_providers")),1)):(i(),m("div",ye,[e("div",ke,[e("table",we,[e("thead",null,[e("tr",null,[e("th",null,o(a(t)("mgmt_name")),1),e("th",null,o(a(t)("mgmt_provider_type")),1),e("th",null,o(a(t)("mgmt_base_url")),1),e("th",null,o(a(t)("mgmt_default_model")),1),e("th",null,o(a(t)("mgmt_created_at")),1),e("th",null,o(a(t)("mgmt_actions")),1)])]),e("tbody",null,[(i(!0),m(V,null,S(U.value,l=>(i(),m("tr",{key:l.name},[e("td",{title:l.name},[e("code",null,o(l.name),1)],8,Ce),e("td",null,[e("code",null,o(l.provider_type),1)]),e("td",null,[e("code",{class:"cell-url",title:l.base_url||"-"},o(l.base_url||"-"),9,xe)]),e("td",null,o(l.default_model||"-"),1),e("td",{class:"cell-audit",title:B(l.created_at,l.created_by)},o(B(l.created_at,l.created_by)),9,Me),e("td",Ve,[e("button",{class:"btn-action",onClick:b=>G(l)},o(a(t)("mgmt_edit")),9,Se),e("button",{class:"btn-action btn-danger",onClick:b=>O(l.name)},o(a(t)("mgmt_delete")),9,Ue)])]))),128))])])]),e("div",Pe,[e("button",{class:"btn-page",disabled:v.value<=1,onClick:s[1]||(s[1]=l=>A(v.value-1))},o(a(t)("mgmt_prev_page")),9,$e),e("span",ze,o(v.value)+" / "+o(F.value),1),e("button",{class:"btn-page",disabled:v.value>=F.value,onClick:s[2]||(s[2]=l=>A(v.value+1))},o(a(t)("mgmt_next_page")),9,Fe),D(ae,{modelValue:M.value,"onUpdate:modelValue":s[3]||(s[3]=l=>M.value=l),modelModifiers:{number:!0},options:L,searchable:!1,onChange:Q},null,8,["modelValue"])])]))]),(i(),N(I,{to:"body"},[g.value?(i(),m("div",{key:0,class:"dialog-overlay",onMousedown:s[11]||(s[11]=E(l=>g.value=!1,["self"]))},[e("div",Te,[e("h2",null,o(y.value?a(t)("mgmt_edit_provider"):a(t)("mgmt_new_provider_title")),1),e("div",Ae,[e("label",null,o(a(t)("mgmt_name")),1),c(e("input",{"onUpdate:modelValue":s[4]||(s[4]=l=>n.value.name=l),placeholder:a(t)("mgmt_placeholder_name"),disabled:y.value},null,8,Be),[[_,n.value.name]])]),e("div",De,[e("label",null,o(a(t)("mgmt_provider_type")),1),c(e("select",{"onUpdate:modelValue":s[5]||(s[5]=l=>n.value.provider_type=l),class:"mgmt-dialog-select"},[(i(),m(V,null,S(K,l=>e("option",{key:l,value:l},o(l),9,Ne)),64))],512),[[oe,n.value.provider_type]])]),e("div",Ee,[e("label",null,o(a(t)("mgmt_api_key")),1),c(e("input",{"onUpdate:modelValue":s[6]||(s[6]=l=>n.value.api_key=l),type:"password",placeholder:a(t)("mgmt_api_key_placeholder")},null,8,Ie),[[_,n.value.api_key]])]),e("div",Ke,[e("label",null,o(a(t)("mgmt_base_url")),1),c(e("input",{"onUpdate:modelValue":s[7]||(s[7]=l=>n.value.base_url=l),placeholder:a(t)("mgmt_base_url_placeholder")},null,8,Le),[[_,n.value.base_url]])]),e("div",Qe,[e("label",null,o(a(t)("mgmt_default_model")),1),c(e("input",{"onUpdate:modelValue":s[8]||(s[8]=l=>n.value.default_model=l),placeholder:a(t)("mgmt_model_placeholder")},null,8,qe),[[_,n.value.default_model]])]),e("div",Ge,[e("label",null,o(a(t)("mgmt_description")),1),c(e("textarea",{"onUpdate:modelValue":s[9]||(s[9]=l=>n.value.description=l),rows:"2"},null,512),[[_,n.value.description]])]),e("details",Je,[e("summary",null,o(a(t)("mgmt_models")),1),(n.value.models??[]).length===0?(i(),m("div",Oe,o(a(t)("mgmt_no_models")),1)):(i(),m("div",Ye,[(i(!0),m(V,null,S(n.value.models,(l,b)=>(i(),m("div",{key:l.id,class:"model-item"},[e("div",Ze,[e("strong",null,o(l.display_name||l.id),1),e("span",je,[e("code",null,o(l.code||l.id),1)]),l.max_context>0?(i(),m("span",He,o(l.max_context.toLocaleString())+" ctx",1)):$("",!0)]),e("div",Re,[e("button",{class:"btn-sm btn-action",onClick:R=>Z(b)},o(a(t)("mgmt_edit")),9,We),e("button",{class:"btn-sm btn-action btn-danger",onClick:R=>H(b)},o(a(t)("mgmt_delete")),9,Xe)])]))),128))])),e("button",{class:"btn-sm btn-primary",style:{"margin-top":"8px"},onClick:Y},o(a(t)("mgmt_add_model")),1)]),e("div",el,[e("button",{class:"btn-action",onClick:s[10]||(s[10]=l=>g.value=!1)},o(a(t)("mgmt_cancel")),1),e("button",{class:"btn-primary",onClick:J,disabled:!n.value.name||w.value},o(w.value?a(t)("mgmt_saving"):a(t)("mgmt_save")),9,ll)])])],32)):$("",!0)])),(i(),N(I,{to:"body"},[p.value?(i(),m("div",{key:0,class:"dialog-overlay",onMousedown:s[17]||(s[17]=E(l=>p.value=!1,["self"]))},[e("div",tl,[e("h2",null,o(k.value?a(t)("mgmt_edit_model"):a(t)("mgmt_add_model")),1),e("div",al,[e("label",null,o(a(t)("mgmt_model_id")),1),c(e("input",{"onUpdate:modelValue":s[12]||(s[12]=l=>u.value.id=l),placeholder:a(t)("mgmt_placeholder_id"),disabled:k.value},null,8,ol),[[_,u.value.id]])]),e("div",sl,[e("label",null,o(a(t)("mgmt_model_code")),1),c(e("input",{"onUpdate:modelValue":s[13]||(s[13]=l=>u.value.code=l),placeholder:a(t)("mgmt_model_placeholder_code")},null,8,nl),[[_,u.value.code]])]),e("div",dl,[e("label",null,o(a(t)("mgmt_model_display_name")),1),c(e("input",{"onUpdate:modelValue":s[14]||(s[14]=l=>u.value.display_name=l),placeholder:a(t)("mgmt_placeholder_display_name")},null,8,il),[[_,u.value.display_name]])]),e("div",ul,[e("label",null,o(a(t)("mgmt_model_max_context")),1),c(e("input",{"onUpdate:modelValue":s[15]||(s[15]=l=>u.value.max_context=l),type:"number",min:"0",placeholder:a(t)("mgmt_model_placeholder_context")},null,8,ml),[[_,u.value.max_context,void 0,{number:!0}]])]),e("div",rl,[e("button",{class:"btn-action",onClick:s[16]||(s[16]=l=>p.value=!1)},o(a(t)("mgmt_cancel")),1),e("button",{class:"btn-primary",onClick:j,disabled:!u.value.id},o(a(t)("mgmt_save")),9,cl)])])],32)):$("",!0)]))]))}}),hl=me(_l,[["__scopeId","data-v-aa263a36"]]);export{hl as default};
@@ -0,0 +1 @@
1
+ .mgmt-dialog-select[data-v-aa263a36]{display:block;width:100%;padding:10px 14px;border:1px solid var(--glass-border);border-radius:10px;background:var(--glass-highlight);color:var(--text-primary);font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;transition:border-color var(--transition-duration),box-shadow var(--transition-duration)}.mgmt-dialog-select[data-v-aa263a36]:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-dim)}.model-list[data-v-aa263a36]{display:flex;flex-direction:column;gap:6px}.model-item[data-v-aa263a36]{display:flex;align-items:center;justify-content:space-between;padding:8px 10px;background:var(--glass-highlight);border:1px solid var(--glass-border);border-radius:8px;gap:8px}.model-item-info[data-v-aa263a36]{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.model-item-code[data-v-aa263a36]{color:var(--text-muted);font-size:12px}.model-item-ctx[data-v-aa263a36]{color:var(--accent);font-size:11px;white-space:nowrap}.model-item-actions[data-v-aa263a36]{display:flex;gap:4px;flex-shrink:0}.btn-sm[data-v-aa263a36]{padding:4px 10px;font-size:12px;border-radius:6px;border:1px solid var(--glass-border);background:var(--glass-highlight);color:var(--text-primary);cursor:pointer;transition:opacity .15s}.btn-sm[data-v-aa263a36]:hover{opacity:.8}