$ cat node-template.py

C

Create Artifact

// Generate a knowledge-base-grounded Artifact (document) from a Drive folder using a generation template, then wait for generation to finish and output the content.

AI
Document
#artifact#document#knowledge-base#generate
template.py
1"""create-artifact — generate a KB-grounded Artifact and wait for the content.23Drives the existing www-emblema Artifact pipeline (template + Knowledge Base ->4grounded, translated, watermarked document) entirely through the gais SDK5(Gais.artifact.create); this node imports no HTTP client and never sees6USER_TOKEN — the lint deny-list blocks requests/httpx/os in template code, so7all privileged artifact IO lives in gais.backends._artifact.89Generation is ASYNCHRONOUS: the create call returns instantly with empty10content while a background task fills it in. ``wait=True`` makes the SDK poll11the generation TASK status until it COMPLETES (return content), FAILS/CANCELS12(raise), or the deadline passes (raise) — so this node blocks like the13video/image creation nodes and hands real content to the next node.1415Outputs ``artifactId`` + ``driveItemId`` as separate ports so a downstream Get16Artifact node can be wired from both (entity ports carry scalar ids, not17objects).18"""1920from __future__ import annotations2122import json23import re24import sys25import traceback26from typing import Any2728from gais import Gais2930_UUID_RE = re.compile(31    r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",32    re.IGNORECASE,33)343536def _normalize_uuid(value: Any, field: str) -> str:37    """Accept a bare UUID or a ``mention://.../<uuid>`` URI; validate as UUID.3839    The id is interpolated into the Artifact API path by the backend, so a40    value from an upstream node (which may emit ``mention://drive_folder/<uuid>``41    from the picker) is stripped to its trailing segment and UUID-checked here42    — a non-UUID can't reach the URL.43    """44    if not isinstance(value, str):45        raise ValueError(f"{field} must be a string, got {type(value).__name__}")46    s = value.strip()47    if "://" in s:48        s = s.rsplit("/", 1)[-1]49    if not _UUID_RE.match(s):50        raise ValueError(f"{field} is not a valid UUID: {value!r}")51    return s525354def process(inputs: dict[str, Any]) -> dict[str, Any]:55    drive_item_id = _normalize_uuid(inputs.get("driveItemId"), "driveItemId")56    template_id = _normalize_uuid(inputs.get("templateId"), "templateId")57    language = inputs.get("language") or "italian"58    formality = inputs.get("formality") or "formal"59    name = inputs.get("name") or None60    try:61        max_wait = float(inputs.get("maxWaitSeconds") or 300)62    except (TypeError, ValueError):63        max_wait = 300.06465    print(66        f"[create-artifact] kb={drive_item_id} template={template_id} "67        f"lang={language} wait<={max_wait:.0f}s",68        file=sys.stderr,69    )7071    result = Gais.artifact.create(72        drive_item_id=drive_item_id,73        template_id=template_id,74        name=name,75        config={"language": language, "langFormality": formality},76        wait=True,77        timeout=max_wait,78    )79    meta = result.metadata8081    print(82        f"[create-artifact] done id={meta.get('artifactId')} "83        f"status={meta.get('status')} chars={len(result.text or '')}",84        file=sys.stderr,85    )8687    return {88        "content": result.text or "",89        "artifactId": meta.get("artifactId", ""),90        "status": meta.get("status", ""),91        "format": meta.get("format", "markdown"),92    }939495def main() -> None:96    try:97        envelope = json.loads(sys.stdin.read() or "{}")98        if not isinstance(envelope, dict):99            envelope = {}100        inputs = envelope.get("inputs", {}) or {}101        json.dump(process(inputs), sys.stdout)102    except Exception as e:103        print(104            json.dumps({105                "error": str(e),106                "errorType": type(e).__name__,107                "traceback": traceback.format_exc(),108            }),109            file=sys.stderr,110        )111        sys.exit(1)112113114if __name__ == "__main__":115    main()116

$ git log --oneline

v1.2.0
HEAD
2026-06-12
v1.1.02026-06-12