# -*- coding: utf-8 -*- """生成 wwwroot/api/*.dspy 契约端点(10 个)。 统一模板要点(对应 QC 退回 #3/#6): * 第 2 行 debug 必须是 **f-string**,输出真实 params_kw(module-development-spec 要求); * dspy 内禁止 import / print / uuid(禁项审计零命中); * 契约函数由 init.py 注册到 ServerEnv,dspy 直接按名调用; * 显式 return(ahserver 把 dspy 包进 async def,裸表达式返回 None)。 """ import os ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) API_DIR = os.path.join(ROOT, "wwwroot", "api") CONTRACTS = ( ("pbl_agent_designer_run", "Designer Agent 运行(可写,写操作经服务端裁决)"), ("pbl_agent_critic_run", "Critic Agent 运行(零写权限)"), ("pbl_agent_trace_write", "写 Agent 执行轨迹(7 要素,append-only)"), ("pbl_agent_trace_list", "查询 Agent 执行轨迹"), ("pbl_tool_registry_list", "工具注册表查询(13 启用 / 9 禁用)"), ("pbl_tool_registry_save", "工具注册表变更(四类强制审批之一)"), ("pbl_tool_adjudicate", "fail-closed 8 步工具裁决(默认 DENY)"), ("pbl_approval_create", "创建人工审批单(14.2 四类)"), ("pbl_approval_decide", "人工审批裁决(无 Agent 绕过路径)"), ("pbl_approval_list", "审批单列表查询"), ) TEMPLATE = """# {doc} debug(f'{name}.dspy: START params_kw={{dict(params_kw)}}') result = {name}(**dict(params_kw)) debug(f'{name}.dspy: END success={{result.get("success") if isinstance(result, dict) else result}}') return result """ def main(): if not os.path.isdir(API_DIR): os.makedirs(API_DIR, exist_ok=True) written = [] for name, doc in CONTRACTS: path = os.path.join(API_DIR, "%s.dspy" % name) with open(path, "w", encoding="utf-8") as handle: handle.write(TEMPLATE.format(name=name, doc=doc)) written.append(os.path.relpath(path, ROOT)) print("generated %d dspy endpoints:" % len(written)) for item in written: print(" -", item) if __name__ == "__main__": main()