@oneciel-ai/ciel-runtime 0.2.2 → 0.2.4
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.
- package/ciel_runtime.py +2555 -9635
- package/ciel_runtime_support/advisor_request_builder.py +8 -21
- package/ciel_runtime_support/anthropic_tool_turns.py +13 -8
- package/ciel_runtime_support/architecture.py +68 -0
- package/ciel_runtime_support/architecture_budget.py +1 -1
- package/ciel_runtime_support/channel_connection_context.py +233 -0
- package/ciel_runtime_support/channel_delivery_context.py +332 -0
- package/ciel_runtime_support/channel_mcp_context.py +313 -0
- package/ciel_runtime_support/channel_mcp_discovery.py +47 -0
- package/ciel_runtime_support/channel_mcp_transport.py +5 -1
- package/ciel_runtime_support/channel_message_context.py +212 -0
- package/ciel_runtime_support/channel_message_repository.py +14 -3
- package/ciel_runtime_support/channel_pending_injection.py +9 -0
- package/ciel_runtime_support/channel_probe_launch_context.py +213 -0
- package/ciel_runtime_support/channel_replay_policy.py +38 -0
- package/ciel_runtime_support/channel_runtime_environment.py +8 -0
- package/ciel_runtime_support/channel_session_context.py +236 -0
- package/ciel_runtime_support/channel_terminal_context.py +350 -0
- package/ciel_runtime_support/channel_wake_context.py +532 -0
- package/ciel_runtime_support/claude_environment.py +60 -0
- package/ciel_runtime_support/claude_launch_assembly.py +249 -0
- package/ciel_runtime_support/claude_router.py +62 -12
- package/ciel_runtime_support/cli_application_context.py +132 -0
- package/ciel_runtime_support/cli_assembly.py +50 -0
- package/ciel_runtime_support/codex_backend_context.py +363 -0
- package/ciel_runtime_support/codex_config.py +13 -1
- package/ciel_runtime_support/codex_launch_assembly.py +213 -0
- package/ciel_runtime_support/codex_launch_configuration.py +30 -1
- package/ciel_runtime_support/codex_mcp_integration.py +90 -8
- package/ciel_runtime_support/codex_model_catalog.py +4 -1
- package/ciel_runtime_support/codex_reasoning_rejects.py +225 -0
- package/ciel_runtime_support/codex_router.py +38 -8
- package/ciel_runtime_support/codex_turn_recovery.py +154 -0
- package/ciel_runtime_support/config_migrations.py +103 -0
- package/ciel_runtime_support/config_repository.py +30 -0
- package/ciel_runtime_support/configuration_cli.py +38 -0
- package/ciel_runtime_support/context_compaction.py +9 -4
- package/ciel_runtime_support/credential_management.py +12 -0
- package/ciel_runtime_support/credentials.py +12 -0
- package/ciel_runtime_support/github_copilot_oauth.py +2 -2
- package/ciel_runtime_support/hosted_formula_tools.py +216 -0
- package/ciel_runtime_support/kimi_runtime_context.py +208 -0
- package/ciel_runtime_support/llm_preset_context.py +338 -0
- package/ciel_runtime_support/managed_mcp_config.py +8 -4
- package/ciel_runtime_support/mcp_configuration_context.py +291 -0
- package/ciel_runtime_support/mcp_http_proxy.py +14 -8
- package/ciel_runtime_support/mcp_probe_transport.py +47 -15
- package/ciel_runtime_support/mcp_transport.py +14 -1
- package/ciel_runtime_support/native_context_recovery.py +72 -0
- package/ciel_runtime_support/ollama_catalog_context.py +213 -0
- package/ciel_runtime_support/ollama_stream_collection.py +103 -0
- package/ciel_runtime_support/ollama_thinking.py +6 -1
- package/ciel_runtime_support/ollama_wire_projection.py +157 -0
- package/ciel_runtime_support/openai_forwarding.py +32 -10
- package/ciel_runtime_support/openai_responses_router.py +12 -0
- package/ciel_runtime_support/package_lifecycle.py +39 -0
- package/ciel_runtime_support/prelaunch_assembly.py +37 -0
- package/ciel_runtime_support/prelaunch_panel_context.py +418 -0
- package/ciel_runtime_support/prelaunch_shell_context.py +394 -0
- package/ciel_runtime_support/prompt_compaction.py +144 -0
- package/ciel_runtime_support/prompt_injection.py +45 -0
- package/ciel_runtime_support/protocols/anthropic_thinking_policy.py +1 -1
- package/ciel_runtime_support/protocols/chat_projection.py +85 -5
- package/ciel_runtime_support/protocols/conversation_turn_policy.py +43 -0
- package/ciel_runtime_support/protocols/ollama_chat.py +31 -0
- package/ciel_runtime_support/protocols/ollama_response.py +57 -5
- package/ciel_runtime_support/protocols/openai_reasoning.py +5 -2
- package/ciel_runtime_support/protocols/openai_responses.py +61 -15
- package/ciel_runtime_support/provider_adapters.py +26 -0
- package/ciel_runtime_support/provider_administration_context.py +207 -0
- package/ciel_runtime_support/provider_config_mutations.py +3 -0
- package/ciel_runtime_support/provider_model_catalog_context.py +137 -0
- package/ciel_runtime_support/provider_model_context.py +107 -0
- package/ciel_runtime_support/provider_model_metadata_context.py +197 -0
- package/ciel_runtime_support/provider_model_selection.py +10 -3
- package/ciel_runtime_support/provider_models.py +45 -2
- package/ciel_runtime_support/provider_option_cli.py +19 -0
- package/ciel_runtime_support/provider_policy.py +1 -1
- package/ciel_runtime_support/provider_readiness_context.py +189 -0
- package/ciel_runtime_support/provider_request_builder.py +64 -28
- package/ciel_runtime_support/provider_responses_passthrough.py +21 -2
- package/ciel_runtime_support/provider_timeout_policy.py +54 -0
- package/ciel_runtime_support/provider_tool_policy.py +9 -1
- package/ciel_runtime_support/providers/__init__.py +6 -0
- package/ciel_runtime_support/providers/alibaba.py +634 -0
- package/ciel_runtime_support/providers/catalog.py +24 -16
- package/ciel_runtime_support/providers/deepseek.py +73 -0
- package/ciel_runtime_support/providers/github_copilot_oauth.py +22 -1
- package/ciel_runtime_support/providers/kimi.py +69 -9
- package/ciel_runtime_support/providers/ollama.py +8 -0
- package/ciel_runtime_support/providers/ollama_context.py +21 -2
- package/ciel_runtime_support/providers/vllm.py +7 -1
- package/ciel_runtime_support/response_collection.py +68 -18
- package/ciel_runtime_support/response_collection_context.py +391 -0
- package/ciel_runtime_support/response_stream_context.py +555 -0
- package/ciel_runtime_support/responses_input_compatibility.py +121 -0
- package/ciel_runtime_support/responses_usage_observer.py +83 -0
- package/ciel_runtime_support/router_client_lifecycle.py +1 -0
- package/ciel_runtime_support/router_http.py +245 -3
- package/ciel_runtime_support/router_observability_context.py +251 -0
- package/ciel_runtime_support/router_process_context.py +200 -0
- package/ciel_runtime_support/router_process_lifecycle.py +2 -0
- package/ciel_runtime_support/router_request_assembly.py +399 -0
- package/ciel_runtime_support/router_request_context.py +215 -0
- package/ciel_runtime_support/router_server_context.py +84 -0
- package/ciel_runtime_support/runaway_output_guard.py +488 -0
- package/ciel_runtime_support/runtime_asset_assembly.py +147 -0
- package/ciel_runtime_support/runtime_asset_context.py +297 -0
- package/ciel_runtime_support/runtime_constants.py +16 -1
- package/ciel_runtime_support/runtime_launch.py +9 -5
- package/ciel_runtime_support/runtime_launch_context.py +130 -0
- package/ciel_runtime_support/runtime_maintenance_assembly.py +60 -0
- package/ciel_runtime_support/runtime_maintenance_context.py +309 -0
- package/ciel_runtime_support/runtime_maintenance_services.py +265 -0
- package/ciel_runtime_support/runtime_paths.py +60 -40
- package/ciel_runtime_support/runtime_primitives.py +78 -0
- package/ciel_runtime_support/speech_http_controller.py +335 -0
- package/ciel_runtime_support/sse_stream_collection.py +236 -0
- package/ciel_runtime_support/statusline_script.py +57 -8
- package/ciel_runtime_support/streaming_anthropic.py +361 -24
- package/ciel_runtime_support/tool_schema.py +40 -2
- package/ciel_runtime_support/tool_side_effect_dedupe.py +117 -12
- package/ciel_runtime_support/upstream_dump.py +68 -0
- package/ciel_runtime_support/upstream_retry_context.py +259 -0
- package/ciel_runtime_support/web_ui.py +248 -1
- package/ciel_runtime_support/workspace_router_selection.py +86 -0
- package/docs/COLAB_SPEECH.md +32 -0
- package/docs/Configuration.md +50 -0
- package/docs/Test-Suite.md +1 -0
- package/package.json +4 -1
- package/scripts/colab/__pycache__/bootstrap_moss_tts.cpython-311.pyc +0 -0
- package/scripts/colab/__pycache__/bootstrap_qwen_asr.cpython-311.pyc +0 -0
- package/scripts/colab/bootstrap_moss_tts.py +106 -0
- package/scripts/colab/bootstrap_qwen_asr.py +106 -0
- package/scripts/configure_speech_workers.py +37 -0
- package/scripts/deploy_colab_speech.ps1 +47 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Bootstrap Qwen3-ASR on a Colab T4 and publish it only to the tailnet.
|
|
2
|
+
|
|
3
|
+
Required Colab Secret: TAILSCALE_AUTHKEY
|
|
4
|
+
Optional Colab Secret: CIEL_SPEECH_API_KEY
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
import time
|
|
16
|
+
import urllib.request
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
HOSTNAME = os.environ.get("CIEL_ASR_HOSTNAME", "ciel-asr")
|
|
20
|
+
PORT = 8000
|
|
21
|
+
SOCKET = "/tmp/ciel-asr-tailscaled.sock"
|
|
22
|
+
STATE = "/tmp/ciel-asr-tailscaled.state"
|
|
23
|
+
LOG_DIR = Path("/content/ciel-speech-logs")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def secret(name: str, *, required: bool = False) -> str:
|
|
27
|
+
value = str(os.environ.get(name) or "").strip()
|
|
28
|
+
if not value:
|
|
29
|
+
try:
|
|
30
|
+
from google.colab import userdata # type: ignore
|
|
31
|
+
|
|
32
|
+
value = str(userdata.get(name) or "").strip()
|
|
33
|
+
except Exception:
|
|
34
|
+
value = ""
|
|
35
|
+
if required and not value:
|
|
36
|
+
raise RuntimeError(f"Add {name} to Colab Secrets and allow notebook access, then rerun this script.")
|
|
37
|
+
return value
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run(*args: str, check: bool = True) -> subprocess.CompletedProcess[str]:
|
|
41
|
+
print("+", " ".join(args))
|
|
42
|
+
return subprocess.run(args, check=check, text=True, capture_output=False)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def install_tailscale() -> None:
|
|
46
|
+
if shutil.which("tailscale"):
|
|
47
|
+
return
|
|
48
|
+
run("bash", "-lc", "curl -fsSL https://tailscale.com/install.sh | sh")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def start_tailscale(auth_key: str) -> tuple[str, str]:
|
|
52
|
+
install_tailscale()
|
|
53
|
+
LOG_DIR.mkdir(parents=True, exist_ok=True)
|
|
54
|
+
tail_log = (LOG_DIR / "tailscale-asr.log").open("ab")
|
|
55
|
+
subprocess.Popen(
|
|
56
|
+
["tailscaled", f"--socket={SOCKET}", f"--state={STATE}", "--tun=userspace-networking"],
|
|
57
|
+
stdout=tail_log,
|
|
58
|
+
stderr=subprocess.STDOUT,
|
|
59
|
+
start_new_session=True,
|
|
60
|
+
)
|
|
61
|
+
for _ in range(60):
|
|
62
|
+
if Path(SOCKET).exists():
|
|
63
|
+
break
|
|
64
|
+
time.sleep(1)
|
|
65
|
+
run("tailscale", f"--socket={SOCKET}", "up", f"--auth-key={auth_key}", f"--hostname={HOSTNAME}", "--accept-dns=true", "--reset")
|
|
66
|
+
status = subprocess.check_output(["tailscale", f"--socket={SOCKET}", "status", "--json"], text=True)
|
|
67
|
+
dns_name = str(json.loads(status).get("Self", {}).get("DNSName") or HOSTNAME).rstrip(".")
|
|
68
|
+
serve = run("tailscale", f"--socket={SOCKET}", "serve", "--bg", "--https=443", f"http://127.0.0.1:{PORT}", check=False)
|
|
69
|
+
if serve.returncode == 0:
|
|
70
|
+
return dns_name, f"https://{dns_name}"
|
|
71
|
+
run("tailscale", f"--socket={SOCKET}", "serve", "--bg", "--http=80", f"http://127.0.0.1:{PORT}")
|
|
72
|
+
return dns_name, f"http://{dns_name}"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def wait_for_server(api_key: str) -> None:
|
|
76
|
+
headers = {"authorization": f"Bearer {api_key}"} if api_key else {}
|
|
77
|
+
for _ in range(180):
|
|
78
|
+
try:
|
|
79
|
+
with urllib.request.urlopen(urllib.request.Request(f"http://127.0.0.1:{PORT}/health", headers=headers), timeout=3) as response:
|
|
80
|
+
if response.status < 500:
|
|
81
|
+
return
|
|
82
|
+
except Exception:
|
|
83
|
+
time.sleep(2)
|
|
84
|
+
raise RuntimeError("Qwen ASR did not become healthy; inspect /content/ciel-speech-logs/qwen-asr.log")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def main() -> None:
|
|
88
|
+
auth_key = secret("TAILSCALE_AUTHKEY", required=True)
|
|
89
|
+
api_key = secret("CIEL_SPEECH_API_KEY")
|
|
90
|
+
run(sys.executable, "-m", "pip", "install", "-U", "qwen-asr[vllm]", "vllm[audio]")
|
|
91
|
+
LOG_DIR.mkdir(parents=True, exist_ok=True)
|
|
92
|
+
command = [
|
|
93
|
+
"qwen-asr-serve", "Qwen/Qwen3-ASR-0.6B", "--host", "127.0.0.1", "--port", str(PORT),
|
|
94
|
+
"--gpu-memory-utilization", "0.78", "--max-model-len", "8192",
|
|
95
|
+
]
|
|
96
|
+
if api_key:
|
|
97
|
+
command.extend(["--api-key", api_key])
|
|
98
|
+
server_log = (LOG_DIR / "qwen-asr.log").open("ab")
|
|
99
|
+
subprocess.Popen(command, stdout=server_log, stderr=subprocess.STDOUT, start_new_session=True)
|
|
100
|
+
wait_for_server(api_key)
|
|
101
|
+
dns_name, base_url = start_tailscale(auth_key)
|
|
102
|
+
print(json.dumps({"ok": True, "role": "asr", "hostname": dns_name, "base_url": base_url, "model": "Qwen/Qwen3-ASR-0.6B", "api_key_set": bool(api_key)}, indent=2))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
main()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Persist deployed speech worker URLs in the active Ciel Runtime config."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import sys
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def configure(asr_base_url: str, tts_base_url: str) -> dict[str, Any]:
|
|
14
|
+
import ciel_runtime
|
|
15
|
+
|
|
16
|
+
config = ciel_runtime.load_config()
|
|
17
|
+
speech = config.setdefault("speech", {})
|
|
18
|
+
asr = speech.setdefault("asr", {})
|
|
19
|
+
tts = speech.setdefault("tts", {})
|
|
20
|
+
asr.update({"enabled": True, "base_url": asr_base_url.rstrip("/"), "model": "Qwen/Qwen3-ASR-0.6B"})
|
|
21
|
+
tts.update({"enabled": True, "base_url": tts_base_url.rstrip("/"), "model": "OpenMOSS-Team/MOSS-TTS-Nano"})
|
|
22
|
+
ciel_runtime.save_config(config)
|
|
23
|
+
return {"asr": asr["base_url"], "tts": tts["base_url"]}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main() -> int:
|
|
27
|
+
parser = argparse.ArgumentParser()
|
|
28
|
+
parser.add_argument("--asr-base-url", required=True)
|
|
29
|
+
parser.add_argument("--tts-base-url", required=True)
|
|
30
|
+
args = parser.parse_args()
|
|
31
|
+
result = configure(args.asr_base_url, args.tts_base_url)
|
|
32
|
+
print(f"Configured Ciel speech workers: ASR={result['asr']} TTS={result['tts']}")
|
|
33
|
+
return 0
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if __name__ == "__main__":
|
|
37
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$Distribution = "Ubuntu-26.04",
|
|
3
|
+
[string]$AsrSession = "ciel-asr",
|
|
4
|
+
[string]$TtsSession = "ciel-tts"
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
$repo = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
|
9
|
+
$wslRepo = (& wsl -d $Distribution -- wslpath -a ($repo -replace '\\', '/')).Trim()
|
|
10
|
+
if (-not $wslRepo) { throw "Could not resolve the repository path in WSL." }
|
|
11
|
+
|
|
12
|
+
Write-Host "Checking Colab CLI authentication..."
|
|
13
|
+
& wsl -d $Distribution -- bash -lc "colab status >/dev/null"
|
|
14
|
+
if ($LASTEXITCODE -ne 0) {
|
|
15
|
+
throw "Colab CLI is not authenticated. Configure ADC in WSL (gcloud auth application-default login), then rerun."
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Write-Host "Creating ASR T4 session: $AsrSession"
|
|
19
|
+
& wsl -d $Distribution -- bash -lc "colab new --gpu T4 --session '$AsrSession'"
|
|
20
|
+
if ($LASTEXITCODE -ne 0) { throw "Could not create ASR Colab session." }
|
|
21
|
+
|
|
22
|
+
Write-Host "Creating TTS T4 session: $TtsSession"
|
|
23
|
+
& wsl -d $Distribution -- bash -lc "colab new --gpu T4 --session '$TtsSession'"
|
|
24
|
+
if ($LASTEXITCODE -ne 0) { throw "Could not create TTS Colab session." }
|
|
25
|
+
|
|
26
|
+
Write-Host "Installing Qwen3-ASR and its Tailscale service..."
|
|
27
|
+
$asrOutput = (& wsl -d $Distribution -- bash -lc "colab exec --session '$AsrSession' --file '$wslRepo/scripts/colab/bootstrap_qwen_asr.py'" 2>&1 | Tee-Object -Variable asrDisplay) -join "`n"
|
|
28
|
+
if ($LASTEXITCODE -ne 0) { throw "ASR bootstrap failed." }
|
|
29
|
+
|
|
30
|
+
Write-Host "Installing MOSS-TTS-Nano and its Tailscale service..."
|
|
31
|
+
$ttsOutput = (& wsl -d $Distribution -- bash -lc "colab exec --session '$TtsSession' --file '$wslRepo/scripts/colab/bootstrap_moss_tts.py'" 2>&1 | Tee-Object -Variable ttsDisplay) -join "`n"
|
|
32
|
+
if ($LASTEXITCODE -ne 0) { throw "TTS bootstrap failed." }
|
|
33
|
+
|
|
34
|
+
function Read-BootstrapResult([string]$Text, [string]$Role) {
|
|
35
|
+
$matches = [regex]::Matches($Text, '(?s)\{\s*"ok"\s*:\s*true.*?\}')
|
|
36
|
+
if ($matches.Count -eq 0) { throw "Could not find the $Role bootstrap result in Colab output." }
|
|
37
|
+
$result = $matches[$matches.Count - 1].Value | ConvertFrom-Json
|
|
38
|
+
if ($result.role -ne $Role -or -not $result.base_url) { throw "Invalid $Role bootstrap result." }
|
|
39
|
+
return $result
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
$asr = Read-BootstrapResult $asrOutput "asr"
|
|
43
|
+
$tts = Read-BootstrapResult $ttsOutput "tts"
|
|
44
|
+
& python (Join-Path $PSScriptRoot "configure_speech_workers.py") --asr-base-url $asr.base_url --tts-base-url $tts.base_url
|
|
45
|
+
if ($LASTEXITCODE -ne 0) { throw "Workers started, but Ciel speech configuration failed." }
|
|
46
|
+
|
|
47
|
+
Write-Host "Both services are running and connected to Web Chat > Speech Settings."
|