Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe0a45a84f | ||
|
|
67a99be224 |
No files matched your search
@@ -2,7 +2,7 @@
|
||||
"name": "aiturk-ide",
|
||||
"productName": "AITURK IDE",
|
||||
"private": true,
|
||||
"version": "1.0.0-beta.12",
|
||||
"version": "1.0.0-beta.13",
|
||||
"description": "TurkServis resmi yapay zekâ geliştirme ortamı. Hermes Agent tabanlıdır.",
|
||||
"author": "AITURK / TurkServis",
|
||||
"repository": {
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
"""Connect the AITURK distribution's media tools to its existing member key."""
|
||||
|
||||
|
||||
def configure_existing_media(cfg: dict) -> bool:
|
||||
"""Migrate an existing member endpoint when the upgraded backend starts."""
|
||||
providers = cfg.get("providers") or {}
|
||||
entries = providers.values() if isinstance(providers, dict) else []
|
||||
for entry in entries:
|
||||
if isinstance(entry, dict) and configure_media(cfg, entry):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def configure_media(cfg: dict, entry: dict) -> bool:
|
||||
if entry.get("base_url", "").rstrip("/") != "https://ai.turkservis.online/v1":
|
||||
return False
|
||||
key_env = entry.get("key_env")
|
||||
if not isinstance(key_env, str) or not key_env:
|
||||
return False
|
||||
servers = cfg.get("mcp_servers")
|
||||
if servers is None:
|
||||
servers = cfg["mcp_servers"] = {}
|
||||
if not isinstance(servers, dict):
|
||||
return False
|
||||
name = "turkservis-media"
|
||||
existing = servers.get(name, {})
|
||||
if not isinstance(existing, dict):
|
||||
return False
|
||||
if existing and existing.get("url") != "https://ai.turkservis.online/mcp":
|
||||
return False
|
||||
updated = {
|
||||
**existing,
|
||||
"url": "https://ai.turkservis.online/mcp",
|
||||
"headers": {"Authorization": "Bearer ${" + key_env + "}"},
|
||||
"timeout": 300,
|
||||
"tools": {"include": ["list_capabilities", "generate_media"]},
|
||||
}
|
||||
if updated == existing:
|
||||
return False
|
||||
servers[name] = updated
|
||||
return True
|
||||
@@ -405,12 +405,6 @@ def _eager_reconcile_own_session_db() -> None:
|
||||
|
||||
@asynccontextmanager
|
||||
async def _lifespan(app: "FastAPI"):
|
||||
from hermes_cli.aiturk_media import configure_existing_media
|
||||
from hermes_cli.config import read_raw_config, save_config
|
||||
with _CONFIG_MUTATION_LOCK:
|
||||
media_cfg = read_raw_config()
|
||||
if configure_existing_media(media_cfg):
|
||||
save_config(media_cfg)
|
||||
app.state.event_channels = {} # dict[str, set]
|
||||
app.state.event_lock = asyncio.Lock()
|
||||
app.state.pty_active_session_files = {} # dict[str, Path]
|
||||
@@ -8829,9 +8823,6 @@ def _write_custom_endpoint(cfg: Dict[str, Any], body: CustomEndpointUpdate) -> T
|
||||
providers[endpoint_id] = entry
|
||||
cfg["providers"] = providers
|
||||
|
||||
from hermes_cli.aiturk_media import configure_media
|
||||
configure_media(cfg, entry)
|
||||
|
||||
if body.make_default:
|
||||
cfg["model"] = _apply_main_model_assignment(
|
||||
cfg.get("model", {}), endpoint_id, model, base_url
|
||||
|
||||
Generated
+1
-1
@@ -65,7 +65,7 @@
|
||||
},
|
||||
"apps/desktop": {
|
||||
"name": "aiturk-ide",
|
||||
"version": "1.0.0-beta.12",
|
||||
"version": "1.0.0-beta.13",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@assistant-ui/core": "0.2.23",
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
name: aiturk-media
|
||||
description: "Generate images, video and speech or transcribe audio with the user's TurkServis account through the AITURK CLI (`aiturk media`). Use whenever the user asks for an image, video, voice-over or transcript."
|
||||
version: 1.0.0
|
||||
author: AITURK / TurkServis
|
||||
license: MIT
|
||||
platforms: [windows]
|
||||
prerequisites:
|
||||
commands: [aiturk]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [Media, Image, Video, TTS, STT, AITURK, TurkServis]
|
||||
---
|
||||
|
||||
# AITURK media (image, video, speech, transcription)
|
||||
|
||||
AITURK IDE produces media with the AITURK CLI that is installed next to it. The
|
||||
CLI uses the same TurkServis account; usage is billed to the member's balance.
|
||||
Do not add or enable an MCP media server for this.
|
||||
|
||||
## When to use
|
||||
|
||||
The user asks for an image, a short video, spoken audio from text, or a
|
||||
transcript of an audio file.
|
||||
|
||||
## Steps
|
||||
|
||||
The launcher is `aiturk.cmd`. In PowerShell or cmd type `aiturk`; in a bash-style
|
||||
terminal (Git Bash) type `aiturk.cmd` instead, with the same arguments.
|
||||
|
||||
1. List what the account can use right now. Never rely on a remembered model list.
|
||||
|
||||
```shell
|
||||
aiturk media list --json
|
||||
```
|
||||
|
||||
Use a capability only when its `status` is `available`. `unknown` is an
|
||||
access error; `unavailable` means no usable model. Pick the model the user
|
||||
named, or a fitting `id` from the list. Never invent a model id.
|
||||
|
||||
2. Run one generation. Choose an output file name that does not exist yet.
|
||||
|
||||
```shell
|
||||
aiturk media run image --model <model-id> --text "<what the user asked for>" --output image.png
|
||||
aiturk media run video --model <model-id> --text "<prompt>" --seconds 5 --output clip.mp4
|
||||
aiturk media run tts --model <model-id> --text "<text>" --voice <voice> --output speech.mp3
|
||||
aiturk media run stt --model <model-id> --audio <audio-file> --output transcript.txt
|
||||
```
|
||||
|
||||
3. Confirm the output file exists and has the expected type, then show or link
|
||||
it to the user. Do not retry a failed or interrupted generation automatically;
|
||||
each run is billed.
|
||||
|
||||
## If the command is unavailable
|
||||
|
||||
- `aiturk` and `aiturk.cmd` both not found: try `%LOCALAPPDATA%\TurkServis\AITURK\program\bin\aiturk.cmd`.
|
||||
If that is missing too, tell the user to install the AITURK CLI from
|
||||
https://turkservis.online/indir.
|
||||
- Not signed in or an authentication error: ask the user to run `aiturk login`
|
||||
once, then `aiturk doctor`.
|
||||
- Only while the CLI cannot be used at all may an already configured TurkServis
|
||||
media connection be used instead; say that you did and why.
|
||||
|
||||
Never print API keys, tokens or authorization headers. Without a generation
|
||||
request, list only; do not start a paid trial generation.
|
||||
@@ -1,35 +1,52 @@
|
||||
from hermes_cli.aiturk_media import configure_media, configure_existing_media
|
||||
"""AITURK IDE produces media through the AITURK CLI, never by adding an MCP server."""
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SKILL = ROOT / "skills" / "media" / "aiturk-media" / "SKILL.md"
|
||||
|
||||
|
||||
def test_existing_member_profile_migrates_once_without_changing_provider():
|
||||
entry = {"base_url": "https://ai.turkservis.online/v1", "key_env": "MEMBER_KEY"}
|
||||
cfg = {"providers": {"turkservis": dict(entry)}, "model": {"default": "kept"}}
|
||||
assert configure_existing_media(cfg)
|
||||
assert cfg["providers"]["turkservis"] == entry
|
||||
assert cfg["model"] == {"default": "kept"}
|
||||
assert not configure_existing_media(cfg)
|
||||
def test_backend_never_registers_a_turkservis_media_mcp_server():
|
||||
assert importlib.util.find_spec("hermes_cli.aiturk_media") is None
|
||||
source = (ROOT / "hermes_cli" / "web_server.py").read_text(encoding="utf-8")
|
||||
for needle in ("aiturk_media", "turkservis-media", "generate_media", "ai.turkservis.online/mcp"):
|
||||
assert needle not in source
|
||||
|
||||
|
||||
def test_member_key_is_referenced_without_copying_or_overwriting_other_servers():
|
||||
cfg = {"mcp_servers": {"other": {"url": "https://example.org/mcp"}}}
|
||||
entry = {"base_url": "https://ai.turkservis.online/v1", "key_env": "HERMES_CUSTOM_TURKSERVIS_API_KEY"}
|
||||
assert configure_media(cfg, entry)
|
||||
assert cfg["mcp_servers"]["other"] == {"url": "https://example.org/mcp"}
|
||||
assert cfg["mcp_servers"]["turkservis-media"]["headers"]["Authorization"] == "Bearer ${HERMES_CUSTOM_TURKSERVIS_API_KEY}"
|
||||
assert not configure_media(cfg, entry)
|
||||
entry["key_env"] = "ROTATED_MEMBER_KEY"
|
||||
assert configure_media(cfg, entry)
|
||||
assert "ROTATED_MEMBER_KEY" in cfg["mcp_servers"]["turkservis-media"]["headers"]["Authorization"]
|
||||
def test_no_backend_module_writes_the_turkservis_mcp_endpoint_into_config():
|
||||
offenders = [
|
||||
path.relative_to(ROOT).as_posix()
|
||||
for package in ("hermes_cli", "agent", "tools", "gateway", "tui_gateway")
|
||||
for path in (ROOT / package).rglob("*.py")
|
||||
if "ai.turkservis.online/mcp" in path.read_text(encoding="utf-8", errors="ignore")
|
||||
]
|
||||
assert offenders == []
|
||||
|
||||
|
||||
def test_other_provider_and_missing_key_do_not_enable_media():
|
||||
for entry in ({"base_url": "https://example.com/v1", "key_env": "SECRET"}, {"base_url": "https://ai.turkservis.online/v1"}):
|
||||
cfg = {}
|
||||
assert not configure_media(cfg, entry)
|
||||
assert cfg == {}
|
||||
def test_existing_user_mcp_entries_are_left_exactly_as_they_are():
|
||||
# Startup used to rewrite config.yaml; with the writer gone, a saved config
|
||||
# round-trips untouched (including a disabled turkservis-media entry).
|
||||
before = {
|
||||
"providers": {"turkservis": {"base_url": "https://ai.turkservis.online/v1", "key_env": "MEMBER_KEY"}},
|
||||
"mcp_servers": {
|
||||
"turkservis-media": {"url": "https://ai.turkservis.online/mcp", "enabled": False},
|
||||
"other": {"url": "https://example.org/mcp"},
|
||||
},
|
||||
}
|
||||
source = (ROOT / "hermes_cli" / "web_server.py").read_text(encoding="utf-8")
|
||||
lifespan = source[source.index("async def _lifespan("):]
|
||||
lifespan = lifespan[:lifespan.index("yield")]
|
||||
assert "save_config" not in lifespan and "mcp_servers" not in lifespan
|
||||
assert yaml.safe_load(yaml.safe_dump(before)) == before
|
||||
|
||||
|
||||
def test_explicitly_disabled_connection_stays_disabled():
|
||||
cfg = {"mcp_servers": {"turkservis-media": {"url": "https://ai.turkservis.online/mcp", "enabled": False}}}
|
||||
configure_media(cfg, {"base_url": "https://ai.turkservis.online/v1", "key_env": "KEY"})
|
||||
assert cfg["mcp_servers"]["turkservis-media"]["enabled"] is False
|
||||
def test_bundled_skill_teaches_aiturk_media():
|
||||
text = SKILL.read_text(encoding="utf-8")
|
||||
meta = yaml.safe_load(text.split("---")[1])
|
||||
assert meta["name"] == "aiturk-media"
|
||||
for phrase in ("aiturk media list --json", "aiturk media run image", "aiturk media run video",
|
||||
"aiturk media run tts", "aiturk media run stt", "aiturk login"):
|
||||
assert phrase in text
|
||||
assert "Do not add or enable an MCP media server" in text
|
||||
Reference in new issue
Block a user