janction-render 0.4.63__tar.gz → 0.4.64__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.
- {janction_render-0.4.63 → janction_render-0.4.64}/PKG-INFO +1 -1
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/__init__.py +1 -1
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/mcp_common.py +61 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/mcp_server.py +6 -38
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/PKG-INFO +1 -1
- {janction_render-0.4.63 → janction_render-0.4.64}/pyproject.toml +1 -1
- {janction_render-0.4.63 → janction_render-0.4.64}/LICENSE +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/README.md +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/brief.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/cli.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/client.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/hookup.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/links.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/mcp_app.html +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/prompts.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render/tooldocs.py +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/SOURCES.txt +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/dependency_links.txt +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/entry_points.txt +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/requires.txt +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/top_level.txt +0 -0
- {janction_render-0.4.63 → janction_render-0.4.64}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: janction-render
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.64
|
|
4
4
|
Summary: Cloud GPU rendering for Blender scenes and 3D models (GLB, FBX, USD, OBJ, STL), built for AI agents: MCP server (remote + stdio), HTTP API and CLI. Product shots, 360-degree turntables, animations and stills; preview in seconds with a critic; no local Blender or GPU. A 100 JPY welcome credit for a new key (one per network every 30 days) and 400 JPY more for saving a card that is not charged, then 0.1 JPY per GPU-second.
|
|
5
5
|
Author-email: "JasmyLab Inc." <contact@jasmylab.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -60,6 +60,67 @@ def job_params(environment: str, environment_strength: float, environment_visibl
|
|
|
60
60
|
return out
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
# ------------------------------------------------------------------ 見積もりとシーンの読み取りの返事(両方の道具で同じ)
|
|
64
|
+
|
|
65
|
+
def estimate_body(kind: str, scene_id: str, frames: str, frame_start: int, frame_end: int, width: int, height: int, samples: int,
|
|
66
|
+
cameras: Any, preset: str) -> tuple[dict[str, Any], bool]:
|
|
67
|
+
"""render_estimate の引数から受付への本文を作る。戻り値は (本文, シーンの読み取りが先に要るか)。
|
|
68
|
+
preset='animation' でコマの指定が無ければ、呼ぶ側が scene_info を済ませてから見積もる。"""
|
|
69
|
+
from .client import parse_frames
|
|
70
|
+
body: dict[str, Any] = {"kind": kind, "width": width, "height": height, "samples": samples}
|
|
71
|
+
if scene_id:
|
|
72
|
+
body["scene_id"] = scene_id
|
|
73
|
+
if kind == "preview":
|
|
74
|
+
body["frames"] = parse_frames(frames) if (frames or not preset) else None
|
|
75
|
+
else:
|
|
76
|
+
body.update({"frame_start": frame_start, "frame_end": frame_end})
|
|
77
|
+
if cameras:
|
|
78
|
+
body["cameras"] = list(cameras)
|
|
79
|
+
if kind != "preview":
|
|
80
|
+
body.pop("frame_end", None)
|
|
81
|
+
needs_info = bool(preset == "animation" and scene_id
|
|
82
|
+
and (body.get("frames") is None if kind == "preview" else frame_end <= frame_start))
|
|
83
|
+
body = {k: v for k, v in with_preset(body, preset, kind).items() if v is not None}
|
|
84
|
+
return body, needs_info
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def estimate_next(est: dict[str, Any]) -> str:
|
|
88
|
+
"""見積もりの返事の next(エージェントへの次の一手)。上限の言い方は docs/60 BRAND-02 に合わせる。"""
|
|
89
|
+
q = est.get("quota") or {}
|
|
90
|
+
cost = est.get("cost") or {}
|
|
91
|
+
if q and q.get("fits_size") is False:
|
|
92
|
+
return (f"too big for one job: at most {q.get('max_frames_per_job')} frames per job part (1920x1080 on free time, 3840x2160 "
|
|
93
|
+
"on prepaid credit); the service splits longer instructions into parts under one job id, or lower the size")
|
|
94
|
+
if q and not q.get("fits_today", True) and q.get("mode") == "free_allowance":
|
|
95
|
+
# 有料モード: 無料枠を超えた分は残高から(10/8)。額と残高を言ってから
|
|
96
|
+
return (f"this goes past the free GPU time left: about {cost.get('estimated_yen')} JPY would be charged from credit "
|
|
97
|
+
f"(balance {cost.get('balance_yen')} JPY). Tell the user the time and the price and ask before "
|
|
98
|
+
"render_final; a smaller job (fewer frames, lower resolution or samples) may stay free")
|
|
99
|
+
if q and not q.get("fits_today", True):
|
|
100
|
+
return ("this does not fit today's remaining free GPU time; propose fewer frames, lower resolution or samples, "
|
|
101
|
+
"or wait until resets_at")
|
|
102
|
+
return "tell the user the estimate and ask before calling render_final"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def scene_info_reply(j: dict[str, Any], assets_param: str) -> dict[str, Any]:
|
|
106
|
+
"""scene_info の返事(info に scene_id・エンジンの注意・警告・欠けたファイルの案内・次の一手)。assets_param は素材の渡し方の文
|
|
107
|
+
(remote: 'asset_urls'、stdio: 'assets=[...]')。"""
|
|
108
|
+
from .brief import scene_next, trim
|
|
109
|
+
info = dict(j.get("info") or {})
|
|
110
|
+
info["scene_id"] = j.get("scene_id")
|
|
111
|
+
if info.get("engine") and info["engine"] != "CYCLES":
|
|
112
|
+
info["engine_note"] = "JANCTION renders with CYCLES; the scene's engine setting is not used"
|
|
113
|
+
if j.get("warnings"):
|
|
114
|
+
info["blender_warnings"] = j["warnings"]
|
|
115
|
+
if info.get("missing_files"):
|
|
116
|
+
info["note"] = (f"missing_files will render pink/black; send them with {assets_param} (kept next to the scene), "
|
|
117
|
+
"pack them into the .blend (File > External Data > Pack) or fix the paths")
|
|
118
|
+
if isinstance(info.get("object_names"), list):
|
|
119
|
+
info["object_names"] = trim(info["object_names"], 30)
|
|
120
|
+
info.update(scene_next(info)) # 次の一手: シーンの縦横比に合わせた試し描き(10/9)
|
|
121
|
+
return info
|
|
122
|
+
|
|
123
|
+
|
|
63
124
|
# ------------------------------------------------------------------ 引数の説明(道具の description の末尾に足す)
|
|
64
125
|
|
|
65
126
|
_ENGINE_DOC = (" engine: '' or 'cycles' (path tracing, the default) | 'eevee' (Blender's real-time rasterizer: about half the "
|
|
@@ -29,7 +29,7 @@ except ImportError: # mcp 1.x
|
|
|
29
29
|
from mcp.server.fastmcp import FastMCP as MCPServer, Image # type: ignore
|
|
30
30
|
from mcp.types import ToolAnnotations
|
|
31
31
|
|
|
32
|
-
from janction_render.brief import plan_fields, review_reply,
|
|
32
|
+
from janction_render.brief import plan_fields, review_reply, welcome_billing
|
|
33
33
|
from janction_render.brief import brief as _brief, estimate_brief, final_body_after_preview, followup_after_preview, \
|
|
34
34
|
next_after_preview, trim, PRESENT_FIRST, preview_presentation, turntable_estimate
|
|
35
35
|
from janction_render.client import Client, ClientError, parse_frames
|
|
@@ -390,18 +390,7 @@ def scene_info(scene_path: Annotated[str, D("scene_path", "")] = "",
|
|
|
390
390
|
b["hint"] = (_gated_hint(j, "scene_info(scene_id)") or "still queued (a GPU worker may be busy); call scene_info again in a moment") \
|
|
391
391
|
if j["status"] in ("queued", "running") else "fix the scene and try again"
|
|
392
392
|
return _j(b)
|
|
393
|
-
info =
|
|
394
|
-
info["scene_id"] = j["scene_id"]
|
|
395
|
-
if info.get("engine") and info["engine"] != "CYCLES":
|
|
396
|
-
info["engine_note"] = "JANCTION renders with CYCLES; the scene's engine setting is not used"
|
|
397
|
-
if j.get("warnings"):
|
|
398
|
-
info["blender_warnings"] = j["warnings"]
|
|
399
|
-
if info.get("missing_files"):
|
|
400
|
-
info["note"] = ("missing_files will render pink/black; send them with assets=[...] (kept next to the .blend), "
|
|
401
|
-
"pack them into the .blend (File > External Data > Pack) or fix the paths")
|
|
402
|
-
if isinstance(info.get("object_names"), list):
|
|
403
|
-
info["object_names"] = trim(info["object_names"], 30)
|
|
404
|
-
info.update(scene_next(info)) # 次の一手: シーンの縦横比に合わせた試し描き(10/9)
|
|
393
|
+
info = mcp_common.scene_info_reply(j, "assets=[...]")
|
|
405
394
|
return _j(_attach_upload_notes(info))
|
|
406
395
|
|
|
407
396
|
|
|
@@ -579,37 +568,16 @@ def render_estimate(scene_id: Annotated[str, D("scene_id", "")] = "",
|
|
|
579
568
|
c = _client()
|
|
580
569
|
try:
|
|
581
570
|
preset = _preset_of(preset)
|
|
582
|
-
params
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
else:
|
|
586
|
-
params.update({"frame_start": frame_start, "frame_end": frame_end})
|
|
587
|
-
if cameras:
|
|
588
|
-
params["cameras"] = list(cameras)
|
|
589
|
-
if kind != "preview":
|
|
590
|
-
params.pop("frame_end", None)
|
|
591
|
-
if preset == "animation" and scene_id and (params.get("frames") is None if kind == "preview" else frame_end <= frame_start):
|
|
571
|
+
params, needs_info = mcp_common.estimate_body(kind, scene_id, frames, frame_start, frame_end, width, height, samples, cameras, preset)
|
|
572
|
+
params.pop("scene_id", None)
|
|
573
|
+
if needs_info:
|
|
592
574
|
_ensure_scene_info(c, scene_id)
|
|
593
|
-
params = {k: v for k, v in _with_preset(params, preset, kind).items() if v is not None}
|
|
594
575
|
est = c.estimate(scene_id or None, **params)
|
|
595
576
|
except (ClientError, ValueError) as exc:
|
|
596
577
|
return _j(_fail(exc))
|
|
597
578
|
out = estimate_brief(est) or {}
|
|
598
579
|
out["kind"] = kind
|
|
599
|
-
|
|
600
|
-
cost = est.get("cost") or {}
|
|
601
|
-
if q and q.get("fits_size") is False:
|
|
602
|
-
out["next"] = f"too big for one job (max {q.get('max_frames_per_job')} frames and 1920x1080 per job); split it"
|
|
603
|
-
elif q and not q.get("fits_today", True) and q.get("mode") == "free_allowance":
|
|
604
|
-
# 有料モード(10/8〜): 無料枠を超えた分は残高から。額と残高を言ってから
|
|
605
|
-
out["next"] = (f"this goes past the free GPU time left: about {cost.get('estimated_yen')} JPY would be charged from "
|
|
606
|
-
f"credit (balance {cost.get('balance_yen')} JPY). Tell the user the time and the price and ask before "
|
|
607
|
-
"render_final; a smaller job (fewer frames, lower resolution or samples) may stay free")
|
|
608
|
-
elif q and not q.get("fits_today", True):
|
|
609
|
-
out["next"] = ("this does not fit today's remaining free GPU time; propose fewer frames, lower resolution or "
|
|
610
|
-
"samples, or wait until resets_at")
|
|
611
|
-
else:
|
|
612
|
-
out["next"] = "tell the user the estimate and ask before calling render_final"
|
|
580
|
+
out["next"] = mcp_common.estimate_next(est)
|
|
613
581
|
return _j(out)
|
|
614
582
|
|
|
615
583
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: janction-render
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.64
|
|
4
4
|
Summary: Cloud GPU rendering for Blender scenes and 3D models (GLB, FBX, USD, OBJ, STL), built for AI agents: MCP server (remote + stdio), HTTP API and CLI. Product shots, 360-degree turntables, animations and stills; preview in seconds with a critic; no local Blender or GPU. A 100 JPY welcome credit for a new key (one per network every 30 days) and 400 JPY more for saving a card that is not charged, then 0.1 JPY per GPU-second.
|
|
5
5
|
Author-email: "JasmyLab Inc." <contact@jasmylab.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "janction-render"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.64"
|
|
8
8
|
description = "Cloud GPU rendering for Blender scenes and 3D models (GLB, FBX, USD, OBJ, STL), built for AI agents: MCP server (remote + stdio), HTTP API and CLI. Product shots, 360-degree turntables, animations and stills; preview in seconds with a critic; no local Blender or GPU. A 100 JPY welcome credit for a new key (one per network every 30 days) and 400 JPY more for saving a card that is not charged, then 0.1 JPY per GPU-second."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
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
|
{janction_render-0.4.63 → janction_render-0.4.64}/janction_render.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|