akashcli 4.8.8__tar.gz → 4.8.9__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.
- {akashcli-4.8.8 → akashcli-4.8.9}/PKG-INFO +1 -1
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/__init__.py +1 -1
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/cli.py +307 -17
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli.egg-info/PKG-INFO +1 -1
- {akashcli-4.8.8 → akashcli-4.8.9}/pyproject.toml +1 -1
- {akashcli-4.8.8 → akashcli-4.8.9}/README.md +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/_net.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/auth.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/client.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/config.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/crypto.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/env_manager.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/exceptions.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/exec.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/integrity.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/logger.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/models.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/p2p.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/packages.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/relay.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/restore.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/snapshot_crypto.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/storage.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/terminal.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/updater.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/uploader.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli/utils.py +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli.egg-info/SOURCES.txt +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli.egg-info/dependency_links.txt +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli.egg-info/entry_points.txt +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli.egg-info/requires.txt +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/akashcli.egg-info/top_level.txt +0 -0
- {akashcli-4.8.8 → akashcli-4.8.9}/setup.cfg +0 -0
|
@@ -4090,6 +4090,7 @@ def mcp_share(
|
|
|
4090
4090
|
target: Optional[str] = typer.Argument(None, help="Profile ID (optional if only 1 profile exists)"),
|
|
4091
4091
|
id: Optional[str] = typer.Option(None, "--id", "-i", help="Profile ID"),
|
|
4092
4092
|
temp: Optional[str] = typer.Option(None, "--temp", "-t", help="Temporary short URL duration (e.g. '30m', '30 min', '1h')"),
|
|
4093
|
+
local: bool = typer.Option(False, "--local", "-l", help="Show snippet only for local-first zero-network stdio MCP"),
|
|
4093
4094
|
codex: bool = typer.Option(False, "--codex", "-c", help="Show snippet only for Codex CLI/Desktop"),
|
|
4094
4095
|
claude: bool = typer.Option(False, "--claude", help="Show snippet only for Claude Desktop / Cursor"),
|
|
4095
4096
|
chatgpt: bool = typer.Option(False, "--chatgpt", "-g", help="Show snippet only for ChatGPT Custom GPT Actions"),
|
|
@@ -4250,16 +4251,48 @@ def mcp_share(
|
|
|
4250
4251
|
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4251
4252
|
_p()
|
|
4252
4253
|
|
|
4253
|
-
show_all = not codex and not claude and not chatgpt
|
|
4254
|
+
show_all = not local and not codex and not claude and not chatgpt
|
|
4255
|
+
|
|
4256
|
+
# ── 1. LOCAL-FIRST STDIO MODE (ZERO NETWORK) ──
|
|
4257
|
+
if show_all or local:
|
|
4258
|
+
print(" " + _C + "1. Local Mode (Offline · Zero Network · Direct Stdio · Recommended)" + _RS + ":")
|
|
4259
|
+
print(" " + _DM + "For Claude Desktop, Cursor & local AI agents on this device." + _RS)
|
|
4260
|
+
print(" " + _dim(" (Zero network exposure, no open ports, direct local pipe)"))
|
|
4261
|
+
stdio_cfg = json.dumps({
|
|
4262
|
+
"mcpServers": {
|
|
4263
|
+
"akash": {
|
|
4264
|
+
"command": "akash",
|
|
4265
|
+
"args": ["mcp", "stdio"]
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
}, indent=2)
|
|
4269
|
+
for c_line in stdio_cfg.splitlines():
|
|
4270
|
+
print(" " + c_line)
|
|
4271
|
+
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4272
|
+
_p()
|
|
4254
4273
|
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
print(" " +
|
|
4274
|
+
# ── 2. NETWORK / RELAY MODE (AUTHENTICATED OVER DOMAIN / CLOUDFLARE / AKASHBOX) ──
|
|
4275
|
+
if show_all or claude:
|
|
4276
|
+
is_custom = bool(base != DEFAULT_STORAGE_URL)
|
|
4277
|
+
domain_tag = "Custom Domain / Cloudflare" if is_custom else "Akashbox Network Relay"
|
|
4278
|
+
print(" " + _C + "2. Network / Internet Mode (" + domain_tag + ")" + _RS + ":")
|
|
4279
|
+
print(" " + _DM + "Active Domain : " + _RS + _cy(base))
|
|
4280
|
+
print(" " + _DM + "Hardware Auth : " + _RS + _G + "Strict (Client ID + Secret + Device Fingerprint required)" + _RS)
|
|
4281
|
+
print(" " + _DM + "Authenticated URL : " + _RS)
|
|
4282
|
+
print(" " + _ye(local_url))
|
|
4283
|
+
_p()
|
|
4284
|
+
print(" " + _DM + "Config snippet for remote Claude Desktop, Cursor & Cline:" + _RS)
|
|
4285
|
+
claude_cfg = json.dumps({"mcpServers": {"akash": {"url": local_url}}}, indent=2)
|
|
4286
|
+
for c_line in claude_cfg.splitlines():
|
|
4287
|
+
print(" " + c_line)
|
|
4288
|
+
print(" " + _DM + " Logo / Icon: Clean Cloud Icon delivered automatically via MCP handshake" + _RS)
|
|
4289
|
+
_p()
|
|
4290
|
+
print(" " + _dim(" • To use a custom domain or Cloudflare tunnel: akash url https://your-domain.com"))
|
|
4291
|
+
print(" " + _dim(" • To reset back to default Akashbox relay : akash url --reset"))
|
|
4260
4292
|
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4261
4293
|
_p()
|
|
4262
4294
|
|
|
4295
|
+
# ── 3. CHATGPT CUSTOM GPT ACTIONS (OPENAPI REST) ──
|
|
4263
4296
|
if show_all or chatgpt:
|
|
4264
4297
|
app_token = None
|
|
4265
4298
|
for tok_path in [Path.home() / ".akash_app_tokens.json", Path.home() / ".akash" / "app_tokens.json"]:
|
|
@@ -4282,7 +4315,7 @@ def mcp_share(
|
|
|
4282
4315
|
token_val = app_token or csec or "akash_sec_client_03e804cabbbcface799a4522ca673dd166b8e76813f84389"
|
|
4283
4316
|
openapi_url = base + "/openapi.json"
|
|
4284
4317
|
privacy_url = base + "/privacy"
|
|
4285
|
-
print(" " + _C + "For ChatGPT Custom GPT (OpenAPI Actions)" + _RS + ":")
|
|
4318
|
+
print(" " + _C + "3. For ChatGPT Custom GPT (OpenAPI Actions)" + _RS + ":")
|
|
4286
4319
|
print(" " + _DM + "OpenAPI Schema URL : " + _RS + _cy(openapi_url))
|
|
4287
4320
|
print(" " + _DM + "Authentication : " + _RS + _W + "API Key" + _RS + " " + _dim("->") + " " + _W + "Custom" + _RS)
|
|
4288
4321
|
print(" " + _DM + "Custom Header Name : " + _RS + _ye("X-App-Token"))
|
|
@@ -4292,7 +4325,7 @@ def mcp_share(
|
|
|
4292
4325
|
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4293
4326
|
_p()
|
|
4294
4327
|
|
|
4295
|
-
if
|
|
4328
|
+
if codex:
|
|
4296
4329
|
print(" " + _C + "For Codex CLI / Desktop" + _RS + " " + _dim("(~/.codex/config.toml)") + ":")
|
|
4297
4330
|
print(" " + _DM + "Option A: Same Device (Termux / Localhost)" + _RS)
|
|
4298
4331
|
print(" [mcp_servers.akash]")
|
|
@@ -4305,15 +4338,6 @@ def mcp_share(
|
|
|
4305
4338
|
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4306
4339
|
_p()
|
|
4307
4340
|
|
|
4308
|
-
if show_all or claude:
|
|
4309
|
-
print(" " + _C + "For Claude Desktop, Cursor & Cline" + _RS + " " + _dim("(config.json / settings.json)") + ":")
|
|
4310
|
-
claude_cfg = json.dumps({"mcpServers": {"akash": {"url": local_url}}}, indent=2)
|
|
4311
|
-
for c_line in claude_cfg.splitlines():
|
|
4312
|
-
print(" " + c_line)
|
|
4313
|
-
print(" " + _DM + " Logo / Icon: Clean Cloud Icon delivered automatically via MCP handshake" + _RS)
|
|
4314
|
-
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4315
|
-
_p()
|
|
4316
|
-
|
|
4317
4341
|
_info("Paste snippet into AI client, then keep running:")
|
|
4318
4342
|
_info(" " + _cy("akash mcp serve"))
|
|
4319
4343
|
_p()
|
|
@@ -4360,5 +4384,271 @@ def mcp_status(
|
|
|
4360
4384
|
print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
|
|
4361
4385
|
_p()
|
|
4362
4386
|
|
|
4387
|
+
|
|
4388
|
+
@agent_app.command("stdio")
|
|
4389
|
+
def mcp_stdio(
|
|
4390
|
+
profile_id: Optional[str] = typer.Option(None, "--id", "-i", help="Local Agent Profile ID"),
|
|
4391
|
+
):
|
|
4392
|
+
"""Runs a zero-network, local-first Model Context Protocol stdio server over stdin/stdout."""
|
|
4393
|
+
import sys, json, re, subprocess, time
|
|
4394
|
+
from pathlib import Path
|
|
4395
|
+
from . import __version__
|
|
4396
|
+
|
|
4397
|
+
agents_file = Path.home() / ".akash" / "agents.json"
|
|
4398
|
+
agents = {}
|
|
4399
|
+
if agents_file.exists():
|
|
4400
|
+
try:
|
|
4401
|
+
agents = json.loads(agents_file.read_text(encoding="utf-8"))
|
|
4402
|
+
except Exception:
|
|
4403
|
+
agents = {}
|
|
4404
|
+
|
|
4405
|
+
target_pid = profile_id or (next(reversed(list(agents.keys()))) if agents else "default")
|
|
4406
|
+
profile = agents.get(target_pid, {})
|
|
4407
|
+
scopes = profile.get("scopes", "*")
|
|
4408
|
+
pname = profile.get("name", "LocalAgent")
|
|
4409
|
+
|
|
4410
|
+
tools_definitions = [
|
|
4411
|
+
{
|
|
4412
|
+
"name": "akash_exec_command",
|
|
4413
|
+
"description": "Executes shell commands in the workspace with safety policies, secret redaction, and automatic undo snapshotting.",
|
|
4414
|
+
"inputSchema": {
|
|
4415
|
+
"type": "object",
|
|
4416
|
+
"properties": {
|
|
4417
|
+
"command": {"type": "string", "description": "The shell command to execute."}
|
|
4418
|
+
},
|
|
4419
|
+
"required": ["command"]
|
|
4420
|
+
}
|
|
4421
|
+
},
|
|
4422
|
+
{
|
|
4423
|
+
"name": "akash_read_file",
|
|
4424
|
+
"description": "Reads a file from the workspace with line-range pagination directly into context.",
|
|
4425
|
+
"inputSchema": {
|
|
4426
|
+
"type": "object",
|
|
4427
|
+
"properties": {
|
|
4428
|
+
"path": {"type": "string", "description": "Path to the file to read."},
|
|
4429
|
+
"offset": {"type": "integer", "description": "Starting line number (1-indexed).", "default": 1},
|
|
4430
|
+
"limit": {"type": "integer", "description": "Maximum number of lines to return.", "default": 200}
|
|
4431
|
+
},
|
|
4432
|
+
"required": ["path"]
|
|
4433
|
+
}
|
|
4434
|
+
},
|
|
4435
|
+
{
|
|
4436
|
+
"name": "akash_write_file",
|
|
4437
|
+
"description": "Writes or edits a file in the workspace safely with auto-undo checkpoints.",
|
|
4438
|
+
"inputSchema": {
|
|
4439
|
+
"type": "object",
|
|
4440
|
+
"properties": {
|
|
4441
|
+
"path": {"type": "string", "description": "Path to the file to write."},
|
|
4442
|
+
"content": {"type": "string", "description": "The content to write into the file."},
|
|
4443
|
+
"append": {"type": "boolean", "description": "Whether to append to the file instead of overwriting.", "default": False}
|
|
4444
|
+
},
|
|
4445
|
+
"required": ["path", "content"]
|
|
4446
|
+
}
|
|
4447
|
+
},
|
|
4448
|
+
{
|
|
4449
|
+
"name": "akash_list_dir",
|
|
4450
|
+
"description": "Lists directory entries with file sizes, types, and depth control.",
|
|
4451
|
+
"inputSchema": {
|
|
4452
|
+
"type": "object",
|
|
4453
|
+
"properties": {
|
|
4454
|
+
"path": {"type": "string", "description": "Directory path to list.", "default": "."},
|
|
4455
|
+
"depth": {"type": "integer", "description": "Depth of subdirectory recursion.", "default": 1}
|
|
4456
|
+
}
|
|
4457
|
+
}
|
|
4458
|
+
},
|
|
4459
|
+
{
|
|
4460
|
+
"name": "akash_checkpoint_create",
|
|
4461
|
+
"description": "Creates an instant rollback snapshot before executing large refactors.",
|
|
4462
|
+
"inputSchema": {
|
|
4463
|
+
"type": "object",
|
|
4464
|
+
"properties": {
|
|
4465
|
+
"label": {"type": "string", "description": "Name or tag for this checkpoint.", "default": "manual_checkpoint"}
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
},
|
|
4469
|
+
{
|
|
4470
|
+
"name": "akash_undo",
|
|
4471
|
+
"description": "Reverts workspace files to the last pre-command checkpoint.",
|
|
4472
|
+
"inputSchema": {
|
|
4473
|
+
"type": "object",
|
|
4474
|
+
"properties": {}
|
|
4475
|
+
}
|
|
4476
|
+
},
|
|
4477
|
+
{
|
|
4478
|
+
"name": "akash_scope_details",
|
|
4479
|
+
"description": "Inspects active session permissions, allowed file boundaries, and security rules.",
|
|
4480
|
+
"inputSchema": {
|
|
4481
|
+
"type": "object",
|
|
4482
|
+
"properties": {}
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
]
|
|
4486
|
+
|
|
4487
|
+
while True:
|
|
4488
|
+
line = sys.stdin.readline()
|
|
4489
|
+
if not line:
|
|
4490
|
+
break
|
|
4491
|
+
line = line.strip()
|
|
4492
|
+
if not line:
|
|
4493
|
+
continue
|
|
4494
|
+
try:
|
|
4495
|
+
req = json.loads(line)
|
|
4496
|
+
except Exception:
|
|
4497
|
+
continue
|
|
4498
|
+
|
|
4499
|
+
msg_id = req.get("id")
|
|
4500
|
+
method = req.get("method")
|
|
4501
|
+
params = req.get("params", {})
|
|
4502
|
+
|
|
4503
|
+
if method == "initialize":
|
|
4504
|
+
res = {
|
|
4505
|
+
"jsonrpc": "2.0",
|
|
4506
|
+
"id": msg_id,
|
|
4507
|
+
"result": {
|
|
4508
|
+
"protocolVersion": "2024-11-05",
|
|
4509
|
+
"capabilities": {"tools": {}},
|
|
4510
|
+
"serverInfo": {"name": "akash", "version": __version__}
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
4514
|
+
sys.stdout.flush()
|
|
4515
|
+
elif method == "notifications/initialized":
|
|
4516
|
+
pass
|
|
4517
|
+
elif method == "ping":
|
|
4518
|
+
if msg_id is not None:
|
|
4519
|
+
sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": msg_id, "result": {}}) + "\n")
|
|
4520
|
+
sys.stdout.flush()
|
|
4521
|
+
elif method == "tools/list":
|
|
4522
|
+
res = {
|
|
4523
|
+
"jsonrpc": "2.0",
|
|
4524
|
+
"id": msg_id,
|
|
4525
|
+
"result": {"tools": tools_definitions}
|
|
4526
|
+
}
|
|
4527
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
4528
|
+
sys.stdout.flush()
|
|
4529
|
+
elif method == "tools/call":
|
|
4530
|
+
t_name = params.get("name")
|
|
4531
|
+
t_args = params.get("arguments", {})
|
|
4532
|
+
res_content = ""
|
|
4533
|
+
is_err = False
|
|
4534
|
+
|
|
4535
|
+
if t_name == "akash_exec_command":
|
|
4536
|
+
cmd = t_args.get("command", "")
|
|
4537
|
+
is_safe, sec_reason = _sanitize_agent_command(cmd, scopes=scopes)
|
|
4538
|
+
if not is_safe:
|
|
4539
|
+
res_content = f"[BLOCKED] Security Policy Block: {sec_reason}\nCommand: {cmd}"
|
|
4540
|
+
is_err = True
|
|
4541
|
+
else:
|
|
4542
|
+
if any(k in cmd for k in ["touch", "mkdir", "mv", "cp", "sed", ">", ">>", "python", "npm", "pip"]):
|
|
4543
|
+
_save_undo_checkpoint()
|
|
4544
|
+
import signal
|
|
4545
|
+
try:
|
|
4546
|
+
proc = subprocess.Popen(
|
|
4547
|
+
cmd,
|
|
4548
|
+
shell=True,
|
|
4549
|
+
stdout=subprocess.PIPE,
|
|
4550
|
+
stderr=subprocess.PIPE,
|
|
4551
|
+
stdin=subprocess.DEVNULL,
|
|
4552
|
+
text=True,
|
|
4553
|
+
start_new_session=True,
|
|
4554
|
+
errors="replace"
|
|
4555
|
+
)
|
|
4556
|
+
try:
|
|
4557
|
+
out, err = proc.communicate(timeout=25)
|
|
4558
|
+
returncode = proc.returncode
|
|
4559
|
+
raw_out = (out or "") + (err or "")
|
|
4560
|
+
except subprocess.TimeoutExpired:
|
|
4561
|
+
try:
|
|
4562
|
+
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
|
|
4563
|
+
except Exception:
|
|
4564
|
+
pass
|
|
4565
|
+
raw_out = "[BLOCKED] Command timed out after 25 seconds."
|
|
4566
|
+
returncode = 124
|
|
4567
|
+
except Exception as cmd_err:
|
|
4568
|
+
raw_out = f"[BLOCKED] Command execution error: {cmd_err}"
|
|
4569
|
+
returncode = 1
|
|
4570
|
+
bounded_out = _smart_truncate_output(raw_out)
|
|
4571
|
+
if returncode != 0:
|
|
4572
|
+
res_content = bounded_out or f"Command exited with status code {returncode}"
|
|
4573
|
+
is_err = True
|
|
4574
|
+
else:
|
|
4575
|
+
res_content = bounded_out or "(command completed successfully with no output)"
|
|
4576
|
+
elif t_name == "akash_read_file":
|
|
4577
|
+
res_content, is_err = _handle_tool_read_file(t_args, scopes)
|
|
4578
|
+
elif t_name == "akash_write_file":
|
|
4579
|
+
_save_undo_checkpoint()
|
|
4580
|
+
res_content, is_err = _handle_tool_write_file(t_args, scopes)
|
|
4581
|
+
elif t_name == "akash_list_dir":
|
|
4582
|
+
res_content, is_err = _handle_tool_list_dir(t_args, scopes)
|
|
4583
|
+
elif t_name == "akash_checkpoint_create":
|
|
4584
|
+
label = t_args.get("label", "agent_checkpoint")
|
|
4585
|
+
from .terminal import build_snapshot
|
|
4586
|
+
_, manifest, _ = build_snapshot(label=label)
|
|
4587
|
+
res_content = f"Checkpoint '{label}' created ({len(manifest.get('files', []))} files tracked)"
|
|
4588
|
+
elif t_name == "akash_undo":
|
|
4589
|
+
ok, msg_txt = _restore_undo_checkpoint()
|
|
4590
|
+
res_content = msg_txt
|
|
4591
|
+
is_err = not ok
|
|
4592
|
+
elif t_name == "akash_scope_details":
|
|
4593
|
+
res_content, is_err = _handle_tool_scope_details(scopes, pname, target_pid)
|
|
4594
|
+
else:
|
|
4595
|
+
res_content = f"Tool '{t_name}' not found."
|
|
4596
|
+
is_err = True
|
|
4597
|
+
|
|
4598
|
+
sys.stdout.write(json.dumps({
|
|
4599
|
+
"jsonrpc": "2.0",
|
|
4600
|
+
"id": msg_id,
|
|
4601
|
+
"result": {
|
|
4602
|
+
"content": [{"type": "text", "text": res_content}],
|
|
4603
|
+
"isError": is_err
|
|
4604
|
+
}
|
|
4605
|
+
}) + "\n")
|
|
4606
|
+
sys.stdout.flush()
|
|
4607
|
+
else:
|
|
4608
|
+
if msg_id is not None:
|
|
4609
|
+
sys.stdout.write(json.dumps({
|
|
4610
|
+
"jsonrpc": "2.0",
|
|
4611
|
+
"id": msg_id,
|
|
4612
|
+
"error": {"code": -32601, "message": f"Method '{method}' not found"}
|
|
4613
|
+
}) + "\n")
|
|
4614
|
+
sys.stdout.flush()
|
|
4615
|
+
|
|
4616
|
+
|
|
4617
|
+
@app.command("tunnel")
|
|
4618
|
+
@agent_app.command("tunnel")
|
|
4619
|
+
def cmd_tunnel(
|
|
4620
|
+
url: Optional[str] = typer.Option(None, "--url", "-u", help="Set custom domain or Cloudflare tunnel URL"),
|
|
4621
|
+
reset: bool = typer.Option(False, "--reset", "-r", help="Reset domain back to default akashbox.duckdns.org"),
|
|
4622
|
+
):
|
|
4623
|
+
"""Configure or view custom domain / Cloudflare tunnel for internet mode."""
|
|
4624
|
+
if reset:
|
|
4625
|
+
ConfigManager.delete("api_url")
|
|
4626
|
+
_ok(f"Reset storage and relay URL to default: {_cy(DEFAULT_STORAGE_URL)}")
|
|
4627
|
+
return
|
|
4628
|
+
|
|
4629
|
+
if url:
|
|
4630
|
+
clean = url.strip().rstrip("/")
|
|
4631
|
+
if not clean.startswith(("http://", "https://")):
|
|
4632
|
+
clean = f"https://{clean}"
|
|
4633
|
+
ConfigManager.set("api_url", clean)
|
|
4634
|
+
_ok(f"Configured active gateway domain to: {_cy(clean)}")
|
|
4635
|
+
_info("All remote MCP and API operations will now route through this domain.")
|
|
4636
|
+
return
|
|
4637
|
+
|
|
4638
|
+
cfg = ConfigManager.load()
|
|
4639
|
+
current_url = cfg.get("api_url", DEFAULT_STORAGE_URL)
|
|
4640
|
+
_p()
|
|
4641
|
+
print(f" {_C}◈{_RS} {_W}Akash Gateway Domain Configuration{_RS}")
|
|
4642
|
+
print(f" {_GR}──────────────────────────────────────────────────{_RS}")
|
|
4643
|
+
print(f" {_DM}Active Domain :{_RS} {_cy(current_url)}")
|
|
4644
|
+
print(f" {_DM}Default Relay :{_RS} {_dim(DEFAULT_STORAGE_URL)}")
|
|
4645
|
+
print(f" {_GR}──────────────────────────────────────────────────{_RS}")
|
|
4646
|
+
_p()
|
|
4647
|
+
_info("How to connect your own domain or Cloudflare Tunnel:")
|
|
4648
|
+
print(f" 1. Start Cloudflare Tunnel locally : {_cy('cloudflared tunnel --url http://127.0.0.1:8000')}")
|
|
4649
|
+
print(f" 2. Configure tunnel in akashcli : {_cy('akash tunnel --url https://<your-subdomain>.trycloudflare.com')}")
|
|
4650
|
+
print(f" 3. Reset back to Akashbox relay : {_cy('akash tunnel --reset')}")
|
|
4651
|
+
_p()
|
|
4652
|
+
|
|
4363
4653
|
if __name__ == "__main__":
|
|
4364
4654
|
app()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|