nemo-platform-plugin 0.1.0__py3-none-any.whl

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.
Files changed (1224) hide show
  1. nemo_platform/__init__.py +117 -0
  2. nemo_platform/_base_client.py +2146 -0
  3. nemo_platform/_client.py +1200 -0
  4. nemo_platform/_compat.py +241 -0
  5. nemo_platform/_constants.py +29 -0
  6. nemo_platform/_decoders/jsonl.py +138 -0
  7. nemo_platform/_exceptions.py +123 -0
  8. nemo_platform/_files.py +188 -0
  9. nemo_platform/_models.py +967 -0
  10. nemo_platform/_qs.py +164 -0
  11. nemo_platform/_resource.py +58 -0
  12. nemo_platform/_response.py +872 -0
  13. nemo_platform/_streaming.py +391 -0
  14. nemo_platform/_types.py +288 -0
  15. nemo_platform/_utils/__init__.py +79 -0
  16. nemo_platform/_utils/_compat.py +60 -0
  17. nemo_platform/_utils/_datetime_parse.py +151 -0
  18. nemo_platform/_utils/_json.py +50 -0
  19. nemo_platform/_utils/_logs.py +40 -0
  20. nemo_platform/_utils/_path.py +142 -0
  21. nemo_platform/_utils/_proxy.py +80 -0
  22. nemo_platform/_utils/_reflection.py +57 -0
  23. nemo_platform/_utils/_resources_proxy.py +39 -0
  24. nemo_platform/_utils/_streams.py +27 -0
  25. nemo_platform/_utils/_sync.py +73 -0
  26. nemo_platform/_utils/_transform.py +472 -0
  27. nemo_platform/_utils/_typing.py +171 -0
  28. nemo_platform/_utils/_utils.py +448 -0
  29. nemo_platform/_version.py +21 -0
  30. nemo_platform/auth/__init__.py +15 -0
  31. nemo_platform/auth/device_flow.py +303 -0
  32. nemo_platform/auth/helpers.py +211 -0
  33. nemo_platform/auth/token_provider.py +239 -0
  34. nemo_platform/beta/evaluator/__init__.py +120 -0
  35. nemo_platform/beta/evaluator/agent_inference.py +360 -0
  36. nemo_platform/beta/evaluator/constants.py +4 -0
  37. nemo_platform/beta/evaluator/dataset_schemas/common.py +177 -0
  38. nemo_platform/beta/evaluator/dataset_schemas/compatibility.py +353 -0
  39. nemo_platform/beta/evaluator/dataset_schemas/templates.py +389 -0
  40. nemo_platform/beta/evaluator/datasets/__init__.py +28 -0
  41. nemo_platform/beta/evaluator/datasets/loader.py +415 -0
  42. nemo_platform/beta/evaluator/enums.py +64 -0
  43. nemo_platform/beta/evaluator/execution/_protocols.py +20 -0
  44. nemo_platform/beta/evaluator/execution/backends/base.py +86 -0
  45. nemo_platform/beta/evaluator/execution/backends/local/backend.py +132 -0
  46. nemo_platform/beta/evaluator/execution/benchmark_execution.py +666 -0
  47. nemo_platform/beta/evaluator/execution/config.py +64 -0
  48. nemo_platform/beta/evaluator/execution/evaluator.py +289 -0
  49. nemo_platform/beta/evaluator/execution/job_poll.py +98 -0
  50. nemo_platform/beta/evaluator/execution/metric_execution.py +878 -0
  51. nemo_platform/beta/evaluator/execution/pipeline.py +64 -0
  52. nemo_platform/beta/evaluator/execution/runs.py +143 -0
  53. nemo_platform/beta/evaluator/execution/scoring.py +224 -0
  54. nemo_platform/beta/evaluator/execution/utils.py +116 -0
  55. nemo_platform/beta/evaluator/execution/values.py +53 -0
  56. nemo_platform/beta/evaluator/inference.py +456 -0
  57. nemo_platform/beta/evaluator/metrics/aggregation.py +451 -0
  58. nemo_platform/beta/evaluator/metrics/bleu.py +94 -0
  59. nemo_platform/beta/evaluator/metrics/exact_match.py +52 -0
  60. nemo_platform/beta/evaluator/metrics/f1.py +50 -0
  61. nemo_platform/beta/evaluator/metrics/hooks.py +41 -0
  62. nemo_platform/beta/evaluator/metrics/llm_judge.py +392 -0
  63. nemo_platform/beta/evaluator/metrics/number_check.py +95 -0
  64. nemo_platform/beta/evaluator/metrics/protocol.py +241 -0
  65. nemo_platform/beta/evaluator/metrics/ragas/__init__.py +41 -0
  66. nemo_platform/beta/evaluator/metrics/ragas/base.py +521 -0
  67. nemo_platform/beta/evaluator/metrics/ragas/git_patch.py +36 -0
  68. nemo_platform/beta/evaluator/metrics/ragas/imports.py +192 -0
  69. nemo_platform/beta/evaluator/metrics/ragas/metrics.py +183 -0
  70. nemo_platform/beta/evaluator/metrics/remote.py +250 -0
  71. nemo_platform/beta/evaluator/metrics/rouge.py +71 -0
  72. nemo_platform/beta/evaluator/metrics/string_check.py +69 -0
  73. nemo_platform/beta/evaluator/metrics/template_rendering.py +141 -0
  74. nemo_platform/beta/evaluator/metrics/tool_calling.py +173 -0
  75. nemo_platform/beta/evaluator/metrics/types.py +62 -0
  76. nemo_platform/beta/evaluator/metrics/utils.py +54 -0
  77. nemo_platform/beta/evaluator/resilience/api.py +142 -0
  78. nemo_platform/beta/evaluator/resilience/classifier.py +142 -0
  79. nemo_platform/beta/evaluator/resilience/config.py +69 -0
  80. nemo_platform/beta/evaluator/resilience/errors.py +117 -0
  81. nemo_platform/beta/evaluator/resilience/policy.py +50 -0
  82. nemo_platform/beta/evaluator/resilience/scheduler.py +459 -0
  83. nemo_platform/beta/evaluator/resilience/types.py +93 -0
  84. nemo_platform/beta/evaluator/structured_output.py +184 -0
  85. nemo_platform/beta/evaluator/templates.py +115 -0
  86. nemo_platform/beta/evaluator/values/__init__.py +162 -0
  87. nemo_platform/beta/evaluator/values/agents.py +84 -0
  88. nemo_platform/beta/evaluator/values/common.py +28 -0
  89. nemo_platform/beta/evaluator/values/dataset_schemas.py +112 -0
  90. nemo_platform/beta/evaluator/values/datasets.py +28 -0
  91. nemo_platform/beta/evaluator/values/metrics.py +587 -0
  92. nemo_platform/beta/evaluator/values/models.py +157 -0
  93. nemo_platform/beta/evaluator/values/multi_metric_results.py +359 -0
  94. nemo_platform/beta/evaluator/values/params.py +109 -0
  95. nemo_platform/beta/evaluator/values/results.py +699 -0
  96. nemo_platform/beta/evaluator/values/scores.py +300 -0
  97. nemo_platform/beta/safe_synthesizer/__init__.py +4 -0
  98. nemo_platform/beta/safe_synthesizer/config.py +29 -0
  99. nemo_platform/beta/safe_synthesizer/job.py +309 -0
  100. nemo_platform/beta/safe_synthesizer/job_builder.py +355 -0
  101. nemo_platform/cli/__init__.py +4 -0
  102. nemo_platform/cli/app.py +321 -0
  103. nemo_platform/cli/commands/__init__.py +15 -0
  104. nemo_platform/cli/commands/api/__init__.py +114 -0
  105. nemo_platform/cli/commands/api/adapters.py +384 -0
  106. nemo_platform/cli/commands/api/files/__init__.py +237 -0
  107. nemo_platform/cli/commands/api/files/filesets.py +386 -0
  108. nemo_platform/cli/commands/api/files/otlp/__init__.py +12 -0
  109. nemo_platform/cli/commands/api/files/otlp/logs.py +116 -0
  110. nemo_platform/cli/commands/api/guardrail/__init__.py +270 -0
  111. nemo_platform/cli/commands/api/guardrail/configs.py +311 -0
  112. nemo_platform/cli/commands/api/iam/__init__.py +12 -0
  113. nemo_platform/cli/commands/api/iam/role_bindings.py +264 -0
  114. nemo_platform/cli/commands/api/inference/__init__.py +76 -0
  115. nemo_platform/cli/commands/api/inference/deployment_configs/__init__.py +370 -0
  116. nemo_platform/cli/commands/api/inference/deployment_configs/versions.py +132 -0
  117. nemo_platform/cli/commands/api/inference/deployments/__init__.py +565 -0
  118. nemo_platform/cli/commands/api/inference/deployments/versions.py +141 -0
  119. nemo_platform/cli/commands/api/inference/gateway/__init__.py +14 -0
  120. nemo_platform/cli/commands/api/inference/gateway/model.py +324 -0
  121. nemo_platform/cli/commands/api/inference/gateway/openai/__init__.py +12 -0
  122. nemo_platform/cli/commands/api/inference/gateway/openai/v1/__init__.py +12 -0
  123. nemo_platform/cli/commands/api/inference/gateway/openai/v1/models.py +106 -0
  124. nemo_platform/cli/commands/api/inference/gateway/provider.py +327 -0
  125. nemo_platform/cli/commands/api/inference/models.py +106 -0
  126. nemo_platform/cli/commands/api/inference/providers.py +612 -0
  127. nemo_platform/cli/commands/api/inference/virtual_models.py +412 -0
  128. nemo_platform/cli/commands/api/intake/__init__.py +18 -0
  129. nemo_platform/cli/commands/api/intake/apps/__init__.py +326 -0
  130. nemo_platform/cli/commands/api/intake/apps/tasks.py +340 -0
  131. nemo_platform/cli/commands/api/intake/entries/__init__.py +445 -0
  132. nemo_platform/cli/commands/api/intake/entries/events.py +118 -0
  133. nemo_platform/cli/commands/api/intake/evaluator_results.py +267 -0
  134. nemo_platform/cli/commands/api/intake/exports/__init__.py +63 -0
  135. nemo_platform/cli/commands/api/intake/exports/jobs.py +245 -0
  136. nemo_platform/cli/commands/api/intake/ingest/__init__.py +14 -0
  137. nemo_platform/cli/commands/api/intake/ingest/atif.py +115 -0
  138. nemo_platform/cli/commands/api/intake/ingest/chat_completions.py +125 -0
  139. nemo_platform/cli/commands/api/intake/ingest/otlp/__init__.py +12 -0
  140. nemo_platform/cli/commands/api/intake/ingest/otlp/v1/__init__.py +12 -0
  141. nemo_platform/cli/commands/api/intake/ingest/otlp/v1/traces.py +72 -0
  142. nemo_platform/cli/commands/api/intake/spans/__init__.py +202 -0
  143. nemo_platform/cli/commands/api/intake/spans/evaluator_results.py +65 -0
  144. nemo_platform/cli/commands/api/intake/traces.py +183 -0
  145. nemo_platform/cli/commands/api/jobs/__init__.py +576 -0
  146. nemo_platform/cli/commands/api/jobs/results.py +211 -0
  147. nemo_platform/cli/commands/api/jobs/steps.py +243 -0
  148. nemo_platform/cli/commands/api/jobs/tasks.py +210 -0
  149. nemo_platform/cli/commands/api/members.py +304 -0
  150. nemo_platform/cli/commands/api/models/__init__.py +555 -0
  151. nemo_platform/cli/commands/api/models/adapters.py +261 -0
  152. nemo_platform/cli/commands/api/projects.py +332 -0
  153. nemo_platform/cli/commands/api/safe_synthesizer/__init__.py +12 -0
  154. nemo_platform/cli/commands/api/safe_synthesizer/jobs/__init__.py +417 -0
  155. nemo_platform/cli/commands/api/safe_synthesizer/jobs/results.py +211 -0
  156. nemo_platform/cli/commands/api/secrets/__init__.py +315 -0
  157. nemo_platform/cli/commands/api/secrets/admin.py +44 -0
  158. nemo_platform/cli/commands/api/workspaces.py +339 -0
  159. nemo_platform/cli/commands/auth.py +803 -0
  160. nemo_platform/cli/commands/config.py +308 -0
  161. nemo_platform/cli/commands/docs.py +277 -0
  162. nemo_platform/cli/commands/manifest_registry.py +180 -0
  163. nemo_platform/cli/commands/plugins.py +87 -0
  164. nemo_platform/cli/commands/quickstart/__init__.py +15 -0
  165. nemo_platform/cli/commands/quickstart/cli.py +1178 -0
  166. nemo_platform/cli/commands/services/_process.py +472 -0
  167. nemo_platform/cli/commands/services/cli.py +694 -0
  168. nemo_platform/cli/commands/setup.py +1947 -0
  169. nemo_platform/cli/commands/skills/agents/claude.py +29 -0
  170. nemo_platform/cli/commands/skills/agents/codex.py +32 -0
  171. nemo_platform/cli/commands/skills/agents/cursor.py +18 -0
  172. nemo_platform/cli/commands/skills/agents/opencode.py +20 -0
  173. nemo_platform/cli/commands/skills/base.py +53 -0
  174. nemo_platform/cli/commands/skills/cli.py +313 -0
  175. nemo_platform/cli/commands/skills/installer.py +51 -0
  176. nemo_platform/cli/commands/skills/registry.py +396 -0
  177. nemo_platform/cli/commands/use_cases/__init__.py +15 -0
  178. nemo_platform/cli/commands/use_cases/agent.py +245 -0
  179. nemo_platform/cli/commands/use_cases/chat.py +965 -0
  180. nemo_platform/cli/commands/use_cases/wait.py +151 -0
  181. nemo_platform/cli/core/__init__.py +8 -0
  182. nemo_platform/cli/core/agent_helpers.py +84 -0
  183. nemo_platform/cli/core/api.py +160 -0
  184. nemo_platform/cli/core/autocomplete.py +63 -0
  185. nemo_platform/cli/core/code_generator.py +306 -0
  186. nemo_platform/cli/core/context.py +179 -0
  187. nemo_platform/cli/core/errors.py +349 -0
  188. nemo_platform/cli/core/formatters.py +718 -0
  189. nemo_platform/cli/core/help_formatter.py +868 -0
  190. nemo_platform/cli/core/lazy_load.py +187 -0
  191. nemo_platform/cli/core/logging.py +24 -0
  192. nemo_platform/cli/core/pagination.py +255 -0
  193. nemo_platform/cli/core/stdin_utils.py +233 -0
  194. nemo_platform/cli/core/streaming.py +30 -0
  195. nemo_platform/cli/core/table_config.py +302 -0
  196. nemo_platform/cli/core/timestamp_formatter.py +127 -0
  197. nemo_platform/cli/core/types.py +112 -0
  198. nemo_platform/cli/core/waiters.py +339 -0
  199. nemo_platform/cli/manifest.py +108 -0
  200. nemo_platform/client/__init__.py +15 -0
  201. nemo_platform/client/factory.py +597 -0
  202. nemo_platform/config/README.md +168 -0
  203. nemo_platform/config/__init__.py +23 -0
  204. nemo_platform/config/config.py +538 -0
  205. nemo_platform/config/models.py +377 -0
  206. nemo_platform/config/types.py +7 -0
  207. nemo_platform/filesets/__init__.py +19 -0
  208. nemo_platform/filesets/filesystem/callbacks.py +229 -0
  209. nemo_platform/filesets/filesystem/filesystem.py +940 -0
  210. nemo_platform/filesets/resources.py +1120 -0
  211. nemo_platform/lib/.keep +4 -0
  212. nemo_platform/models/__init__.py +14 -0
  213. nemo_platform/models/resources.py +836 -0
  214. nemo_platform/pagination.py +149 -0
  215. nemo_platform/py.typed +0 -0
  216. nemo_platform/quickstart/__init__.py +99 -0
  217. nemo_platform/quickstart/cluster.py +198 -0
  218. nemo_platform/quickstart/config.py +402 -0
  219. nemo_platform/quickstart/container.py +758 -0
  220. nemo_platform/quickstart/gpu_config.py +111 -0
  221. nemo_platform/quickstart/platform_config.py +82 -0
  222. nemo_platform/quickstart/preflight.py +451 -0
  223. nemo_platform/quickstart/prompts.py +426 -0
  224. nemo_platform/quickstart/storage.py +90 -0
  225. nemo_platform/quickstart/validators.py +268 -0
  226. nemo_platform/resources/__init__.py +16 -0
  227. nemo_platform/resources/adapters/__init__.py +34 -0
  228. nemo_platform/resources/adapters/adapters.py +704 -0
  229. nemo_platform/resources/adapters/api.md +15 -0
  230. nemo_platform/resources/audit/__init__.py +16 -0
  231. nemo_platform/resources/entities/__init__.py +34 -0
  232. nemo_platform/resources/entities/api.md +16 -0
  233. nemo_platform/resources/entities/entities.py +1014 -0
  234. nemo_platform/resources/evaluation/__init__.py +118 -0
  235. nemo_platform/resources/evaluation/api.md +303 -0
  236. nemo_platform/resources/evaluation/benchmark_job_results.py +541 -0
  237. nemo_platform/resources/evaluation/benchmark_jobs/__init__.py +48 -0
  238. nemo_platform/resources/evaluation/benchmark_jobs/benchmark_jobs.py +900 -0
  239. nemo_platform/resources/evaluation/benchmark_jobs/results/__init__.py +76 -0
  240. nemo_platform/resources/evaluation/benchmark_jobs/results/aggregate_scores.py +197 -0
  241. nemo_platform/resources/evaluation/benchmark_jobs/results/artifacts.py +206 -0
  242. nemo_platform/resources/evaluation/benchmark_jobs/results/results.py +516 -0
  243. nemo_platform/resources/evaluation/benchmark_jobs/results/row_scores.py +213 -0
  244. nemo_platform/resources/evaluation/benchmarks.py +690 -0
  245. nemo_platform/resources/evaluation/evaluation.py +277 -0
  246. nemo_platform/resources/evaluation/metric_job_results.py +533 -0
  247. nemo_platform/resources/evaluation/metric_jobs/__init__.py +48 -0
  248. nemo_platform/resources/evaluation/metric_jobs/metric_jobs.py +888 -0
  249. nemo_platform/resources/evaluation/metric_jobs/results/__init__.py +76 -0
  250. nemo_platform/resources/evaluation/metric_jobs/results/aggregate_scores.py +197 -0
  251. nemo_platform/resources/evaluation/metric_jobs/results/artifacts.py +206 -0
  252. nemo_platform/resources/evaluation/metric_jobs/results/results.py +512 -0
  253. nemo_platform/resources/evaluation/metric_jobs/results/row_scores.py +213 -0
  254. nemo_platform/resources/evaluation/metrics.py +3495 -0
  255. nemo_platform/resources/files/__init__.py +62 -0
  256. nemo_platform/resources/files/api.md +65 -0
  257. nemo_platform/resources/files/files.py +683 -0
  258. nemo_platform/resources/files/filesets.py +783 -0
  259. nemo_platform/resources/files/otlp/__init__.py +48 -0
  260. nemo_platform/resources/files/otlp/logs.py +337 -0
  261. nemo_platform/resources/files/otlp/otlp.py +117 -0
  262. nemo_platform/resources/guardrail/__init__.py +48 -0
  263. nemo_platform/resources/guardrail/api.md +116 -0
  264. nemo_platform/resources/guardrail/configs.py +679 -0
  265. nemo_platform/resources/guardrail/guardrail.py +463 -0
  266. nemo_platform/resources/iam/__init__.py +48 -0
  267. nemo_platform/resources/iam/api.md +22 -0
  268. nemo_platform/resources/iam/iam.py +117 -0
  269. nemo_platform/resources/iam/role_bindings.py +537 -0
  270. nemo_platform/resources/inference/__init__.py +118 -0
  271. nemo_platform/resources/inference/api.md +224 -0
  272. nemo_platform/resources/inference/deployment_configs/__init__.py +48 -0
  273. nemo_platform/resources/inference/deployment_configs/deployment_configs.py +756 -0
  274. nemo_platform/resources/inference/deployment_configs/versions.py +418 -0
  275. nemo_platform/resources/inference/deployments/__init__.py +48 -0
  276. nemo_platform/resources/inference/deployments/deployments.py +1017 -0
  277. nemo_platform/resources/inference/deployments/versions.py +434 -0
  278. nemo_platform/resources/inference/gateway/__init__.py +76 -0
  279. nemo_platform/resources/inference/gateway/gateway.py +181 -0
  280. nemo_platform/resources/inference/gateway/model.py +708 -0
  281. nemo_platform/resources/inference/gateway/openai/__init__.py +48 -0
  282. nemo_platform/resources/inference/gateway/openai/openai.py +700 -0
  283. nemo_platform/resources/inference/gateway/openai/v1/__init__.py +48 -0
  284. nemo_platform/resources/inference/gateway/openai/v1/models.py +290 -0
  285. nemo_platform/resources/inference/gateway/openai/v1/v1.py +117 -0
  286. nemo_platform/resources/inference/gateway/provider.py +749 -0
  287. nemo_platform/resources/inference/inference.py +277 -0
  288. nemo_platform/resources/inference/models.py +290 -0
  289. nemo_platform/resources/inference/providers.py +1049 -0
  290. nemo_platform/resources/inference/virtual_models.py +846 -0
  291. nemo_platform/resources/intake/__init__.py +132 -0
  292. nemo_platform/resources/intake/api.md +268 -0
  293. nemo_platform/resources/intake/apps/__init__.py +48 -0
  294. nemo_platform/resources/intake/apps/apps.py +718 -0
  295. nemo_platform/resources/intake/apps/tasks.py +731 -0
  296. nemo_platform/resources/intake/entries/__init__.py +48 -0
  297. nemo_platform/resources/intake/entries/entries.py +855 -0
  298. nemo_platform/resources/intake/entries/events.py +320 -0
  299. nemo_platform/resources/intake/evaluator_results.py +512 -0
  300. nemo_platform/resources/intake/exports/__init__.py +48 -0
  301. nemo_platform/resources/intake/exports/exports.py +229 -0
  302. nemo_platform/resources/intake/exports/jobs.py +464 -0
  303. nemo_platform/resources/intake/ingest/__init__.py +76 -0
  304. nemo_platform/resources/intake/ingest/atif.py +242 -0
  305. nemo_platform/resources/intake/ingest/chat_completions.py +270 -0
  306. nemo_platform/resources/intake/ingest/ingest.py +181 -0
  307. nemo_platform/resources/intake/ingest/otlp/__init__.py +48 -0
  308. nemo_platform/resources/intake/ingest/otlp/otlp.py +117 -0
  309. nemo_platform/resources/intake/ingest/otlp/v1/__init__.py +48 -0
  310. nemo_platform/resources/intake/ingest/otlp/v1/traces.py +183 -0
  311. nemo_platform/resources/intake/ingest/otlp/v1/v1.py +117 -0
  312. nemo_platform/resources/intake/intake.py +309 -0
  313. nemo_platform/resources/intake/spans/__init__.py +48 -0
  314. nemo_platform/resources/intake/spans/evaluator_results.py +197 -0
  315. nemo_platform/resources/intake/spans/spans.py +367 -0
  316. nemo_platform/resources/intake/traces.py +351 -0
  317. nemo_platform/resources/jobs/__init__.py +76 -0
  318. nemo_platform/resources/jobs/api.md +118 -0
  319. nemo_platform/resources/jobs/jobs.py +1300 -0
  320. nemo_platform/resources/jobs/results.py +555 -0
  321. nemo_platform/resources/jobs/steps.py +491 -0
  322. nemo_platform/resources/jobs/tasks.py +470 -0
  323. nemo_platform/resources/members/__init__.py +34 -0
  324. nemo_platform/resources/members/api.md +19 -0
  325. nemo_platform/resources/members/members.py +634 -0
  326. nemo_platform/resources/models/__init__.py +48 -0
  327. nemo_platform/resources/models/adapters.py +514 -0
  328. nemo_platform/resources/models/api.md +44 -0
  329. nemo_platform/resources/models/models.py +981 -0
  330. nemo_platform/resources/projects/__init__.py +34 -0
  331. nemo_platform/resources/projects/api.md +21 -0
  332. nemo_platform/resources/projects/projects.py +736 -0
  333. nemo_platform/resources/safe_synthesizer/__init__.py +48 -0
  334. nemo_platform/resources/safe_synthesizer/api.md +62 -0
  335. nemo_platform/resources/safe_synthesizer/jobs/__init__.py +48 -0
  336. nemo_platform/resources/safe_synthesizer/jobs/jobs.py +895 -0
  337. nemo_platform/resources/safe_synthesizer/jobs/results.py +819 -0
  338. nemo_platform/resources/safe_synthesizer/safe_synthesizer.py +117 -0
  339. nemo_platform/resources/secrets/__init__.py +48 -0
  340. nemo_platform/resources/secrets/admin.py +150 -0
  341. nemo_platform/resources/secrets/api.md +34 -0
  342. nemo_platform/resources/secrets/secrets.py +756 -0
  343. nemo_platform/resources/workspaces/__init__.py +34 -0
  344. nemo_platform/resources/workspaces/api.md +20 -0
  345. nemo_platform/resources/workspaces/workspaces.py +734 -0
  346. nemo_platform/skills/__init__.py +28 -0
  347. nemo_platform/skills/inference/SKILL.md +564 -0
  348. nemo_platform/skills/nemo-build-agent/SKILL.md +221 -0
  349. nemo_platform/skills/nemo-build-agent/references/templates/data-designer-config.py +80 -0
  350. nemo_platform/skills/nemo-evaluator/SKILL.md +140 -0
  351. nemo_platform/skills/nemo-explore/SKILL.md +70 -0
  352. nemo_platform/skills/nemo-files/SKILL.md +81 -0
  353. nemo_platform/skills/nemo-fine-tune/SKILL.md +43 -0
  354. nemo_platform/skills/nemo-guardrails/SKILL.md +519 -0
  355. nemo_platform/skills/nemo-secrets/SKILL.md +60 -0
  356. nemo_platform/skills/nemo-skill-selection/SKILL.md +146 -0
  357. nemo_platform/skills/nemo-spec/SKILL.md +76 -0
  358. nemo_platform/skills/nemo-spec/references/templates/agent-spec.md +68 -0
  359. nemo_platform/skills/nemo-status/SKILL.md +115 -0
  360. nemo_platform/skills/nemo-teardown/SKILL.md +185 -0
  361. nemo_platform/skills/nemo-try-agent/SKILL.md +102 -0
  362. nemo_platform/types/__init__.py +54 -0
  363. nemo_platform/types/adapters/__init__.py +24 -0
  364. nemo_platform/types/adapters/adapter_create_params.py +63 -0
  365. nemo_platform/types/adapters/adapter_entity_filter_param.py +56 -0
  366. nemo_platform/types/adapters/adapter_list_params.py +46 -0
  367. nemo_platform/types/adapters/adapter_patch_params.py +35 -0
  368. nemo_platform/types/adapters/adapters_page.py +37 -0
  369. nemo_platform/types/audit/__init__.py +18 -0
  370. nemo_platform/types/audit/jobs/__init__.py +18 -0
  371. nemo_platform/types/entities/__init__.py +26 -0
  372. nemo_platform/types/entities/entities_page.py +37 -0
  373. nemo_platform/types/entities/entity.py +63 -0
  374. nemo_platform/types/entities/entity_create_params.py +46 -0
  375. nemo_platform/types/entities/entity_delete_entity_by_name_params.py +31 -0
  376. nemo_platform/types/entities/entity_get_entity_by_name_params.py +31 -0
  377. nemo_platform/types/entities/entity_list_params.py +47 -0
  378. nemo_platform/types/entities/entity_update_entity_by_name_params.py +52 -0
  379. nemo_platform/types/evaluation/__init__.py +242 -0
  380. nemo_platform/types/evaluation/agent.py +68 -0
  381. nemo_platform/types/evaluation/agent_goal_accuracy_metric.py +92 -0
  382. nemo_platform/types/evaluation/agent_goal_accuracy_metric_param.py +69 -0
  383. nemo_platform/types/evaluation/agent_goal_accuracy_metric_param_param.py +70 -0
  384. nemo_platform/types/evaluation/agent_goal_accuracy_metric_response.py +88 -0
  385. nemo_platform/types/evaluation/agent_param.py +69 -0
  386. nemo_platform/types/evaluation/aggregate_range_score.py +65 -0
  387. nemo_platform/types/evaluation/aggregate_rubric_score.py +64 -0
  388. nemo_platform/types/evaluation/aggregated_metric_result.py +34 -0
  389. nemo_platform/types/evaluation/answer_accuracy_metric.py +89 -0
  390. nemo_platform/types/evaluation/answer_accuracy_metric_param.py +66 -0
  391. nemo_platform/types/evaluation/answer_accuracy_metric_param_param.py +67 -0
  392. nemo_platform/types/evaluation/answer_accuracy_metric_response.py +85 -0
  393. nemo_platform/types/evaluation/benchmark.py +81 -0
  394. nemo_platform/types/evaluation/benchmark_create_params.py +64 -0
  395. nemo_platform/types/evaluation/benchmark_create_response.py +26 -0
  396. nemo_platform/types/evaluation/benchmark_evaluation_job.py +75 -0
  397. nemo_platform/types/evaluation/benchmark_evaluation_jobs_list_filter_param.py +49 -0
  398. nemo_platform/types/evaluation/benchmark_evaluation_jobs_page.py +37 -0
  399. nemo_platform/types/evaluation/benchmark_evaluation_jobs_sort_field.py +22 -0
  400. nemo_platform/types/evaluation/benchmark_job_create_params.py +58 -0
  401. nemo_platform/types/evaluation/benchmark_job_get_logs_params.py +30 -0
  402. nemo_platform/types/evaluation/benchmark_job_list_params.py +44 -0
  403. nemo_platform/types/evaluation/benchmark_job_result.py +93 -0
  404. nemo_platform/types/evaluation/benchmark_job_result_list_params.py +116 -0
  405. nemo_platform/types/evaluation/benchmark_job_result_retrieve_params.py +50 -0
  406. nemo_platform/types/evaluation/benchmark_job_results_list_response.py +37 -0
  407. nemo_platform/types/evaluation/benchmark_jobs/__init__.py +18 -0
  408. nemo_platform/types/evaluation/benchmark_jobs/results/__init__.py +22 -0
  409. nemo_platform/types/evaluation/benchmark_jobs/results/benchmark_evaluation_result.py +30 -0
  410. nemo_platform/types/evaluation/benchmark_jobs/results/benchmark_metric_result.py +44 -0
  411. nemo_platform/types/evaluation/benchmark_jobs/results/row_score_download_params.py +28 -0
  412. nemo_platform/types/evaluation/benchmark_list_params.py +84 -0
  413. nemo_platform/types/evaluation/benchmark_offline_job.py +43 -0
  414. nemo_platform/types/evaluation/benchmark_offline_job_param.py +44 -0
  415. nemo_platform/types/evaluation/benchmark_online_agent_job.py +71 -0
  416. nemo_platform/types/evaluation/benchmark_online_agent_job_param.py +74 -0
  417. nemo_platform/types/evaluation/benchmark_online_job.py +66 -0
  418. nemo_platform/types/evaluation/benchmark_online_job_param.py +68 -0
  419. nemo_platform/types/evaluation/benchmark_ref.py +22 -0
  420. nemo_platform/types/evaluation/benchmark_retrieve_params.py +29 -0
  421. nemo_platform/types/evaluation/benchmark_retrieve_response.py +27 -0
  422. nemo_platform/types/evaluation/benchmarks_list_response.py +42 -0
  423. nemo_platform/types/evaluation/bleu_metric.py +76 -0
  424. nemo_platform/types/evaluation/bleu_metric_param.py +50 -0
  425. nemo_platform/types/evaluation/bleu_metric_param_param.py +52 -0
  426. nemo_platform/types/evaluation/bleu_metric_response.py +69 -0
  427. nemo_platform/types/evaluation/built_in_dataset.py +46 -0
  428. nemo_platform/types/evaluation/context_entity_recall_metric.py +89 -0
  429. nemo_platform/types/evaluation/context_entity_recall_metric_param.py +66 -0
  430. nemo_platform/types/evaluation/context_entity_recall_metric_param_param.py +67 -0
  431. nemo_platform/types/evaluation/context_entity_recall_metric_response.py +85 -0
  432. nemo_platform/types/evaluation/context_precision_metric.py +89 -0
  433. nemo_platform/types/evaluation/context_precision_metric_param.py +66 -0
  434. nemo_platform/types/evaluation/context_precision_metric_param_param.py +67 -0
  435. nemo_platform/types/evaluation/context_precision_metric_response.py +85 -0
  436. nemo_platform/types/evaluation/context_recall_metric.py +89 -0
  437. nemo_platform/types/evaluation/context_recall_metric_param.py +66 -0
  438. nemo_platform/types/evaluation/context_recall_metric_param_param.py +67 -0
  439. nemo_platform/types/evaluation/context_recall_metric_response.py +85 -0
  440. nemo_platform/types/evaluation/context_relevance_metric.py +89 -0
  441. nemo_platform/types/evaluation/context_relevance_metric_param.py +66 -0
  442. nemo_platform/types/evaluation/context_relevance_metric_param_param.py +67 -0
  443. nemo_platform/types/evaluation/context_relevance_metric_response.py +85 -0
  444. nemo_platform/types/evaluation/dataset_rows.py +35 -0
  445. nemo_platform/types/evaluation/dataset_rows_param.py +36 -0
  446. nemo_platform/types/evaluation/evaluate_dataset_rows_param.py +33 -0
  447. nemo_platform/types/evaluation/exact_match_metric.py +79 -0
  448. nemo_platform/types/evaluation/exact_match_metric_param.py +53 -0
  449. nemo_platform/types/evaluation/exact_match_metric_param_param.py +53 -0
  450. nemo_platform/types/evaluation/exact_match_metric_response.py +72 -0
  451. nemo_platform/types/evaluation/extended_benchmark.py +130 -0
  452. nemo_platform/types/evaluation/f1_metric.py +76 -0
  453. nemo_platform/types/evaluation/f1_metric_param.py +50 -0
  454. nemo_platform/types/evaluation/f1_metric_param_param.py +50 -0
  455. nemo_platform/types/evaluation/f1_metric_response.py +69 -0
  456. nemo_platform/types/evaluation/faithfulness_metric.py +89 -0
  457. nemo_platform/types/evaluation/faithfulness_metric_param.py +66 -0
  458. nemo_platform/types/evaluation/faithfulness_metric_param_param.py +67 -0
  459. nemo_platform/types/evaluation/faithfulness_metric_response.py +85 -0
  460. nemo_platform/types/evaluation/field_mapping.py +56 -0
  461. nemo_platform/types/evaluation/field_mapping_param.py +57 -0
  462. nemo_platform/types/evaluation/fileset.py +48 -0
  463. nemo_platform/types/evaluation/fileset_param.py +49 -0
  464. nemo_platform/types/evaluation/fileset_ref.py +22 -0
  465. nemo_platform/types/evaluation/histogram.py +30 -0
  466. nemo_platform/types/evaluation/histogram_bin.py +33 -0
  467. nemo_platform/types/evaluation/inference_params.py +65 -0
  468. nemo_platform/types/evaluation/inference_params_param.py +53 -0
  469. nemo_platform/types/evaluation/json_score_parser.py +35 -0
  470. nemo_platform/types/evaluation/json_score_parser_param.py +34 -0
  471. nemo_platform/types/evaluation/llm_judge_metric.py +126 -0
  472. nemo_platform/types/evaluation/llm_judge_metric_param.py +103 -0
  473. nemo_platform/types/evaluation/llm_judge_metric_param_param.py +105 -0
  474. nemo_platform/types/evaluation/llm_judge_metric_response.py +120 -0
  475. nemo_platform/types/evaluation/metric_create_params.py +959 -0
  476. nemo_platform/types/evaluation/metric_create_response.py +75 -0
  477. nemo_platform/types/evaluation/metric_evaluate_params.py +111 -0
  478. nemo_platform/types/evaluation/metric_evaluation_job.py +65 -0
  479. nemo_platform/types/evaluation/metric_evaluation_jobs_list_filter_param.py +49 -0
  480. nemo_platform/types/evaluation/metric_evaluation_jobs_page.py +37 -0
  481. nemo_platform/types/evaluation/metric_evaluation_jobs_sort_field.py +22 -0
  482. nemo_platform/types/evaluation/metric_evaluation_response.py +98 -0
  483. nemo_platform/types/evaluation/metric_evaluation_row_score.py +45 -0
  484. nemo_platform/types/evaluation/metric_job_create_params.py +48 -0
  485. nemo_platform/types/evaluation/metric_job_get_logs_params.py +30 -0
  486. nemo_platform/types/evaluation/metric_job_list_params.py +44 -0
  487. nemo_platform/types/evaluation/metric_job_result.py +93 -0
  488. nemo_platform/types/evaluation/metric_job_result_list_params.py +114 -0
  489. nemo_platform/types/evaluation/metric_job_result_retrieve_params.py +50 -0
  490. nemo_platform/types/evaluation/metric_job_results_list_response.py +37 -0
  491. nemo_platform/types/evaluation/metric_jobs/__init__.py +18 -0
  492. nemo_platform/types/evaluation/metric_jobs/results/__init__.py +20 -0
  493. nemo_platform/types/evaluation/metric_jobs/results/row_score_download_params.py +28 -0
  494. nemo_platform/types/evaluation/metric_list_params.py +73 -0
  495. nemo_platform/types/evaluation/metric_offline_job.py +106 -0
  496. nemo_platform/types/evaluation/metric_offline_job_param.py +107 -0
  497. nemo_platform/types/evaluation/metric_online_agent_job.py +133 -0
  498. nemo_platform/types/evaluation/metric_online_agent_job_param.py +135 -0
  499. nemo_platform/types/evaluation/metric_online_job.py +127 -0
  500. nemo_platform/types/evaluation/metric_online_job_param.py +129 -0
  501. nemo_platform/types/evaluation/metric_output.py +30 -0
  502. nemo_platform/types/evaluation/metric_ref.py +22 -0
  503. nemo_platform/types/evaluation/metric_retrieve_response.py +98 -0
  504. nemo_platform/types/evaluation/metric_retriever_job.py +64 -0
  505. nemo_platform/types/evaluation/metric_retriever_job_param.py +65 -0
  506. nemo_platform/types/evaluation/metric_type.py +47 -0
  507. nemo_platform/types/evaluation/metrics_list_response.py +90 -0
  508. nemo_platform/types/evaluation/model.py +44 -0
  509. nemo_platform/types/evaluation/model_param.py +44 -0
  510. nemo_platform/types/evaluation/model_ref.py +22 -0
  511. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric.py +87 -0
  512. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric_param.py +64 -0
  513. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric_param_param.py +65 -0
  514. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric_response.py +80 -0
  515. nemo_platform/types/evaluation/noise_sensitivity_metric.py +89 -0
  516. nemo_platform/types/evaluation/noise_sensitivity_metric_param.py +66 -0
  517. nemo_platform/types/evaluation/noise_sensitivity_metric_param_param.py +67 -0
  518. nemo_platform/types/evaluation/noise_sensitivity_metric_response.py +85 -0
  519. nemo_platform/types/evaluation/number_check_metric.py +104 -0
  520. nemo_platform/types/evaluation/number_check_metric_param.py +81 -0
  521. nemo_platform/types/evaluation/number_check_metric_param_param.py +83 -0
  522. nemo_platform/types/evaluation/number_check_metric_response.py +97 -0
  523. nemo_platform/types/evaluation/parameter.py +42 -0
  524. nemo_platform/types/evaluation/parameter_param.py +40 -0
  525. nemo_platform/types/evaluation/percentiles.py +54 -0
  526. nemo_platform/types/evaluation/range_score.py +56 -0
  527. nemo_platform/types/evaluation/range_score_param.py +57 -0
  528. nemo_platform/types/evaluation/reasoning_params.py +41 -0
  529. nemo_platform/types/evaluation/reasoning_params_param.py +41 -0
  530. nemo_platform/types/evaluation/regex_score_parser.py +38 -0
  531. nemo_platform/types/evaluation/regex_score_parser_param.py +37 -0
  532. nemo_platform/types/evaluation/remote_metric.py +91 -0
  533. nemo_platform/types/evaluation/remote_metric_param.py +68 -0
  534. nemo_platform/types/evaluation/remote_metric_param_param.py +69 -0
  535. nemo_platform/types/evaluation/remote_metric_response.py +84 -0
  536. nemo_platform/types/evaluation/remote_score.py +49 -0
  537. nemo_platform/types/evaluation/remote_score_param.py +50 -0
  538. nemo_platform/types/evaluation/response_groundedness_metric.py +89 -0
  539. nemo_platform/types/evaluation/response_groundedness_metric_param.py +66 -0
  540. nemo_platform/types/evaluation/response_groundedness_metric_param_param.py +67 -0
  541. nemo_platform/types/evaluation/response_groundedness_metric_response.py +85 -0
  542. nemo_platform/types/evaluation/response_relevancy_metric.py +95 -0
  543. nemo_platform/types/evaluation/response_relevancy_metric_param.py +74 -0
  544. nemo_platform/types/evaluation/response_relevancy_metric_param_param.py +75 -0
  545. nemo_platform/types/evaluation/response_relevancy_metric_response.py +93 -0
  546. nemo_platform/types/evaluation/retriever_pipeline.py +34 -0
  547. nemo_platform/types/evaluation/retriever_pipeline_param.py +35 -0
  548. nemo_platform/types/evaluation/rouge_metric.py +76 -0
  549. nemo_platform/types/evaluation/rouge_metric_param.py +53 -0
  550. nemo_platform/types/evaluation/rouge_metric_param_param.py +53 -0
  551. nemo_platform/types/evaluation/rouge_metric_response.py +69 -0
  552. nemo_platform/types/evaluation/row_score.py +59 -0
  553. nemo_platform/types/evaluation/rubric.py +40 -0
  554. nemo_platform/types/evaluation/rubric_param.py +40 -0
  555. nemo_platform/types/evaluation/rubric_score.py +54 -0
  556. nemo_platform/types/evaluation/rubric_score_param.py +55 -0
  557. nemo_platform/types/evaluation/rubric_score_stat.py +38 -0
  558. nemo_platform/types/evaluation/run_config.py +39 -0
  559. nemo_platform/types/evaluation/run_config_online.py +51 -0
  560. nemo_platform/types/evaluation/run_config_online_model.py +73 -0
  561. nemo_platform/types/evaluation/run_config_online_model_param.py +75 -0
  562. nemo_platform/types/evaluation/run_config_online_param.py +51 -0
  563. nemo_platform/types/evaluation/run_config_param.py +39 -0
  564. nemo_platform/types/evaluation/string_check_metric.py +82 -0
  565. nemo_platform/types/evaluation/string_check_metric_param.py +59 -0
  566. nemo_platform/types/evaluation/string_check_metric_param_param.py +61 -0
  567. nemo_platform/types/evaluation/string_check_metric_response.py +75 -0
  568. nemo_platform/types/evaluation/system_benchmark.py +71 -0
  569. nemo_platform/types/evaluation/system_benchmark_offline_job.py +58 -0
  570. nemo_platform/types/evaluation/system_benchmark_offline_job_param.py +60 -0
  571. nemo_platform/types/evaluation/system_benchmark_online_job.py +54 -0
  572. nemo_platform/types/evaluation/system_benchmark_online_job_param.py +55 -0
  573. nemo_platform/types/evaluation/system_metric.py +70 -0
  574. nemo_platform/types/evaluation/system_metric_param.py +50 -0
  575. nemo_platform/types/evaluation/system_metric_param_param.py +51 -0
  576. nemo_platform/types/evaluation/system_metric_response.py +66 -0
  577. nemo_platform/types/evaluation/tool_call_accuracy_metric.py +70 -0
  578. nemo_platform/types/evaluation/tool_call_accuracy_metric_param.py +44 -0
  579. nemo_platform/types/evaluation/tool_call_accuracy_metric_param_param.py +44 -0
  580. nemo_platform/types/evaluation/tool_call_accuracy_metric_response.py +63 -0
  581. nemo_platform/types/evaluation/tool_calling_metric.py +70 -0
  582. nemo_platform/types/evaluation/tool_calling_metric_param.py +47 -0
  583. nemo_platform/types/evaluation/tool_calling_metric_param_param.py +47 -0
  584. nemo_platform/types/evaluation/tool_calling_metric_response.py +63 -0
  585. nemo_platform/types/evaluation/topic_adherence_metric.py +92 -0
  586. nemo_platform/types/evaluation/topic_adherence_metric_param.py +69 -0
  587. nemo_platform/types/evaluation/topic_adherence_metric_param_param.py +70 -0
  588. nemo_platform/types/evaluation/topic_adherence_metric_response.py +88 -0
  589. nemo_platform/types/files/__init__.py +45 -0
  590. nemo_platform/types/files/cache_status.py +22 -0
  591. nemo_platform/types/files/dataset_metadata_content.py +46 -0
  592. nemo_platform/types/files/dataset_metadata_content_param.py +45 -0
  593. nemo_platform/types/files/file_list_files_params.py +35 -0
  594. nemo_platform/types/files/file_upload_file_params.py +28 -0
  595. nemo_platform/types/files/fileset.py +62 -0
  596. nemo_platform/types/files/fileset_create_params.py +74 -0
  597. nemo_platform/types/files/fileset_file.py +36 -0
  598. nemo_platform/types/files/fileset_filter_param.py +54 -0
  599. nemo_platform/types/files/fileset_list_params.py +47 -0
  600. nemo_platform/types/files/fileset_metadata_param.py +46 -0
  601. nemo_platform/types/files/fileset_metadata_param_param.py +47 -0
  602. nemo_platform/types/files/fileset_outputs_page.py +37 -0
  603. nemo_platform/types/files/fileset_purpose.py +22 -0
  604. nemo_platform/types/files/fileset_update_params.py +49 -0
  605. nemo_platform/types/files/huggingface_storage_config.py +60 -0
  606. nemo_platform/types/files/huggingface_storage_config_param.py +60 -0
  607. nemo_platform/types/files/list_fileset_files_response.py +27 -0
  608. nemo_platform/types/files/local_storage_config.py +39 -0
  609. nemo_platform/types/files/local_storage_config_param.py +38 -0
  610. nemo_platform/types/files/ngc_storage_config.py +66 -0
  611. nemo_platform/types/files/ngc_storage_config_param.py +66 -0
  612. nemo_platform/types/files/otlp/__init__.py +22 -0
  613. nemo_platform/types/files/otlp/log_query_params.py +36 -0
  614. nemo_platform/types/files/otlp/otel_export_logs_partial_success.py +34 -0
  615. nemo_platform/types/files/otlp/otel_export_logs_service_response.py +35 -0
  616. nemo_platform/types/files/s3_storage_config.py +85 -0
  617. nemo_platform/types/files/s3_storage_config_param.py +85 -0
  618. nemo_platform/types/files/secret_ref.py +22 -0
  619. nemo_platform/types/files/storage_config_type.py +22 -0
  620. nemo_platform/types/guardrail/__init__.py +165 -0
  621. nemo_platform/types/guardrail/action_rails.py +36 -0
  622. nemo_platform/types/guardrail/action_rails_param.py +38 -0
  623. nemo_platform/types/guardrail/activated_rail.py +61 -0
  624. nemo_platform/types/guardrail/ai_defense_rail_config.py +36 -0
  625. nemo_platform/types/guardrail/ai_defense_rail_config_param.py +36 -0
  626. nemo_platform/types/guardrail/auto_align_options.py +29 -0
  627. nemo_platform/types/guardrail/auto_align_options_param.py +30 -0
  628. nemo_platform/types/guardrail/auto_align_rail_config.py +35 -0
  629. nemo_platform/types/guardrail/auto_align_rail_config_param.py +37 -0
  630. nemo_platform/types/guardrail/cache_stats_config.py +32 -0
  631. nemo_platform/types/guardrail/cache_stats_config_param.py +32 -0
  632. nemo_platform/types/guardrail/chat_completion_assistant_message_param.py +45 -0
  633. nemo_platform/types/guardrail/chat_completion_content_part_image_param.py +34 -0
  634. nemo_platform/types/guardrail/chat_completion_content_part_text_param.py +32 -0
  635. nemo_platform/types/guardrail/chat_completion_function_message_param.py +35 -0
  636. nemo_platform/types/guardrail/chat_completion_message_tool_call_param.py +37 -0
  637. nemo_platform/types/guardrail/chat_completion_system_message_param.py +35 -0
  638. nemo_platform/types/guardrail/chat_completion_tool_message_param.py +35 -0
  639. nemo_platform/types/guardrail/chat_completion_user_message_param.py +41 -0
  640. nemo_platform/types/guardrail/clavata_rail_config.py +47 -0
  641. nemo_platform/types/guardrail/clavata_rail_config_param.py +48 -0
  642. nemo_platform/types/guardrail/clavata_rail_options.py +36 -0
  643. nemo_platform/types/guardrail/clavata_rail_options_param.py +38 -0
  644. nemo_platform/types/guardrail/config_create_params.py +36 -0
  645. nemo_platform/types/guardrail/config_list_params.py +47 -0
  646. nemo_platform/types/guardrail/config_update_params.py +33 -0
  647. nemo_platform/types/guardrail/content_safety_config.py +34 -0
  648. nemo_platform/types/guardrail/content_safety_config_param.py +35 -0
  649. nemo_platform/types/guardrail/crowd_strike_aidr_rail_config.py +29 -0
  650. nemo_platform/types/guardrail/crowd_strike_aidr_rail_config_param.py +29 -0
  651. nemo_platform/types/guardrail/dialog_rails.py +34 -0
  652. nemo_platform/types/guardrail/dialog_rails_param.py +35 -0
  653. nemo_platform/types/guardrail/executed_action.py +48 -0
  654. nemo_platform/types/guardrail/fact_checking_rail_config.py +31 -0
  655. nemo_platform/types/guardrail/fact_checking_rail_config_param.py +32 -0
  656. nemo_platform/types/guardrail/fiddler_guardrails.py +35 -0
  657. nemo_platform/types/guardrail/fiddler_guardrails_param.py +35 -0
  658. nemo_platform/types/guardrail/function_call_param.py +35 -0
  659. nemo_platform/types/guardrail/function_param.py +35 -0
  660. nemo_platform/types/guardrail/g_li_ner_detection.py +51 -0
  661. nemo_platform/types/guardrail/g_li_ner_detection_options.py +29 -0
  662. nemo_platform/types/guardrail/g_li_ner_detection_options_param.py +31 -0
  663. nemo_platform/types/guardrail/g_li_ner_detection_param.py +52 -0
  664. nemo_platform/types/guardrail/generation_log.py +44 -0
  665. nemo_platform/types/guardrail/generation_log_options_param.py +50 -0
  666. nemo_platform/types/guardrail/generation_options_param.py +55 -0
  667. nemo_platform/types/guardrail/generation_rails_options_param.py +53 -0
  668. nemo_platform/types/guardrail/generation_stats.py +56 -0
  669. nemo_platform/types/guardrail/guardrail_check_params.py +164 -0
  670. nemo_platform/types/guardrail/guardrail_check_response.py +36 -0
  671. nemo_platform/types/guardrail/guardrail_config.py +59 -0
  672. nemo_platform/types/guardrail/guardrail_config_filter_param.py +49 -0
  673. nemo_platform/types/guardrail/guardrail_configs_page.py +37 -0
  674. nemo_platform/types/guardrail/guardrails_ai_rail_config.py +33 -0
  675. nemo_platform/types/guardrail/guardrails_ai_rail_config_param.py +35 -0
  676. nemo_platform/types/guardrail/guardrails_ai_validator_config.py +44 -0
  677. nemo_platform/types/guardrail/guardrails_ai_validator_config_param.py +45 -0
  678. nemo_platform/types/guardrail/guardrails_data.py +40 -0
  679. nemo_platform/types/guardrail/guardrails_data_param.py +67 -0
  680. nemo_platform/types/guardrail/image_u_rl_param.py +32 -0
  681. nemo_platform/types/guardrail/injection_detection.py +49 -0
  682. nemo_platform/types/guardrail/injection_detection_param.py +52 -0
  683. nemo_platform/types/guardrail/input_rails.py +32 -0
  684. nemo_platform/types/guardrail/input_rails_param.py +34 -0
  685. nemo_platform/types/guardrail/instruction.py +30 -0
  686. nemo_platform/types/guardrail/instruction_param.py +32 -0
  687. nemo_platform/types/guardrail/jailbreak_detection_config.py +52 -0
  688. nemo_platform/types/guardrail/jailbreak_detection_config_param.py +58 -0
  689. nemo_platform/types/guardrail/llm_call_info.py +63 -0
  690. nemo_platform/types/guardrail/log_adapter_config.py +41 -0
  691. nemo_platform/types/guardrail/log_adapter_config_param.py +27 -0
  692. nemo_platform/types/guardrail/message_template.py +30 -0
  693. nemo_platform/types/guardrail/message_template_param.py +32 -0
  694. nemo_platform/types/guardrail/model.py +55 -0
  695. nemo_platform/types/guardrail/model_cache_config.py +36 -0
  696. nemo_platform/types/guardrail/model_cache_config_param.py +37 -0
  697. nemo_platform/types/guardrail/model_param.py +55 -0
  698. nemo_platform/types/guardrail/model_parameters.py +51 -0
  699. nemo_platform/types/guardrail/model_parameters_param.py +38 -0
  700. nemo_platform/types/guardrail/multilingual_config.py +40 -0
  701. nemo_platform/types/guardrail/multilingual_config_param.py +41 -0
  702. nemo_platform/types/guardrail/output_rails.py +44 -0
  703. nemo_platform/types/guardrail/output_rails_param.py +46 -0
  704. nemo_platform/types/guardrail/output_rails_streaming_config.py +44 -0
  705. nemo_platform/types/guardrail/output_rails_streaming_config_param.py +44 -0
  706. nemo_platform/types/guardrail/pangea_rail_config.py +33 -0
  707. nemo_platform/types/guardrail/pangea_rail_config_param.py +34 -0
  708. nemo_platform/types/guardrail/pangea_rail_options.py +31 -0
  709. nemo_platform/types/guardrail/pangea_rail_options_param.py +33 -0
  710. nemo_platform/types/guardrail/patronus_evaluate_api_params.py +38 -0
  711. nemo_platform/types/guardrail/patronus_evaluate_api_params_param.py +40 -0
  712. nemo_platform/types/guardrail/patronus_evaluate_config.py +30 -0
  713. nemo_platform/types/guardrail/patronus_evaluate_config_param.py +31 -0
  714. nemo_platform/types/guardrail/patronus_evaluation_success_strategy.py +22 -0
  715. nemo_platform/types/guardrail/patronus_rail_config.py +33 -0
  716. nemo_platform/types/guardrail/patronus_rail_config_param.py +34 -0
  717. nemo_platform/types/guardrail/private_ai_detection.py +39 -0
  718. nemo_platform/types/guardrail/private_ai_detection_options.py +29 -0
  719. nemo_platform/types/guardrail/private_ai_detection_options_param.py +31 -0
  720. nemo_platform/types/guardrail/private_ai_detection_param.py +40 -0
  721. nemo_platform/types/guardrail/rail_status.py +26 -0
  722. nemo_platform/types/guardrail/rails.py +73 -0
  723. nemo_platform/types/guardrail/rails_config.py +79 -0
  724. nemo_platform/types/guardrail/rails_config_data.py +94 -0
  725. nemo_platform/types/guardrail/rails_config_data_param.py +95 -0
  726. nemo_platform/types/guardrail/rails_config_param.py +81 -0
  727. nemo_platform/types/guardrail/rails_param.py +74 -0
  728. nemo_platform/types/guardrail/reasoning_config.py +32 -0
  729. nemo_platform/types/guardrail/reasoning_config_param.py +32 -0
  730. nemo_platform/types/guardrail/regex_detection.py +36 -0
  731. nemo_platform/types/guardrail/regex_detection_options.py +32 -0
  732. nemo_platform/types/guardrail/regex_detection_options_param.py +34 -0
  733. nemo_platform/types/guardrail/regex_detection_param.py +37 -0
  734. nemo_platform/types/guardrail/retrieval_rails.py +29 -0
  735. nemo_platform/types/guardrail/retrieval_rails_param.py +31 -0
  736. nemo_platform/types/guardrail/sensitive_data_detection.py +43 -0
  737. nemo_platform/types/guardrail/sensitive_data_detection_options.py +37 -0
  738. nemo_platform/types/guardrail/sensitive_data_detection_options_param.py +39 -0
  739. nemo_platform/types/guardrail/sensitive_data_detection_param.py +45 -0
  740. nemo_platform/types/guardrail/single_call_config.py +31 -0
  741. nemo_platform/types/guardrail/single_call_config_param.py +31 -0
  742. nemo_platform/types/guardrail/status_enum.py +22 -0
  743. nemo_platform/types/guardrail/task_prompt.py +63 -0
  744. nemo_platform/types/guardrail/task_prompt_param.py +65 -0
  745. nemo_platform/types/guardrail/tool_input_rails.py +36 -0
  746. nemo_platform/types/guardrail/tool_input_rails_param.py +38 -0
  747. nemo_platform/types/guardrail/tool_output_rails.py +36 -0
  748. nemo_platform/types/guardrail/tool_output_rails_param.py +38 -0
  749. nemo_platform/types/guardrail/tracing_config.py +48 -0
  750. nemo_platform/types/guardrail/tracing_config_param.py +50 -0
  751. nemo_platform/types/guardrail/trend_micro_rail_config.py +51 -0
  752. nemo_platform/types/guardrail/trend_micro_rail_config_param.py +51 -0
  753. nemo_platform/types/guardrail/user_messages_config.py +42 -0
  754. nemo_platform/types/guardrail/user_messages_config_param.py +42 -0
  755. nemo_platform/types/iam/__init__.py +26 -0
  756. nemo_platform/types/iam/date_range_filter_param.py +36 -0
  757. nemo_platform/types/iam/role_binding.py +42 -0
  758. nemo_platform/types/iam/role_binding_create_params.py +39 -0
  759. nemo_platform/types/iam/role_binding_delete_params.py +30 -0
  760. nemo_platform/types/iam/role_binding_filter_param.py +49 -0
  761. nemo_platform/types/iam/role_binding_list_params.py +44 -0
  762. nemo_platform/types/iam/role_bindings_page.py +37 -0
  763. nemo_platform/types/inference/__init__.py +60 -0
  764. nemo_platform/types/inference/deployment_config_create_params.py +47 -0
  765. nemo_platform/types/inference/deployment_config_list_params.py +46 -0
  766. nemo_platform/types/inference/deployment_config_update_params.py +37 -0
  767. nemo_platform/types/inference/deployment_configs/__init__.py +20 -0
  768. nemo_platform/types/inference/deployment_configs/version_list_response.py +25 -0
  769. nemo_platform/types/inference/deployment_create_params.py +45 -0
  770. nemo_platform/types/inference/deployment_list_models_response.py +23 -0
  771. nemo_platform/types/inference/deployment_list_params.py +52 -0
  772. nemo_platform/types/inference/deployment_update_params.py +35 -0
  773. nemo_platform/types/inference/deployment_update_status_params.py +42 -0
  774. nemo_platform/types/inference/deployments/__init__.py +20 -0
  775. nemo_platform/types/inference/deployments/version_list_response.py +25 -0
  776. nemo_platform/types/inference/gateway/__init__.py +38 -0
  777. nemo_platform/types/inference/gateway/model_patch_params.py +31 -0
  778. nemo_platform/types/inference/gateway/model_patch_response.py +23 -0
  779. nemo_platform/types/inference/gateway/model_post_params.py +31 -0
  780. nemo_platform/types/inference/gateway/model_post_response.py +23 -0
  781. nemo_platform/types/inference/gateway/model_put_params.py +31 -0
  782. nemo_platform/types/inference/gateway/model_put_response.py +23 -0
  783. nemo_platform/types/inference/gateway/openai/__init__.py +18 -0
  784. nemo_platform/types/inference/gateway/openai/v1/__init__.py +21 -0
  785. nemo_platform/types/inference/gateway/openai/v1/openai_list_models_resp.py +31 -0
  786. nemo_platform/types/inference/gateway/openai/v1/openai_model_resp.py +34 -0
  787. nemo_platform/types/inference/gateway/openai_patch_params.py +29 -0
  788. nemo_platform/types/inference/gateway/openai_patch_response.py +23 -0
  789. nemo_platform/types/inference/gateway/openai_post_params.py +29 -0
  790. nemo_platform/types/inference/gateway/openai_post_response.py +23 -0
  791. nemo_platform/types/inference/gateway/openai_put_params.py +29 -0
  792. nemo_platform/types/inference/gateway/openai_put_response.py +23 -0
  793. nemo_platform/types/inference/gateway/provider_patch_params.py +31 -0
  794. nemo_platform/types/inference/gateway/provider_patch_response.py +23 -0
  795. nemo_platform/types/inference/gateway/provider_post_params.py +31 -0
  796. nemo_platform/types/inference/gateway/provider_post_response.py +23 -0
  797. nemo_platform/types/inference/gateway/provider_put_params.py +31 -0
  798. nemo_platform/types/inference/gateway/provider_put_response.py +23 -0
  799. nemo_platform/types/inference/gateway/provider_ready_response.py +23 -0
  800. nemo_platform/types/inference/k8s_nim_operator_config.py +57 -0
  801. nemo_platform/types/inference/k8s_nim_operator_config_param.py +58 -0
  802. nemo_platform/types/inference/middleware_call.py +55 -0
  803. nemo_platform/types/inference/middleware_call_param.py +56 -0
  804. nemo_platform/types/inference/model_deployment.py +97 -0
  805. nemo_platform/types/inference/model_deployment_config.py +76 -0
  806. nemo_platform/types/inference/model_deployment_config_filter_param.py +49 -0
  807. nemo_platform/types/inference/model_deployment_configs_page.py +37 -0
  808. nemo_platform/types/inference/model_deployment_filter_param.py +56 -0
  809. nemo_platform/types/inference/model_deployment_status.py +24 -0
  810. nemo_platform/types/inference/model_deployment_status_history_item.py +37 -0
  811. nemo_platform/types/inference/model_deployments_page.py +37 -0
  812. nemo_platform/types/inference/model_provider.py +134 -0
  813. nemo_platform/types/inference/model_provider_filter_param.py +56 -0
  814. nemo_platform/types/inference/model_provider_sort.py +24 -0
  815. nemo_platform/types/inference/model_provider_status.py +24 -0
  816. nemo_platform/types/inference/model_providers_page.py +37 -0
  817. nemo_platform/types/inference/model_type.py +22 -0
  818. nemo_platform/types/inference/nim_deployment.py +96 -0
  819. nemo_platform/types/inference/nim_deployment_param.py +93 -0
  820. nemo_platform/types/inference/provider_create_params.py +94 -0
  821. nemo_platform/types/inference/provider_list_params.py +47 -0
  822. nemo_platform/types/inference/provider_update_params.py +87 -0
  823. nemo_platform/types/inference/provider_update_status_params.py +48 -0
  824. nemo_platform/types/inference/served_model_mapping.py +35 -0
  825. nemo_platform/types/inference/served_model_mapping_param.py +32 -0
  826. nemo_platform/types/inference/virtual_model.py +91 -0
  827. nemo_platform/types/inference/virtual_model_create_params.py +83 -0
  828. nemo_platform/types/inference/virtual_model_inference_config.py +32 -0
  829. nemo_platform/types/inference/virtual_model_inference_config_param.py +34 -0
  830. nemo_platform/types/inference/virtual_model_list_params.py +35 -0
  831. nemo_platform/types/inference/virtual_model_patch_params.py +80 -0
  832. nemo_platform/types/inference/virtual_models_page.py +37 -0
  833. nemo_platform/types/intake/__init__.py +86 -0
  834. nemo_platform/types/intake/app.py +51 -0
  835. nemo_platform/types/intake/app_create_params.py +38 -0
  836. nemo_platform/types/intake/app_filter_param.py +46 -0
  837. nemo_platform/types/intake/app_list_params.py +44 -0
  838. nemo_platform/types/intake/app_patch_params.py +35 -0
  839. nemo_platform/types/intake/app_sort_field.py +22 -0
  840. nemo_platform/types/intake/apps/__init__.py +26 -0
  841. nemo_platform/types/intake/apps/task.py +54 -0
  842. nemo_platform/types/intake/apps/task_create_params.py +40 -0
  843. nemo_platform/types/intake/apps/task_filter_param.py +49 -0
  844. nemo_platform/types/intake/apps/task_list_params.py +44 -0
  845. nemo_platform/types/intake/apps/task_patch_params.py +37 -0
  846. nemo_platform/types/intake/apps/task_sort_field.py +22 -0
  847. nemo_platform/types/intake/apps/tasks_page.py +37 -0
  848. nemo_platform/types/intake/apps_page.py +37 -0
  849. nemo_platform/types/intake/entries/__init__.py +20 -0
  850. nemo_platform/types/intake/entries/event_create_params.py +40 -0
  851. nemo_platform/types/intake/entry.py +98 -0
  852. nemo_platform/types/intake/entry_context.py +79 -0
  853. nemo_platform/types/intake/entry_context_filter_param.py +41 -0
  854. nemo_platform/types/intake/entry_context_param.py +82 -0
  855. nemo_platform/types/intake/entry_create_params.py +85 -0
  856. nemo_platform/types/intake/entry_data.py +48 -0
  857. nemo_platform/types/intake/entry_data_param.py +51 -0
  858. nemo_platform/types/intake/entry_filter_param.py +85 -0
  859. nemo_platform/types/intake/entry_list_params.py +47 -0
  860. nemo_platform/types/intake/entry_patch_params.py +79 -0
  861. nemo_platform/types/intake/entry_sort_field.py +22 -0
  862. nemo_platform/types/intake/entry_user_rating_filter_param.py +31 -0
  863. nemo_platform/types/intake/entrys_page.py +37 -0
  864. nemo_platform/types/intake/evaluation_context_param.py +41 -0
  865. nemo_platform/types/intake/evaluator_result.py +52 -0
  866. nemo_platform/types/intake/evaluator_result_create_params.py +52 -0
  867. nemo_platform/types/intake/evaluator_result_data_type.py +22 -0
  868. nemo_platform/types/intake/evaluator_result_event.py +67 -0
  869. nemo_platform/types/intake/evaluator_result_event_param.py +69 -0
  870. nemo_platform/types/intake/evaluator_result_filter_param.py +49 -0
  871. nemo_platform/types/intake/evaluator_result_list_params.py +43 -0
  872. nemo_platform/types/intake/evaluator_result_sort_field.py +22 -0
  873. nemo_platform/types/intake/evaluator_results_page.py +37 -0
  874. nemo_platform/types/intake/export_config_param.py +44 -0
  875. nemo_platform/types/intake/export_config_param_param.py +45 -0
  876. nemo_platform/types/intake/export_preview_params.py +34 -0
  877. nemo_platform/types/intake/export_preview_response.py +39 -0
  878. nemo_platform/types/intake/exports/__init__.py +28 -0
  879. nemo_platform/types/intake/exports/export_config.py +44 -0
  880. nemo_platform/types/intake/exports/export_job.py +76 -0
  881. nemo_platform/types/intake/exports/export_job_filter_param.py +50 -0
  882. nemo_platform/types/intake/exports/export_job_sort_field.py +22 -0
  883. nemo_platform/types/intake/exports/export_jobs_page.py +37 -0
  884. nemo_platform/types/intake/exports/export_status_details.py +35 -0
  885. nemo_platform/types/intake/exports/job_create_params.py +40 -0
  886. nemo_platform/types/intake/exports/job_list_params.py +46 -0
  887. nemo_platform/types/intake/exports/job_status.py +22 -0
  888. nemo_platform/types/intake/flexible_entry_request.py +63 -0
  889. nemo_platform/types/intake/flexible_entry_request_param.py +51 -0
  890. nemo_platform/types/intake/flexible_entry_response.py +62 -0
  891. nemo_platform/types/intake/flexible_entry_response_param.py +49 -0
  892. nemo_platform/types/intake/flexible_message.py +56 -0
  893. nemo_platform/types/intake/flexible_message_param.py +43 -0
  894. nemo_platform/types/intake/float_filter_param.py +32 -0
  895. nemo_platform/types/intake/ingest/__init__.py +37 -0
  896. nemo_platform/types/intake/ingest/atif_agent_param.py +35 -0
  897. nemo_platform/types/intake/ingest/atif_content_part_image_param.py +30 -0
  898. nemo_platform/types/intake/ingest/atif_content_part_param.py +28 -0
  899. nemo_platform/types/intake/ingest/atif_content_part_text_param.py +28 -0
  900. nemo_platform/types/intake/ingest/atif_create_params.py +52 -0
  901. nemo_platform/types/intake/ingest/atif_final_metrics_param.py +37 -0
  902. nemo_platform/types/intake/ingest/atif_image_source_param.py +28 -0
  903. nemo_platform/types/intake/ingest/atif_metrics_param.py +41 -0
  904. nemo_platform/types/intake/ingest/atif_observation_param.py +29 -0
  905. nemo_platform/types/intake/ingest/atif_observation_result_param.py +36 -0
  906. nemo_platform/types/intake/ingest/atif_step_agent_param.py +58 -0
  907. nemo_platform/types/intake/ingest/atif_step_param.py +29 -0
  908. nemo_platform/types/intake/ingest/atif_step_system_param.py +43 -0
  909. nemo_platform/types/intake/ingest/atif_step_user_param.py +43 -0
  910. nemo_platform/types/intake/ingest/atif_subagent_trajectory_ref_param.py +33 -0
  911. nemo_platform/types/intake/ingest/atif_tool_call_param.py +31 -0
  912. nemo_platform/types/intake/ingest/chat_completion_create_params.py +66 -0
  913. nemo_platform/types/intake/ingest/chat_completions_ingest_response.py +26 -0
  914. nemo_platform/types/intake/ingest/otlp/__init__.py +18 -0
  915. nemo_platform/types/intake/ingest/otlp/v1/__init__.py +20 -0
  916. nemo_platform/types/intake/ingest/otlp/v1/ingest_response.py +26 -0
  917. nemo_platform/types/intake/message_role.py +22 -0
  918. nemo_platform/types/intake/reviewer_annotation_event.py +95 -0
  919. nemo_platform/types/intake/reviewer_annotation_event_param.py +97 -0
  920. nemo_platform/types/intake/span.py +100 -0
  921. nemo_platform/types/intake/span_evaluation_context.py +40 -0
  922. nemo_platform/types/intake/span_filter_param.py +95 -0
  923. nemo_platform/types/intake/span_kind.py +24 -0
  924. nemo_platform/types/intake/span_list_params.py +46 -0
  925. nemo_platform/types/intake/span_sort_field.py +22 -0
  926. nemo_platform/types/intake/span_status.py +22 -0
  927. nemo_platform/types/intake/spans/__init__.py +20 -0
  928. nemo_platform/types/intake/spans/evaluator_result_list_response.py +25 -0
  929. nemo_platform/types/intake/spans_page.py +37 -0
  930. nemo_platform/types/intake/thumb_direction.py +22 -0
  931. nemo_platform/types/intake/trace.py +65 -0
  932. nemo_platform/types/intake/trace_filter_param.py +60 -0
  933. nemo_platform/types/intake/trace_list_params.py +49 -0
  934. nemo_platform/types/intake/trace_retrieve_params.py +32 -0
  935. nemo_platform/types/intake/trace_sort_field.py +22 -0
  936. nemo_platform/types/intake/traces_page.py +37 -0
  937. nemo_platform/types/intake/usage.py +65 -0
  938. nemo_platform/types/intake/usage_param.py +68 -0
  939. nemo_platform/types/intake/user_action_event.py +65 -0
  940. nemo_platform/types/intake/user_action_event_param.py +68 -0
  941. nemo_platform/types/intake/user_feedback_event.py +84 -0
  942. nemo_platform/types/intake/user_feedback_event_param.py +86 -0
  943. nemo_platform/types/intake/user_rating.py +68 -0
  944. nemo_platform/types/intake/user_rating_param.py +70 -0
  945. nemo_platform/types/jobs/__init__.py +95 -0
  946. nemo_platform/types/jobs/compute_resource_spec.py +32 -0
  947. nemo_platform/types/jobs/compute_resource_spec_param.py +32 -0
  948. nemo_platform/types/jobs/compute_resources.py +46 -0
  949. nemo_platform/types/jobs/compute_resources_param.py +47 -0
  950. nemo_platform/types/jobs/container_spec.py +35 -0
  951. nemo_platform/types/jobs/container_spec_param.py +37 -0
  952. nemo_platform/types/jobs/cpu_execution_provider.py +46 -0
  953. nemo_platform/types/jobs/cpu_execution_provider_param.py +46 -0
  954. nemo_platform/types/jobs/distributed_gpu_execution_provider.py +46 -0
  955. nemo_platform/types/jobs/distributed_gpu_execution_provider_param.py +46 -0
  956. nemo_platform/types/jobs/docker_job_execution_profile.py +43 -0
  957. nemo_platform/types/jobs/docker_job_execution_profile_config.py +52 -0
  958. nemo_platform/types/jobs/docker_job_network_config.py +27 -0
  959. nemo_platform/types/jobs/docker_job_storage_config.py +36 -0
  960. nemo_platform/types/jobs/docker_volume_mount.py +47 -0
  961. nemo_platform/types/jobs/e2e_job_execution_profile.py +43 -0
  962. nemo_platform/types/jobs/gpu_execution_provider.py +46 -0
  963. nemo_platform/types/jobs/gpu_execution_provider_param.py +46 -0
  964. nemo_platform/types/jobs/image_pull_secret.py +27 -0
  965. nemo_platform/types/jobs/job_create_params.py +46 -0
  966. nemo_platform/types/jobs/job_execution_profile_config.py +42 -0
  967. nemo_platform/types/jobs/job_get_logs_params.py +41 -0
  968. nemo_platform/types/jobs/job_list_execution_profiles_response.py +37 -0
  969. nemo_platform/types/jobs/job_list_params.py +47 -0
  970. nemo_platform/types/jobs/job_update_status_details_params.py +29 -0
  971. nemo_platform/types/jobs/kubernetes_empty_dir_volume.py +32 -0
  972. nemo_platform/types/jobs/kubernetes_job_execution_profile.py +43 -0
  973. nemo_platform/types/jobs/kubernetes_job_execution_profile_config.py +101 -0
  974. nemo_platform/types/jobs/kubernetes_job_storage_config.py +40 -0
  975. nemo_platform/types/jobs/kubernetes_object_metadata.py +28 -0
  976. nemo_platform/types/jobs/kubernetes_persistent_volume_claim.py +32 -0
  977. nemo_platform/types/jobs/kubernetes_volume.py +37 -0
  978. nemo_platform/types/jobs/kubernetes_volume_mount.py +38 -0
  979. nemo_platform/types/jobs/platform_job_environment_variable.py +36 -0
  980. nemo_platform/types/jobs/platform_job_environment_variable_param.py +37 -0
  981. nemo_platform/types/jobs/platform_job_list_task_response.py +29 -0
  982. nemo_platform/types/jobs/platform_job_response.py +75 -0
  983. nemo_platform/types/jobs/platform_job_responses_page.py +37 -0
  984. nemo_platform/types/jobs/platform_job_secret_environment_variable_ref.py +27 -0
  985. nemo_platform/types/jobs/platform_job_secret_environment_variable_ref_param.py +29 -0
  986. nemo_platform/types/jobs/platform_job_sort_field.py +22 -0
  987. nemo_platform/types/jobs/platform_job_spec.py +30 -0
  988. nemo_platform/types/jobs/platform_job_spec_param.py +32 -0
  989. nemo_platform/types/jobs/platform_job_step.py +75 -0
  990. nemo_platform/types/jobs/platform_job_step_spec.py +63 -0
  991. nemo_platform/types/jobs/platform_job_step_spec_param.py +65 -0
  992. nemo_platform/types/jobs/platform_job_step_with_context.py +67 -0
  993. nemo_platform/types/jobs/platform_job_step_with_contexts_page.py +37 -0
  994. nemo_platform/types/jobs/platform_job_steps_list_filter_param.py +38 -0
  995. nemo_platform/types/jobs/platform_job_task.py +75 -0
  996. nemo_platform/types/jobs/platform_jobs_list_filter_param.py +51 -0
  997. nemo_platform/types/jobs/result_create_params.py +34 -0
  998. nemo_platform/types/jobs/result_list_params.py +34 -0
  999. nemo_platform/types/jobs/step_lifecycle.py +37 -0
  1000. nemo_platform/types/jobs/step_lifecycle_param.py +37 -0
  1001. nemo_platform/types/jobs/step_list_params.py +44 -0
  1002. nemo_platform/types/jobs/step_update_status_params.py +44 -0
  1003. nemo_platform/types/jobs/subprocess_execution_provider.py +33 -0
  1004. nemo_platform/types/jobs/subprocess_execution_provider_param.py +34 -0
  1005. nemo_platform/types/jobs/subprocess_job_execution_profile.py +36 -0
  1006. nemo_platform/types/jobs/subprocess_job_execution_profile_config.py +49 -0
  1007. nemo_platform/types/jobs/task_create_or_update_params.py +46 -0
  1008. nemo_platform/types/jobs/volcano_job_execution_profile.py +39 -0
  1009. nemo_platform/types/jobs/volcano_job_execution_profile_config.py +114 -0
  1010. nemo_platform/types/members/__init__.py +24 -0
  1011. nemo_platform/types/members/member_create_params.py +40 -0
  1012. nemo_platform/types/members/member_delete_params.py +32 -0
  1013. nemo_platform/types/members/member_update_params.py +37 -0
  1014. nemo_platform/types/members/workspace_member.py +39 -0
  1015. nemo_platform/types/members/workspace_member_list_response.py +29 -0
  1016. nemo_platform/types/models/__init__.py +34 -0
  1017. nemo_platform/types/models/adapter.py +73 -0
  1018. nemo_platform/types/models/adapter_create_params.py +54 -0
  1019. nemo_platform/types/models/adapter_update_params.py +37 -0
  1020. nemo_platform/types/models/base_model_filter_param.py +29 -0
  1021. nemo_platform/types/models/finetuning_type_filter_param.py +31 -0
  1022. nemo_platform/types/models/lora.py +30 -0
  1023. nemo_platform/types/models/lora_param.py +30 -0
  1024. nemo_platform/types/models/model_create_params.py +93 -0
  1025. nemo_platform/types/models/model_entity.py +112 -0
  1026. nemo_platform/types/models/model_entity_filter_param.py +72 -0
  1027. nemo_platform/types/models/model_entity_sort_field.py +22 -0
  1028. nemo_platform/types/models/model_entitys_page.py +37 -0
  1029. nemo_platform/types/models/model_list_params.py +50 -0
  1030. nemo_platform/types/models/model_retrieve_params.py +29 -0
  1031. nemo_platform/types/models/model_update_params.py +86 -0
  1032. nemo_platform/types/projects/__init__.py +25 -0
  1033. nemo_platform/types/projects/project.py +45 -0
  1034. nemo_platform/types/projects/project_create_params.py +37 -0
  1035. nemo_platform/types/projects/project_list_params.py +49 -0
  1036. nemo_platform/types/projects/project_sort_field.py +22 -0
  1037. nemo_platform/types/projects/project_update_params.py +29 -0
  1038. nemo_platform/types/projects/projects_page.py +37 -0
  1039. nemo_platform/types/safe_synthesizer/__init__.py +68 -0
  1040. nemo_platform/types/safe_synthesizer/classify_config.py +41 -0
  1041. nemo_platform/types/safe_synthesizer/classify_config_param.py +43 -0
  1042. nemo_platform/types/safe_synthesizer/column.py +46 -0
  1043. nemo_platform/types/safe_synthesizer/column_actions.py +36 -0
  1044. nemo_platform/types/safe_synthesizer/column_actions_param.py +38 -0
  1045. nemo_platform/types/safe_synthesizer/column_param.py +49 -0
  1046. nemo_platform/types/safe_synthesizer/data_parameters.py +69 -0
  1047. nemo_platform/types/safe_synthesizer/data_parameters_param.py +69 -0
  1048. nemo_platform/types/safe_synthesizer/differential_privacy_hyperparams.py +48 -0
  1049. nemo_platform/types/safe_synthesizer/differential_privacy_hyperparams_param.py +48 -0
  1050. nemo_platform/types/safe_synthesizer/evaluation_parameters.py +64 -0
  1051. nemo_platform/types/safe_synthesizer/evaluation_parameters_param.py +66 -0
  1052. nemo_platform/types/safe_synthesizer/generate_parameters.py +104 -0
  1053. nemo_platform/types/safe_synthesizer/generate_parameters_param.py +102 -0
  1054. nemo_platform/types/safe_synthesizer/gliner_config.py +41 -0
  1055. nemo_platform/types/safe_synthesizer/gliner_config_param.py +41 -0
  1056. nemo_platform/types/safe_synthesizer/globals.py +45 -0
  1057. nemo_platform/types/safe_synthesizer/globals_param.py +47 -0
  1058. nemo_platform/types/safe_synthesizer/job_create_params.py +46 -0
  1059. nemo_platform/types/safe_synthesizer/job_get_logs_params.py +30 -0
  1060. nemo_platform/types/safe_synthesizer/job_list_params.py +44 -0
  1061. nemo_platform/types/safe_synthesizer/jobs/__init__.py +21 -0
  1062. nemo_platform/types/safe_synthesizer/jobs/safe_synthesizer_summary.py +95 -0
  1063. nemo_platform/types/safe_synthesizer/jobs/safe_synthesizer_timing.py +41 -0
  1064. nemo_platform/types/safe_synthesizer/ner_config.py +42 -0
  1065. nemo_platform/types/safe_synthesizer/ner_config_param.py +44 -0
  1066. nemo_platform/types/safe_synthesizer/pii_replacer_config.py +40 -0
  1067. nemo_platform/types/safe_synthesizer/pii_replacer_config_param.py +42 -0
  1068. nemo_platform/types/safe_synthesizer/row.py +50 -0
  1069. nemo_platform/types/safe_synthesizer/row_actions.py +33 -0
  1070. nemo_platform/types/safe_synthesizer/row_actions_param.py +35 -0
  1071. nemo_platform/types/safe_synthesizer/row_param.py +53 -0
  1072. nemo_platform/types/safe_synthesizer/safe_synthesizer_job.py +63 -0
  1073. nemo_platform/types/safe_synthesizer/safe_synthesizer_job_config.py +55 -0
  1074. nemo_platform/types/safe_synthesizer/safe_synthesizer_job_config_param.py +56 -0
  1075. nemo_platform/types/safe_synthesizer/safe_synthesizer_jobs_list_filter_param.py +49 -0
  1076. nemo_platform/types/safe_synthesizer/safe_synthesizer_jobs_page.py +37 -0
  1077. nemo_platform/types/safe_synthesizer/safe_synthesizer_jobs_sort_field.py +22 -0
  1078. nemo_platform/types/safe_synthesizer/safe_synthesizer_parameters.py +91 -0
  1079. nemo_platform/types/safe_synthesizer/safe_synthesizer_parameters_param.py +92 -0
  1080. nemo_platform/types/safe_synthesizer/step_definition.py +39 -0
  1081. nemo_platform/types/safe_synthesizer/step_definition_param.py +41 -0
  1082. nemo_platform/types/safe_synthesizer/time_series_parameters.py +73 -0
  1083. nemo_platform/types/safe_synthesizer/time_series_parameters_param.py +74 -0
  1084. nemo_platform/types/safe_synthesizer/training_hyperparams.py +165 -0
  1085. nemo_platform/types/safe_synthesizer/training_hyperparams_param.py +167 -0
  1086. nemo_platform/types/safe_synthesizer/validation_parameters.py +54 -0
  1087. nemo_platform/types/safe_synthesizer/validation_parameters_param.py +54 -0
  1088. nemo_platform/types/secrets/__init__.py +28 -0
  1089. nemo_platform/types/secrets/platform_secret_access_response.py +33 -0
  1090. nemo_platform/types/secrets/platform_secret_admin_rotation_response.py +28 -0
  1091. nemo_platform/types/secrets/platform_secret_response.py +40 -0
  1092. nemo_platform/types/secrets/platform_secret_responses_page.py +37 -0
  1093. nemo_platform/types/secrets/secret_create_params.py +39 -0
  1094. nemo_platform/types/secrets/secret_list_params.py +32 -0
  1095. nemo_platform/types/secrets/secret_update_params.py +32 -0
  1096. nemo_platform/types/shared/__init__.py +50 -0
  1097. nemo_platform/types/shared/api_endpoint_data.py +43 -0
  1098. nemo_platform/types/shared/auth_context.py +48 -0
  1099. nemo_platform/types/shared/auth_discovery_response.py +32 -0
  1100. nemo_platform/types/shared/backend_format.py +22 -0
  1101. nemo_platform/types/shared/datetime_filter.py +33 -0
  1102. nemo_platform/types/shared/delete_response.py +33 -0
  1103. nemo_platform/types/shared/error_response.py +46 -0
  1104. nemo_platform/types/shared/field_error.py +28 -0
  1105. nemo_platform/types/shared/file_storage_type.py +22 -0
  1106. nemo_platform/types/shared/fileset_metadata.py +46 -0
  1107. nemo_platform/types/shared/finetuning_type.py +48 -0
  1108. nemo_platform/types/shared/generic_sort_field.py +22 -0
  1109. nemo_platform/types/shared/http_validation_error.py +27 -0
  1110. nemo_platform/types/shared/linear_layer_spec.py +33 -0
  1111. nemo_platform/types/shared/mamba_config.py +44 -0
  1112. nemo_platform/types/shared/mo_e_config.py +41 -0
  1113. nemo_platform/types/shared/model_metadata_content.py +38 -0
  1114. nemo_platform/types/shared/model_spec.py +111 -0
  1115. nemo_platform/types/shared/oidc_discovery_response.py +42 -0
  1116. nemo_platform/types/shared/pagination_data.py +37 -0
  1117. nemo_platform/types/shared/platform_job_list_result_response.py +27 -0
  1118. nemo_platform/types/shared/platform_job_log.py +34 -0
  1119. nemo_platform/types/shared/platform_job_log_page.py +33 -0
  1120. nemo_platform/types/shared/platform_job_result_response.py +44 -0
  1121. nemo_platform/types/shared/platform_job_status.py +24 -0
  1122. nemo_platform/types/shared/platform_job_status_response.py +48 -0
  1123. nemo_platform/types/shared/platform_job_step_status_response.py +48 -0
  1124. nemo_platform/types/shared/platform_job_task_status_response.py +47 -0
  1125. nemo_platform/types/shared/prompt_data.py +47 -0
  1126. nemo_platform/types/shared/sliding_window_config.py +27 -0
  1127. nemo_platform/types/shared/tool_call_config.py +46 -0
  1128. nemo_platform/types/shared/tool_calling_metadata_content.py +48 -0
  1129. nemo_platform/types/shared/validation_error.py +34 -0
  1130. nemo_platform/types/shared_params/__init__.py +33 -0
  1131. nemo_platform/types/shared_params/api_endpoint_data.py +38 -0
  1132. nemo_platform/types/shared_params/backend_format.py +24 -0
  1133. nemo_platform/types/shared_params/datetime_filter.py +34 -0
  1134. nemo_platform/types/shared_params/file_storage_type.py +24 -0
  1135. nemo_platform/types/shared_params/finetuning_type.py +50 -0
  1136. nemo_platform/types/shared_params/generic_sort_field.py +24 -0
  1137. nemo_platform/types/shared_params/linear_layer_spec.py +35 -0
  1138. nemo_platform/types/shared_params/mamba_config.py +44 -0
  1139. nemo_platform/types/shared_params/mo_e_config.py +41 -0
  1140. nemo_platform/types/shared_params/model_metadata_content.py +39 -0
  1141. nemo_platform/types/shared_params/model_spec.py +113 -0
  1142. nemo_platform/types/shared_params/platform_job_status.py +26 -0
  1143. nemo_platform/types/shared_params/prompt_data.py +48 -0
  1144. nemo_platform/types/shared_params/sliding_window_config.py +29 -0
  1145. nemo_platform/types/shared_params/tool_call_config.py +46 -0
  1146. nemo_platform/types/shared_params/tool_calling_metadata_content.py +48 -0
  1147. nemo_platform/types/workspaces/__init__.py +24 -0
  1148. nemo_platform/types/workspaces/workspace.py +48 -0
  1149. nemo_platform/types/workspaces/workspace_create_params.py +41 -0
  1150. nemo_platform/types/workspaces/workspace_list_params.py +47 -0
  1151. nemo_platform/types/workspaces/workspace_update_params.py +27 -0
  1152. nemo_platform/types/workspaces/workspaces_page.py +37 -0
  1153. nemo_platform/ui/__init__.py +15 -0
  1154. nemo_platform/ui/output.py +109 -0
  1155. nemo_platform/ui/prompts.py +678 -0
  1156. nemo_platform_plugin/.agents/skills/creating-a-plugin/SKILL.md +275 -0
  1157. nemo_platform_plugin/.agents/skills/plugin-config/SKILL.md +168 -0
  1158. nemo_platform_plugin/.agents/skills/plugin-controller/SKILL.md +320 -0
  1159. nemo_platform_plugin/.agents/skills/plugin-entities/SKILL.md +290 -0
  1160. nemo_platform_plugin/.agents/skills/plugin-function/SKILL.md +292 -0
  1161. nemo_platform_plugin/.agents/skills/plugin-inference-middleware/SKILL.md +346 -0
  1162. nemo_platform_plugin/.agents/skills/plugin-job/SKILL.md +247 -0
  1163. nemo_platform_plugin/.agents/skills/plugin-platform-services/SKILL.md +239 -0
  1164. nemo_platform_plugin/.agents/skills/plugin-platform-services/services-reference.md +192 -0
  1165. nemo_platform_plugin/.agents/skills/plugin-service/SKILL.md +181 -0
  1166. nemo_platform_plugin/.agents/skills/plugin-service/crud-example.md +353 -0
  1167. nemo_platform_plugin/.agents/skills/plugin-testing/SKILL.md +206 -0
  1168. nemo_platform_plugin/README.md +43 -0
  1169. nemo_platform_plugin/_base.py +53 -0
  1170. nemo_platform_plugin/_spec_flags.py +573 -0
  1171. nemo_platform_plugin/api/filter.py +189 -0
  1172. nemo_platform_plugin/api/parsed_filter.py +288 -0
  1173. nemo_platform_plugin/api/text_filter.py +291 -0
  1174. nemo_platform_plugin/cli.py +152 -0
  1175. nemo_platform_plugin/cli_errors.py +232 -0
  1176. nemo_platform_plugin/cli_renderer.py +92 -0
  1177. nemo_platform_plugin/commands.py +1433 -0
  1178. nemo_platform_plugin/config.py +844 -0
  1179. nemo_platform_plugin/controller.py +148 -0
  1180. nemo_platform_plugin/dependencies.py +64 -0
  1181. nemo_platform_plugin/discovery.py +484 -0
  1182. nemo_platform_plugin/docs/ARCHITECTURE.md +160 -0
  1183. nemo_platform_plugin/docs/CONFIG.md +151 -0
  1184. nemo_platform_plugin/docs/CONTROLLER.md +209 -0
  1185. nemo_platform_plugin/docs/ENTITY.md +186 -0
  1186. nemo_platform_plugin/docs/INFERENCE_MIDDLEWARE.md +408 -0
  1187. nemo_platform_plugin/docs/JOB.md +237 -0
  1188. nemo_platform_plugin/docs/QUICKSTART.md +306 -0
  1189. nemo_platform_plugin/docs/SERVICE.md +302 -0
  1190. nemo_platform_plugin/entities.py +793 -0
  1191. nemo_platform_plugin/entity.py +79 -0
  1192. nemo_platform_plugin/entity_client.py +54 -0
  1193. nemo_platform_plugin/filter_ops.py +169 -0
  1194. nemo_platform_plugin/function.py +299 -0
  1195. nemo_platform_plugin/function_context.py +61 -0
  1196. nemo_platform_plugin/functions/frames.py +69 -0
  1197. nemo_platform_plugin/functions/routes.py +454 -0
  1198. nemo_platform_plugin/inference_middleware.py +1191 -0
  1199. nemo_platform_plugin/interface.py +28 -0
  1200. nemo_platform_plugin/job.py +370 -0
  1201. nemo_platform_plugin/job_context.py +86 -0
  1202. nemo_platform_plugin/job_results.py +209 -0
  1203. nemo_platform_plugin/jobs/_cli_options.py +204 -0
  1204. nemo_platform_plugin/jobs/api_factory.py +1178 -0
  1205. nemo_platform_plugin/jobs/constants.py +27 -0
  1206. nemo_platform_plugin/jobs/docker.py +76 -0
  1207. nemo_platform_plugin/jobs/exceptions.py +8 -0
  1208. nemo_platform_plugin/jobs/file_manager.py +238 -0
  1209. nemo_platform_plugin/jobs/openapi_utils.py +174 -0
  1210. nemo_platform_plugin/jobs/profile.py +110 -0
  1211. nemo_platform_plugin/jobs/result_manager.py +291 -0
  1212. nemo_platform_plugin/jobs/routes.py +297 -0
  1213. nemo_platform_plugin/jobs/schemas.py +174 -0
  1214. nemo_platform_plugin/refs.py +154 -0
  1215. nemo_platform_plugin/run_dependencies.py +137 -0
  1216. nemo_platform_plugin/scheduler.py +537 -0
  1217. nemo_platform_plugin/schema.py +216 -0
  1218. nemo_platform_plugin/sdk.py +34 -0
  1219. nemo_platform_plugin/seed.py +71 -0
  1220. nemo_platform_plugin/service.py +130 -0
  1221. nemo_platform_plugin/tasks/dispatcher.py +226 -0
  1222. nemo_platform_plugin-0.1.0.dist-info/METADATA +88 -0
  1223. nemo_platform_plugin-0.1.0.dist-info/RECORD +1224 -0
  1224. nemo_platform_plugin-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,1433 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """CLI integration for NemoJob and NemoFunction primitives.
5
+
6
+ Two parallel helpers, one per primitive:
7
+
8
+ - :func:`add_job_commands` — three-verb subgroups
9
+ (``run``/``submit``/``explain``) per :class:`~nemo_platform_plugin.job.NemoJob`,
10
+ routed through :class:`~nemo_platform_plugin.scheduler.NemoJobScheduler`.
11
+ - :func:`add_function_commands` — two-verb subgroups
12
+ (``run``/``submit``) per :class:`~nemo_platform_plugin.function.NemoFunction`.
13
+ Functions don't have an ``explain`` verb because their only schema
14
+ is :attr:`~nemo_platform_plugin.function.NemoFunction.spec_schema` and that's
15
+ introspected through ``--help`` directly.
16
+
17
+ :func:`add_job_commands` is the bridge between the ``nemo.jobs`` and
18
+ ``nemo.cli`` surfaces. The platform calls it at startup for each plugin that
19
+ has registered both a CLI group and jobs, injecting a generated **sub-group**
20
+ for every job into the plugin's :class:`typer.Typer` group. Each sub-group
21
+ exposes three verbs — ``run``, ``submit``, ``explain`` — matching
22
+ :class:`~nemo_platform_plugin.scheduler.NemoJobScheduler`.
23
+
24
+ Plugin authors do **not** call this themselves — it is called automatically
25
+ by the platform's CLI loader. The result is that each job becomes available
26
+ as::
27
+
28
+ nemo <plugin> <job-name> run [--config ...] [--config-file ...]
29
+ nemo <plugin> <job-name> submit [--profile ...] [--cluster ...] [-o ...]
30
+ nemo <plugin> <job-name> explain [--profile ...] [--cluster ...]
31
+
32
+ The **bare form** ``nemo <plugin> <job-name>`` prints usage and exits with
33
+ status 1. No implicit default verb — the submitter's choice of execution
34
+ target is always explicit. This breaks the previous one-line form; the
35
+ fix is typing ``run`` (or ``submit``) explicitly.
36
+
37
+ Phase 1 MR 1.2c delivers the CLI shape. ``submit`` and ``explain`` delegate
38
+ to :class:`NemoJobScheduler` stubs that raise
39
+ :class:`NotImplementedError`; MR 1.3 and MR 1.4 wire them. ``run`` works
40
+ end-to-end today.
41
+
42
+ Generated command interface
43
+ ---------------------------
44
+
45
+ ``run``
46
+ Execute the job in-process. Accepts ``--config <json>`` (default ``{}``)
47
+ and ``--config-file <path>`` (takes precedence over ``--config``). The
48
+ scheduler validates against :attr:`~nemo_platform_plugin.job.NemoJob.spec_schema`
49
+ / :attr:`~nemo_platform_plugin.job.NemoJob.input_spec_schema` when declared.
50
+
51
+ ``submit``
52
+ Submit the job to a cluster. Phase 1 MR 1.3 wires this.
53
+
54
+ ``explain``
55
+ Print the job's spec / options schemas. Phase 1 MR 1.4 wires this.
56
+
57
+ Example
58
+ -------
59
+
60
+ Given::
61
+
62
+ class SayHelloJob(NemoJob):
63
+ name = "say-hello"
64
+ description = "Greet a name."
65
+
66
+ def run(self, config: dict) -> dict:
67
+ return {"result": f"Hello, {config.get('name', 'world')}!"}
68
+
69
+ The platform generates::
70
+
71
+ $ nemo example say-hello run --config '{"name": "Claude"}'
72
+ {
73
+ "result": "Hello, Claude!"
74
+ }
75
+
76
+ $ nemo example say-hello
77
+ Usage: nemo example say-hello [OPTIONS] COMMAND [ARGS]...
78
+ ...
79
+ $ echo $?
80
+ 1
81
+ """
82
+
83
+ from __future__ import annotations
84
+
85
+ import asyncio
86
+ import inspect
87
+ import json
88
+ import logging
89
+ import os
90
+ from collections.abc import AsyncIterator, Callable, Iterable, Mapping
91
+ from pathlib import Path
92
+ from typing import Any, Literal, Optional, cast
93
+
94
+ import httpx
95
+ import typer
96
+ from nemo_platform_plugin._spec_flags import (
97
+ UNSET,
98
+ SpecLeafField,
99
+ build_callback_signature,
100
+ build_epilog,
101
+ build_overlay,
102
+ deep_merge,
103
+ kw,
104
+ walk_spec_leaves,
105
+ )
106
+ from nemo_platform_plugin.cli import NemoCLI
107
+ from nemo_platform_plugin.cli_errors import print_http_request_error, print_http_status_error
108
+ from nemo_platform_plugin.cli_renderer import CLIRenderer, RendererContext
109
+ from nemo_platform_plugin.function import NemoFunction, returns_async_iterator
110
+ from nemo_platform_plugin.function_context import FunctionContext
111
+ from nemo_platform_plugin.functions.routes import DEFAULT_FUNCTION_PATH, NDJSON_MEDIA_TYPE
112
+ from nemo_platform_plugin.job import NemoJob
113
+ from nemo_platform_plugin.jobs._cli_options import (
114
+ load_options_file,
115
+ load_spec_file,
116
+ merge_options,
117
+ parse_dotted_kv_list,
118
+ )
119
+ from nemo_platform_plugin.run_dependencies import LocalRunError
120
+ from nemo_platform_plugin.scheduler import NemoJobScheduler
121
+ from pydantic import BaseModel, ValidationError
122
+
123
+ logger = logging.getLogger(__name__)
124
+
125
+ # Submit host resolution for both functions and jobs:
126
+ # ``--base-url`` > ``--cluster`` (resolved from CLI config) > active context
127
+ # base URL > ``$NMP_BASE_URL`` > localhost.
128
+ _DEFAULT_BASE_URL_ENV_VAR = "NMP_BASE_URL"
129
+ _DEFAULT_BASE_URL = "http://localhost:8080"
130
+
131
+ # Rich-help panels for the function and job CLIs. Mirror PR #160's
132
+ # panel names but scoped per primitive so jobs and functions sharing a
133
+ # plugin still group cleanly when both are documented in --help.
134
+ _PANEL_SPEC_SOURCE: str = "Spec Source"
135
+ _PANEL_FUNCTION_SPEC: str = "Function Spec"
136
+ _PANEL_JOB_SPEC: str = "Job Spec"
137
+ _PANEL_SUBMISSION: str = "Submission"
138
+
139
+ # Static flag names declared by each function verb. Spec fields whose
140
+ # names collide with these are dropped from the auto-generated flag
141
+ # set; they remain reachable via ``--spec`` / ``--spec-file``. ``run``
142
+ # is deliberately permissive — only the JSON-passing flags and the
143
+ # context-input ``workspace`` flag are reserved. ``submit`` layers on
144
+ # the URL-routing flags + the request-id surface.
145
+ _FN_RUN_RESERVED_FLAGS: frozenset[str] = frozenset({"spec", "spec_file", "workspace"})
146
+ _FN_SUBMIT_RESERVED_FLAGS: frozenset[str] = _FN_RUN_RESERVED_FLAGS | frozenset({"cluster", "base_url", "request_id"})
147
+
148
+ # Static flag names declared by each job verb. ``run`` reserves the
149
+ # spec-source flags plus the deprecated ``--config`` / ``--config-file``
150
+ # aliases (kept during the rename transition). ``submit`` layers on the
151
+ # submission-routing flags (``--profile`` / ``--cluster`` / ``--base-url``
152
+ # / ``--workspace``) and the options-passthrough flags (``-o`` /
153
+ # ``--options-file``). Reserved spec fields remain reachable via
154
+ # ``--spec`` / ``--spec-file`` JSON.
155
+ _JOB_RUN_RESERVED_FLAGS: frozenset[str] = frozenset({"spec", "spec_file", "config", "config_file"})
156
+ _JOB_SUBMIT_RESERVED_FLAGS: frozenset[str] = _JOB_RUN_RESERVED_FLAGS | frozenset(
157
+ {"options", "options_file", "profile", "cluster", "base_url", "workspace"}
158
+ )
159
+
160
+
161
+ # ---------------------------------------------------------------------------
162
+ # Renderer plumbing
163
+ # ---------------------------------------------------------------------------
164
+
165
+
166
+ def _output_format_is_json(typer_ctx: typer.Context | None) -> bool:
167
+ """Return True when the global ``--output-format json`` flag is set.
168
+
169
+ Read from ``typer_ctx.obj.overrides`` — the ``CLIContext`` populated by
170
+ the top-level :func:`nemo_platform_ext.cli.app.main` callback. Defensive
171
+ against non-``CLIContext`` objects so plugins exercising the CLI directly
172
+ in tests (with ``ctx.obj = None``) still work.
173
+ """
174
+ if typer_ctx is None:
175
+ return False
176
+ state = typer_ctx.obj
177
+ if state is None:
178
+ return False
179
+ overrides = getattr(state, "overrides", None)
180
+ if not isinstance(overrides, dict):
181
+ return False
182
+ return overrides.get("output_format") == "json"
183
+
184
+
185
+ def _make_renderer_context(
186
+ *,
187
+ cli_kwargs: Mapping[str, Any],
188
+ verb: Literal["run", "submit"],
189
+ is_local: bool,
190
+ ) -> RendererContext:
191
+ """Build the per-invocation :class:`RendererContext` passed to renderer methods."""
192
+ from rich.console import Console
193
+
194
+ return RendererContext(console=Console(), cli_kwargs=cli_kwargs, verb=verb, is_local=is_local)
195
+
196
+
197
+ async def _drive_async_renderer(
198
+ stream: AsyncIterator[Any],
199
+ renderer_cls: type[CLIRenderer],
200
+ *,
201
+ rctx: RendererContext,
202
+ ) -> CLIRenderer:
203
+ """Drive *renderer_cls*'s ``on_start`` + ``on_frame`` over an async stream.
204
+
205
+ Returns the renderer instance so the sync caller (the one calling
206
+ :func:`asyncio.run`) can fire :meth:`CLIRenderer.on_complete` *after*
207
+ the loop tears down — important because renderers commonly use
208
+ event-loop-bound libraries (e.g. ``prompt_toolkit.Application.run``)
209
+ in ``on_complete``, and those use their own :func:`asyncio.run` which
210
+ raises ``RuntimeError: asyncio.run() cannot be called from a running
211
+ event loop`` when nested.
212
+
213
+ :meth:`CLIRenderer.on_error` is fired in-loop because the exception
214
+ is most usefully handled where it surfaced; the exception still
215
+ propagates so the caller sees it.
216
+ """
217
+ renderer = renderer_cls()
218
+ renderer.on_start(ctx=rctx)
219
+ try:
220
+ async for frame in stream:
221
+ renderer.on_frame(frame, ctx=rctx)
222
+ except BaseException as exc:
223
+ renderer.on_error(exc, ctx=rctx)
224
+ raise
225
+ return renderer
226
+
227
+
228
+ def _drive_sync_renderer(
229
+ line_iter: Iterable[str],
230
+ renderer_cls: type[CLIRenderer],
231
+ *,
232
+ rctx: RendererContext,
233
+ ) -> CLIRenderer:
234
+ """Drive *renderer_cls*'s ``on_start`` + ``on_frame`` over a sync line iterator.
235
+
236
+ Returns the renderer; the caller fires :meth:`CLIRenderer.on_complete`.
237
+ Symmetric with :func:`_drive_async_renderer` so all three drivers obey
238
+ the same contract: in-loop work happens here (``on_start`` / per-frame
239
+ / ``on_error``), the post-stream summary happens at the call site after
240
+ this returns. That contract matters even for sync drivers: it keeps the
241
+ plugin-author mental model consistent and avoids re-introducing
242
+ nested-event-loop hazards if a sync driver is ever wrapped in an async
243
+ context.
244
+
245
+ Each non-empty NDJSON line is parsed as JSON and passed to
246
+ :meth:`CLIRenderer.on_frame`. Lines that fail to parse pass through as
247
+ raw strings — renderers can decide how to handle non-JSON output.
248
+ """
249
+ renderer = renderer_cls()
250
+ renderer.on_start(ctx=rctx)
251
+ try:
252
+ for line in line_iter:
253
+ if not line:
254
+ continue
255
+ try:
256
+ frame: object = json.loads(line)
257
+ except json.JSONDecodeError:
258
+ frame = line
259
+ renderer.on_frame(frame, ctx=rctx)
260
+ except BaseException as exc:
261
+ renderer.on_error(exc, ctx=rctx)
262
+ raise
263
+ return renderer
264
+
265
+
266
+ def _drive_single_value_renderer(
267
+ callable_: Callable[[], Any],
268
+ renderer_cls: type[CLIRenderer],
269
+ *,
270
+ rctx: RendererContext,
271
+ ) -> CLIRenderer:
272
+ """Drive *renderer_cls* around a synchronous, non-streaming result.
273
+
274
+ Used for jobs (which return a single dict). The result is passed to
275
+ :meth:`CLIRenderer.on_frame` once. Returns the renderer so the caller
276
+ can fire :meth:`CLIRenderer.on_complete` — same contract as the
277
+ streaming drivers.
278
+ """
279
+ renderer = renderer_cls()
280
+ renderer.on_start(ctx=rctx)
281
+ try:
282
+ result = callable_()
283
+ renderer.on_frame(result, ctx=rctx)
284
+ except BaseException as exc:
285
+ renderer.on_error(exc, ctx=rctx)
286
+ raise
287
+ return renderer
288
+
289
+
290
+ def add_job_commands(
291
+ cli_app: typer.Typer,
292
+ jobs: dict[str, type[NemoJob]],
293
+ *,
294
+ cli: NemoCLI | None = None,
295
+ ) -> None:
296
+ """Inject three-verb subcommand groups for each job into *cli_app*.
297
+
298
+ Each entry in *jobs* produces one :class:`typer.Typer` sub-group
299
+ registered under :attr:`~nemo_platform_plugin.job.NemoJob.name` in a ``"Jobs"``
300
+ rich help panel. The sub-group owns ``run`` / ``submit`` / ``explain``
301
+ commands.
302
+
303
+ Args:
304
+ cli_app: The plugin's :class:`typer.Typer` group to inject
305
+ sub-groups into. Typically the value returned by
306
+ :meth:`~nemo_platform_plugin.cli.NemoCLI.get_cli`.
307
+ jobs: Mapping of entry-point key → :class:`~nemo_platform_plugin.job.NemoJob`
308
+ subclass, already filtered to the relevant plugin. Typically a
309
+ subset of the dict returned by
310
+ :func:`~nemo_platform_plugin.discovery.discover_jobs`.
311
+ cli: Optional plugin :class:`~nemo_platform_plugin.cli.NemoCLI` instance. When
312
+ supplied, :meth:`~nemo_platform_plugin.cli.NemoCLI.update_job_cli` is
313
+ invoked once per job after default verb registration and before
314
+ the sub-group is mounted, giving the plugin a chance to amend
315
+ the auto-generated CLI surface.
316
+ """
317
+ scheduler = NemoJobScheduler()
318
+ for job_cls in jobs.values():
319
+ _register_job_subgroup(cli_app, job_cls, scheduler, cli=cli)
320
+
321
+
322
+ def _register_job_subgroup(
323
+ cli_app: typer.Typer,
324
+ job_cls: type[NemoJob],
325
+ scheduler: NemoJobScheduler,
326
+ *,
327
+ cli: NemoCLI | None = None,
328
+ ) -> None:
329
+ """Register a ``<job-name>`` sub-group with run / submit / explain verbs."""
330
+ job_group = typer.Typer(
331
+ name=job_cls.name,
332
+ help=job_cls.description or f"Manage the {job_cls.name} job.",
333
+ no_args_is_help=False, # we override bare behavior to exit non-zero
334
+ )
335
+
336
+ @job_group.callback(invoke_without_command=True)
337
+ def _root(ctx: typer.Context) -> None: # pragma: no cover - trivial delegation
338
+ """Stub callback — prints usage and exits 1 when no verb is given."""
339
+ if ctx.invoked_subcommand is None:
340
+ typer.echo(ctx.get_help())
341
+ raise typer.Exit(code=1)
342
+
343
+ _add_run_command(job_group, job_cls, scheduler, cli=cli)
344
+ _add_submit_command(job_group, job_cls, scheduler, cli=cli)
345
+ _add_explain_command(job_group, job_cls, scheduler)
346
+
347
+ if cli is not None:
348
+ cli.update_job_cli(job_cls, job_group)
349
+
350
+ cli_app.add_typer(job_group, name=job_cls.name, rich_help_panel="Jobs")
351
+
352
+
353
+ # ---------------------------------------------------------------------------
354
+ # run — local execution, wired via NemoJobScheduler.run_local
355
+ # ---------------------------------------------------------------------------
356
+
357
+
358
+ def _job_input_schema(job_cls: type[NemoJob]) -> type[BaseModel] | None:
359
+ """Pick the schema that the submitter's input is validated against.
360
+
361
+ Mirrors the precedence used by
362
+ :meth:`~nemo_platform_plugin.scheduler.NemoJobScheduler._validate_and_compile`:
363
+ :attr:`~nemo_platform_plugin.job.NemoJob.input_spec_schema` when declared,
364
+ else :attr:`~nemo_platform_plugin.job.NemoJob.spec_schema`. Both ``run`` and
365
+ ``submit`` accept the same shape from the user, so we walk a single
366
+ schema for both verbs. Returns ``None`` when neither attribute is
367
+ declared — the auto-flag generator treats ``None`` as "no leaves",
368
+ keeping legacy schema-less jobs unchanged.
369
+ """
370
+ return job_cls.input_spec_schema or job_cls.spec_schema
371
+
372
+
373
+ def _add_run_command(
374
+ group: typer.Typer,
375
+ job_cls: type[NemoJob],
376
+ scheduler: NemoJobScheduler,
377
+ *,
378
+ cli: NemoCLI | None = None,
379
+ ) -> None:
380
+ """Register the ``run`` verb. Generates per-field flags from the input schema.
381
+
382
+ Each scalar leaf in :func:`_job_input_schema` becomes a Typer option
383
+ named after its dotted path, kebab-cased per segment (``--name``,
384
+ ``--target.url``). Precedence at runtime is ``--spec-file`` (base)
385
+ → ``--spec`` JSON (overlay) → per-field flags (top overlay), with
386
+ the deprecated ``--config`` / ``--config-file`` aliases routed
387
+ through the same precedence as ``--spec`` / ``--spec-file``.
388
+
389
+ When *cli* supplies a renderer via ``get_job_renderer(verb="run")`` (and
390
+ ``--output-format json`` is not set), the renderer's lifecycle wraps the
391
+ synchronous ``run_local`` call: ``on_start`` → ``on_frame(result)`` →
392
+ ``on_complete``. The default-printer fallback echoes the dict result
393
+ when no renderer is supplied.
394
+ """
395
+ schema = _job_input_schema(job_cls)
396
+ leaves = walk_spec_leaves(schema, reserved=_JOB_RUN_RESERVED_FLAGS)
397
+
398
+ def _run(typer_ctx: typer.Context, **kwargs: object) -> None:
399
+ original_kwargs = dict(kwargs)
400
+ spec_str: str = cast(str, kwargs.pop("spec", "{}"))
401
+ spec_file: Path | None = cast("Path | None", kwargs.pop("spec_file", None))
402
+ config: str | None = cast("str | None", kwargs.pop("config", None))
403
+ config_file: Path | None = cast("Path | None", kwargs.pop("config_file", None))
404
+
405
+ effective_spec_str = config if config is not None else spec_str
406
+ effective_spec_file = config_file if config_file is not None else spec_file
407
+ base = _load_spec(effective_spec_str, effective_spec_file)
408
+ overlay = build_overlay(leaves, kwargs, unset_sentinel=UNSET)
409
+ data = deep_merge(base, overlay)
410
+ logger.debug("Running job %r locally with spec %r", job_cls.name, data)
411
+ sdk, async_sdk = _resolve_local_cli_sdks(typer_ctx)
412
+
413
+ renderer_cls: type[CLIRenderer] | None = None
414
+ if cli is not None and not _output_format_is_json(typer_ctx):
415
+ renderer_cls = cli.get_job_renderer(job_cls, verb="run")
416
+
417
+ def _do_run() -> Any:
418
+ return scheduler.run_local(job_cls, data, sdk=sdk, async_sdk=async_sdk)
419
+
420
+ renderer: CLIRenderer | None = None
421
+ rctx: RendererContext | None = None
422
+ try:
423
+ if renderer_cls is not None:
424
+ rctx = _make_renderer_context(
425
+ cli_kwargs=original_kwargs,
426
+ verb="run",
427
+ is_local=True,
428
+ )
429
+ renderer = _drive_single_value_renderer(_do_run, renderer_cls, rctx=rctx)
430
+ else:
431
+ result = _do_run()
432
+ typer.echo(json.dumps(result, indent=2))
433
+ except LocalRunError as exc:
434
+ typer.echo(f"Error: {exc}", err=True)
435
+ raise typer.Exit(code=1) from exc
436
+
437
+ # on_complete fires after the driver returns, in the same contract
438
+ # the async renderer driver follows — see _drive_sync_renderer.
439
+ if renderer is not None and rctx is not None:
440
+ renderer.on_complete(ctx=rctx)
441
+
442
+ help_text = f"Run {job_cls.name} locally, in-process."
443
+ _run.__signature__ = _build_job_run_signature(leaves) # type: ignore[attr-defined]
444
+ group.command(name="run", help=help_text)(_run)
445
+
446
+
447
+ def _build_job_run_signature(leaves: list[SpecLeafField]) -> inspect.Signature:
448
+ """Compose the synthetic signature for the job ``run`` verb.
449
+
450
+ Static flags (``--spec`` / ``--spec-file``) come first under the
451
+ ``Spec Source`` panel, followed by the auto-generated per-field
452
+ flags under ``Job Spec``, then the hidden ``--config`` /
453
+ ``--config-file`` deprecated aliases.
454
+ """
455
+ static_params = [
456
+ # ``typer.Context`` is auto-injected by Click via ``pass_context``,
457
+ # which passes it as the first positional argument. Hand-built
458
+ # rather than via ``kw()`` because ``kw()`` only emits
459
+ # ``KEYWORD_ONLY`` params (which Click's positional injection
460
+ # would reject).
461
+ inspect.Parameter(
462
+ "typer_ctx",
463
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
464
+ annotation=typer.Context,
465
+ ),
466
+ kw(
467
+ "spec",
468
+ str,
469
+ typer.Option(
470
+ "{}",
471
+ "--spec",
472
+ help="Spec as a JSON string.",
473
+ rich_help_panel=_PANEL_SPEC_SOURCE,
474
+ ),
475
+ ),
476
+ kw(
477
+ "spec_file",
478
+ Optional[Path],
479
+ typer.Option(
480
+ None,
481
+ "--spec-file",
482
+ help="Path to a YAML or JSON spec file (used as base; per-flag values override).",
483
+ rich_help_panel=_PANEL_SPEC_SOURCE,
484
+ ),
485
+ ),
486
+ ]
487
+ # Deprecated aliases — kept for the transition period (MR 1.3b).
488
+ # Trailing so they sort below the auto-generated panel in --help,
489
+ # though they're hidden anyway and only matter for backwards-compatible
490
+ # invocations.
491
+ trailing_params = [
492
+ kw(
493
+ "config",
494
+ Optional[str],
495
+ typer.Option(
496
+ None,
497
+ "--config",
498
+ help="(Deprecated — use --spec.) Spec as a JSON string.",
499
+ hidden=True,
500
+ ),
501
+ ),
502
+ kw(
503
+ "config_file",
504
+ Optional[Path],
505
+ typer.Option(
506
+ None,
507
+ "--config-file",
508
+ help="(Deprecated — use --spec-file.) Path to a JSON spec file.",
509
+ hidden=True,
510
+ ),
511
+ ),
512
+ ]
513
+ return build_callback_signature(
514
+ static_params,
515
+ leaves,
516
+ rich_help_panel=_PANEL_JOB_SPEC,
517
+ trailing_params=trailing_params,
518
+ )
519
+
520
+
521
+ # ---------------------------------------------------------------------------
522
+ # submit — stub delegate to scheduler.submit_remote (wired in MR 1.3)
523
+ # ---------------------------------------------------------------------------
524
+
525
+
526
+ def _add_submit_command(
527
+ group: typer.Typer,
528
+ job_cls: type[NemoJob],
529
+ scheduler: NemoJobScheduler,
530
+ *,
531
+ cli: NemoCLI | None = None,
532
+ ) -> None:
533
+ """Register the ``submit`` verb. Generates per-field flags + static submit flags.
534
+
535
+ Static flags (``--spec`` / ``--spec-file``, ``-o`` / ``--options-file``,
536
+ ``--profile``, ``--cluster``, ``--base-url``, ``--workspace``, plus the
537
+ hidden ``--config`` / ``--config-file`` deprecated aliases) come first;
538
+ spec fields whose names collide with any of those are dropped from
539
+ the auto-generated set and remain reachable via ``--spec`` /
540
+ ``--spec-file``.
541
+
542
+ When *cli* supplies a renderer via ``get_job_renderer(verb="submit")``
543
+ (and ``--output-format json`` is not set), the renderer's lifecycle
544
+ wraps the ``submit_remote`` call: ``on_start`` → ``on_frame(result)`` →
545
+ ``on_complete``.
546
+ """
547
+ schema = _job_input_schema(job_cls)
548
+ leaves = walk_spec_leaves(schema, reserved=_JOB_SUBMIT_RESERVED_FLAGS)
549
+
550
+ def _submit(typer_ctx: typer.Context, **kwargs: object) -> None:
551
+ original_kwargs = dict(kwargs)
552
+ spec_str: str = cast(str, kwargs.pop("spec", "{}"))
553
+ spec_file: Path | None = cast("Path | None", kwargs.pop("spec_file", None))
554
+ options: list[str] = cast("list[str]", kwargs.pop("options", []))
555
+ options_file: Path | None = cast("Path | None", kwargs.pop("options_file", None))
556
+ profile: str | None = cast("str | None", kwargs.pop("profile", None))
557
+ cluster: str | None = cast("str | None", kwargs.pop("cluster", None))
558
+ base_url: str | None = cast("str | None", kwargs.pop("base_url", None))
559
+ workspace: str = cast(str, kwargs.pop("workspace", "default"))
560
+ config: str | None = cast("str | None", kwargs.pop("config", None))
561
+ config_file: Path | None = cast("Path | None", kwargs.pop("config_file", None))
562
+
563
+ effective_spec_str = config if config is not None else spec_str
564
+ effective_spec_file = config_file if config_file is not None else spec_file
565
+ base = _load_spec(effective_spec_str, effective_spec_file)
566
+ overlay = build_overlay(leaves, kwargs, unset_sentinel=UNSET)
567
+ spec_data = deep_merge(base, overlay)
568
+
569
+ try:
570
+ merged_options = _merge_options_inputs(options, options_file)
571
+ except ValueError as exc:
572
+ typer.echo(f"Error: {exc}", err=True)
573
+ raise typer.Exit(code=1) from exc
574
+
575
+ renderer_cls: type[CLIRenderer] | None = None
576
+ if cli is not None and not _output_format_is_json(typer_ctx):
577
+ renderer_cls = cli.get_job_renderer(job_cls, verb="submit")
578
+
579
+ def _do_submit() -> Any:
580
+ return scheduler.submit_remote(
581
+ job_cls,
582
+ spec_data,
583
+ base_url=_resolve_submit_base_url(typer_ctx, base_url=base_url, cluster=cluster),
584
+ workspace=workspace,
585
+ profile=profile,
586
+ options=merged_options or None,
587
+ )
588
+
589
+ renderer: CLIRenderer | None = None
590
+ rctx: RendererContext | None = None
591
+ try:
592
+ if renderer_cls is not None:
593
+ rctx = _make_renderer_context(
594
+ cli_kwargs=original_kwargs,
595
+ verb="submit",
596
+ is_local=False,
597
+ )
598
+ renderer = _drive_single_value_renderer(_do_submit, renderer_cls, rctx=rctx)
599
+ else:
600
+ result = _do_submit()
601
+ typer.echo(json.dumps(result, indent=2))
602
+ except (NotImplementedError, ValueError) as exc:
603
+ typer.echo(f"Error: {exc}", err=True)
604
+ raise typer.Exit(code=2) from exc
605
+ except httpx.HTTPStatusError as exc:
606
+ print_http_status_error(exc, action=f"submit {job_cls.name}")
607
+ raise typer.Exit(code=2) from exc
608
+ except httpx.RequestError as exc:
609
+ print_http_request_error(exc, action=f"submit {job_cls.name}")
610
+ raise typer.Exit(code=2) from exc
611
+ except httpx.HTTPError as exc:
612
+ typer.echo(f"Error: submit {job_cls.name} failed: {exc}", err=True)
613
+ raise typer.Exit(code=2) from exc
614
+
615
+ if renderer is not None and rctx is not None:
616
+ renderer.on_complete(ctx=rctx)
617
+
618
+ help_text = f"Submit {job_cls.name} to a cluster."
619
+ _submit.__signature__ = _build_job_submit_signature(leaves) # type: ignore[attr-defined]
620
+ group.command(name="submit", help=help_text)(_submit)
621
+
622
+
623
+ def _build_job_submit_signature(leaves: list[SpecLeafField]) -> inspect.Signature:
624
+ """Compose the synthetic signature for the job ``submit`` verb."""
625
+ static_params = [
626
+ inspect.Parameter(
627
+ "typer_ctx",
628
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
629
+ annotation=typer.Context,
630
+ ),
631
+ kw(
632
+ "spec",
633
+ str,
634
+ typer.Option(
635
+ "{}",
636
+ "--spec",
637
+ help="Spec as a JSON string.",
638
+ rich_help_panel=_PANEL_SPEC_SOURCE,
639
+ ),
640
+ ),
641
+ kw(
642
+ "spec_file",
643
+ Optional[Path],
644
+ typer.Option(
645
+ None,
646
+ "--spec-file",
647
+ help="Path to a YAML or JSON spec file (used as base; per-flag values override).",
648
+ rich_help_panel=_PANEL_SPEC_SOURCE,
649
+ ),
650
+ ),
651
+ kw(
652
+ "options",
653
+ list[str],
654
+ typer.Option(
655
+ [], # noqa: B006 — Typer evaluates the default lazily per invocation
656
+ "-o",
657
+ help="Backend option override, 'backend.key=value' (repeatable).",
658
+ rich_help_panel=_PANEL_SUBMISSION,
659
+ ),
660
+ ),
661
+ kw(
662
+ "options_file",
663
+ Optional[Path],
664
+ typer.Option(
665
+ None,
666
+ "--options-file",
667
+ help="Path to a YAML or JSON options file (nested by backend name).",
668
+ rich_help_panel=_PANEL_SUBMISSION,
669
+ ),
670
+ ),
671
+ kw(
672
+ "profile",
673
+ Optional[str],
674
+ typer.Option(
675
+ None,
676
+ "--profile",
677
+ help=(
678
+ "Execution profile (operator-configured). Required unless the active "
679
+ "cluster has a 'default' profile."
680
+ ),
681
+ rich_help_panel=_PANEL_SUBMISSION,
682
+ ),
683
+ ),
684
+ kw(
685
+ "cluster",
686
+ Optional[str],
687
+ typer.Option(
688
+ None,
689
+ "--cluster",
690
+ help="Configured cluster name to resolve via the NeMo CLI config.",
691
+ rich_help_panel=_PANEL_SUBMISSION,
692
+ ),
693
+ ),
694
+ kw(
695
+ "base_url",
696
+ Optional[str],
697
+ typer.Option(
698
+ None,
699
+ "--base-url",
700
+ help=("Explicit plugin-service base URL (overrides --cluster and all other submit host resolution)."),
701
+ rich_help_panel=_PANEL_SUBMISSION,
702
+ ),
703
+ ),
704
+ kw(
705
+ "workspace",
706
+ str,
707
+ typer.Option(
708
+ "default",
709
+ "--workspace",
710
+ help="Workspace scope for the submission.",
711
+ rich_help_panel=_PANEL_SUBMISSION,
712
+ ),
713
+ ),
714
+ ]
715
+ trailing_params = [
716
+ kw(
717
+ "config",
718
+ Optional[str],
719
+ typer.Option(
720
+ None,
721
+ "--config",
722
+ help="(Deprecated — use --spec.) Spec as a JSON string.",
723
+ hidden=True,
724
+ ),
725
+ ),
726
+ kw(
727
+ "config_file",
728
+ Optional[Path],
729
+ typer.Option(
730
+ None,
731
+ "--config-file",
732
+ help="(Deprecated — use --spec-file.) Path to a JSON spec file.",
733
+ hidden=True,
734
+ ),
735
+ ),
736
+ ]
737
+ return build_callback_signature(
738
+ static_params,
739
+ leaves,
740
+ rich_help_panel=_PANEL_JOB_SPEC,
741
+ trailing_params=trailing_params,
742
+ )
743
+
744
+
745
+ # ---------------------------------------------------------------------------
746
+ # explain — stub delegate to scheduler.explain (wired in MR 1.4)
747
+ # ---------------------------------------------------------------------------
748
+
749
+
750
+ def _add_explain_command(
751
+ group: typer.Typer,
752
+ job_cls: type[NemoJob],
753
+ scheduler: NemoJobScheduler,
754
+ ) -> None:
755
+ def _explain(
756
+ profile: Optional[str] = typer.Option(
757
+ None,
758
+ "--profile",
759
+ help="Annotate the bundle with this profile. Profile metadata lands in MR 1.4b.",
760
+ ),
761
+ cluster: Optional[str] = typer.Option(
762
+ None,
763
+ "--cluster",
764
+ help="Accepted for forward compatibility; unused in MR 1.4a.",
765
+ ),
766
+ ) -> None:
767
+ """Print schemas for the job (spec / input_spec / options)."""
768
+ del cluster # reserved for MR 1.4b when /execution-profiles fetch lands
769
+ bundle = scheduler.explain(job_cls, profile=profile)
770
+ typer.echo(json.dumps(bundle, indent=2))
771
+
772
+ _explain.__doc__ = f"Show the schemas for {job_cls.name}."
773
+ group.command(name="explain", help=_explain.__doc__)(_explain)
774
+
775
+
776
+ # ---------------------------------------------------------------------------
777
+ # Shared helpers
778
+ # ---------------------------------------------------------------------------
779
+
780
+
781
+ def _load_spec(spec_str: str, spec_file: Path | None) -> dict:
782
+ """Load the spec dict from ``--spec`` JSON or ``--spec-file`` path.
783
+
784
+ ``--spec-file`` wins when both are provided. Supports YAML or JSON
785
+ (extension-driven). Raises :class:`typer.Exit` with a helpful error
786
+ message on malformed content **or** on top-level non-mapping
787
+ payloads (e.g. ``--spec '[]'``); the downstream
788
+ :func:`~nemo_platform_plugin._spec_flags.deep_merge` assumes a dict and
789
+ would otherwise fail with a raw ``TypeError`` after a per-field
790
+ overlay was applied.
791
+ """
792
+ try:
793
+ if spec_file is not None:
794
+ loaded = load_spec_file(spec_file)
795
+ else:
796
+ loaded = json.loads(spec_str)
797
+ except (json.JSONDecodeError, ValueError) as exc:
798
+ typer.echo(f"Error: invalid spec — {exc}", err=True)
799
+ raise typer.Exit(code=1) from exc
800
+ if not isinstance(loaded, dict):
801
+ typer.echo(
802
+ f"Error: invalid spec — expected a JSON/YAML object, got {type(loaded).__name__}.",
803
+ err=True,
804
+ )
805
+ raise typer.Exit(code=1)
806
+ return loaded
807
+
808
+
809
+ def _merge_options_inputs(options: list[str], options_file: Path | None) -> dict:
810
+ """Combine ``--options-file`` contents (base) with ``-o`` overrides (overlay).
811
+
812
+ Precedence: individual ``-o`` flags win over values in ``--options-file``.
813
+ Both inputs are optional; an empty result is fine (the submit body
814
+ omits the ``options`` field when the merged dict is empty).
815
+ """
816
+ base: dict = load_options_file(options_file) if options_file is not None else {}
817
+ overlay: dict = parse_dotted_kv_list(options)
818
+ return merge_options(base, overlay)
819
+
820
+
821
+ # ---------------------------------------------------------------------------
822
+ # NemoFunction CLI — two verbs (run / submit), no `explain`
823
+ # ---------------------------------------------------------------------------
824
+
825
+
826
+ def add_function_commands(
827
+ cli_app: typer.Typer,
828
+ functions: dict[str, type[NemoFunction]],
829
+ *,
830
+ cli: NemoCLI | None = None,
831
+ ) -> None:
832
+ """Inject two-verb subcommand groups for each function into *cli_app*.
833
+
834
+ Each entry produces one :class:`typer.Typer` sub-group registered
835
+ under :attr:`~nemo_platform_plugin.function.NemoFunction.name` in a
836
+ ``"Functions"`` rich help panel. The sub-group owns ``run`` and
837
+ ``submit`` commands. There is no ``explain`` verb — functions
838
+ have a single ``spec_schema`` and ``--help`` is the introspection
839
+ surface.
840
+
841
+ Args:
842
+ cli_app: The plugin's :class:`typer.Typer` group to inject
843
+ sub-groups into. Typically the value returned by
844
+ :meth:`~nemo_platform_plugin.cli.NemoCLI.get_cli`.
845
+ functions: Mapping of entry-point key →
846
+ :class:`~nemo_platform_plugin.function.NemoFunction` subclass,
847
+ already filtered to the relevant plugin. Typically a
848
+ subset of the dict returned by
849
+ :func:`~nemo_platform_plugin.discovery.discover_functions`.
850
+ cli: Optional plugin :class:`~nemo_platform_plugin.cli.NemoCLI` instance. When
851
+ supplied, :meth:`~nemo_platform_plugin.cli.NemoCLI.update_function_cli` is
852
+ invoked once per function after default verb registration and
853
+ before the sub-group is mounted, giving the plugin a chance to
854
+ amend the auto-generated CLI surface.
855
+ """
856
+ for fn_cls in functions.values():
857
+ _register_function_subgroup(cli_app, fn_cls, cli=cli)
858
+
859
+
860
+ def _register_function_subgroup(
861
+ cli_app: typer.Typer,
862
+ fn_cls: type[NemoFunction],
863
+ *,
864
+ cli: NemoCLI | None = None,
865
+ ) -> None:
866
+ """Register a ``<fn-name>`` sub-group with run / submit verbs."""
867
+ fn_group = typer.Typer(
868
+ name=fn_cls.name,
869
+ help=fn_cls.description or f"Manage the {fn_cls.name} function.",
870
+ no_args_is_help=False,
871
+ )
872
+
873
+ @fn_group.callback(invoke_without_command=True)
874
+ def _root(ctx: typer.Context) -> None: # pragma: no cover - trivial delegation
875
+ """Stub callback — prints usage and exits 1 when no verb is given."""
876
+ if ctx.invoked_subcommand is None:
877
+ typer.echo(ctx.get_help())
878
+ raise typer.Exit(code=1)
879
+
880
+ _add_function_run_command(fn_group, fn_cls, cli=cli)
881
+ _add_function_submit_command(fn_group, fn_cls, cli=cli)
882
+
883
+ if cli is not None:
884
+ cli.update_function_cli(fn_cls, fn_group)
885
+
886
+ cli_app.add_typer(fn_group, name=fn_cls.name, rich_help_panel="Functions")
887
+
888
+
889
+ # ---- run --------------------------------------------------------- #
890
+
891
+
892
+ def _add_function_run_command(
893
+ group: typer.Typer,
894
+ fn_cls: type[NemoFunction],
895
+ *,
896
+ cli: NemoCLI | None = None,
897
+ ) -> None:
898
+ """Register the ``run`` verb. Generates per-field flags from ``spec_schema``.
899
+
900
+ Each scalar leaf in ``spec_schema`` becomes a Typer option named
901
+ after its dotted path, kebab-cased per segment (``--name``,
902
+ ``--target.url``). Precedence at runtime is ``--spec-file`` (base)
903
+ → ``--spec`` JSON (overlay) → per-field flags (top overlay).
904
+ Validation happens after the merge — surfaces a single
905
+ ``ValidationError`` for the merged spec rather than per-overlay.
906
+
907
+ When *cli* supplies a renderer via ``get_function_renderer(verb="run")``
908
+ (and ``--output-format json`` is not set), the renderer's lifecycle
909
+ drives the streamed output instead of the default per-frame echo.
910
+ """
911
+ leaves = walk_spec_leaves(fn_cls.spec_schema, reserved=_FN_RUN_RESERVED_FLAGS)
912
+
913
+ def _run(typer_ctx: typer.Context, **kwargs: object) -> None:
914
+ original_kwargs = dict(kwargs)
915
+ spec_str: str = cast(str, kwargs.pop("spec", "{}"))
916
+ spec_file: Path | None = cast("Path | None", kwargs.pop("spec_file", None))
917
+ workspace: str = cast(str, kwargs.pop("workspace", "default"))
918
+
919
+ base = _load_spec(spec_str, spec_file)
920
+ overlay = build_overlay(leaves, kwargs, unset_sentinel=UNSET)
921
+ merged = deep_merge(base, overlay)
922
+ try:
923
+ spec_obj = fn_cls.spec_schema.model_validate(merged, context={"is_local": True})
924
+ except ValidationError as exc:
925
+ typer.echo(f"Error: invalid spec for {fn_cls.name}: {exc}", err=True)
926
+ raise typer.Exit(code=1) from exc
927
+
928
+ sdk, async_sdk = _resolve_local_cli_sdks(typer_ctx)
929
+ ctx = FunctionContext(workspace=workspace)
930
+ renderer_cls: type[CLIRenderer] | None = None
931
+ if cli is not None and not _output_format_is_json(typer_ctx):
932
+ renderer_cls = cli.get_function_renderer(fn_cls, verb="run")
933
+ try:
934
+ outcome = asyncio.run(
935
+ _invoke_function_locally(
936
+ fn_cls,
937
+ spec_obj,
938
+ ctx,
939
+ sdk=sdk,
940
+ async_sdk=async_sdk,
941
+ renderer_cls=renderer_cls,
942
+ cli_kwargs=original_kwargs,
943
+ )
944
+ )
945
+ except LocalRunError as exc:
946
+ typer.echo(f"Error: {exc}", err=True)
947
+ raise typer.Exit(code=1) from exc
948
+ except KeyboardInterrupt as exc: # pragma: no cover - terminal-only
949
+ typer.echo("Interrupted.", err=True)
950
+ raise typer.Exit(code=130) from exc
951
+
952
+ # Fire on_complete *outside* asyncio.run so renderers using event-loop-bound
953
+ # libraries (e.g. prompt_toolkit's Application.run for an interactive
954
+ # record browser) don't collide with the loop we just tore down.
955
+ if outcome is not None:
956
+ renderer, rctx = outcome
957
+ renderer.on_complete(ctx=rctx)
958
+
959
+ help_text = f"Run {fn_cls.name} locally, in-process."
960
+ epilog = build_epilog(schema=fn_cls.spec_schema, leaves=leaves, kind="Function")
961
+ _run.__signature__ = _build_function_run_signature(leaves) # type: ignore[attr-defined]
962
+ group.command(name="run", help=help_text, epilog=epilog)(_run)
963
+
964
+
965
+ def _build_function_run_signature(leaves: list[SpecLeafField]) -> inspect.Signature:
966
+ """Compose the synthetic signature for the function ``run`` verb."""
967
+ static_params = [
968
+ # ``typer.Context`` is auto-injected by Click via ``pass_context``,
969
+ # which passes it as the first positional argument. Hand-built
970
+ # rather than via ``kw()`` because ``kw()`` only emits
971
+ # ``KEYWORD_ONLY`` params (which Click's positional injection
972
+ # would reject).
973
+ inspect.Parameter(
974
+ "typer_ctx",
975
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
976
+ annotation=typer.Context,
977
+ ),
978
+ kw(
979
+ "spec",
980
+ str,
981
+ typer.Option(
982
+ "{}",
983
+ "--spec",
984
+ help="Spec as a JSON string.",
985
+ rich_help_panel=_PANEL_SPEC_SOURCE,
986
+ ),
987
+ ),
988
+ kw(
989
+ "spec_file",
990
+ Optional[Path],
991
+ typer.Option(
992
+ None,
993
+ "--spec-file",
994
+ help="Path to a YAML or JSON spec file (used as base; per-flag values override).",
995
+ rich_help_panel=_PANEL_SPEC_SOURCE,
996
+ ),
997
+ ),
998
+ kw(
999
+ "workspace",
1000
+ str,
1001
+ typer.Option(
1002
+ "default",
1003
+ "--workspace",
1004
+ help="Workspace identity passed to the function as ctx.workspace.",
1005
+ rich_help_panel=_PANEL_SPEC_SOURCE,
1006
+ ),
1007
+ ),
1008
+ ]
1009
+ return build_callback_signature(
1010
+ static_params,
1011
+ leaves,
1012
+ rich_help_panel=_PANEL_FUNCTION_SPEC,
1013
+ )
1014
+
1015
+
1016
+ async def _invoke_function_locally(
1017
+ fn_cls: type[NemoFunction],
1018
+ spec_obj: BaseModel,
1019
+ ctx: FunctionContext,
1020
+ *,
1021
+ sdk: object | None,
1022
+ async_sdk: object | None,
1023
+ renderer_cls: type[CLIRenderer] | None = None,
1024
+ cli_kwargs: Mapping[str, Any] | None = None,
1025
+ ) -> tuple[CLIRenderer, RendererContext] | None:
1026
+ """Call ``fn_cls().run(spec, ...)`` and print result(s) to stdout.
1027
+
1028
+ Mirrors :func:`~nemo_platform_plugin.run_dependencies.resolve_run_kwargs` for the SDK
1029
+ parameters: inject when the caller supplied an SDK, leave the parameter
1030
+ unbound (Python default applies) when the function's signature has a
1031
+ default to fall back on, and raise :class:`LocalRunError` only when
1032
+ the function declared a required SDK parameter that we can't satisfy.
1033
+
1034
+ When *renderer_cls* is supplied, drive the renderer's ``on_start`` +
1035
+ ``on_frame`` around the streamed iterator and return ``(renderer, rctx)``
1036
+ so the caller can fire ``on_complete`` *after* :func:`asyncio.run`
1037
+ returns — see :func:`_drive_async_renderer`. Renderers don't apply to
1038
+ non-streaming returns — those still echo via
1039
+ :func:`_format_value_for_stdout` and this function returns ``None``.
1040
+ """
1041
+ instance = fn_cls()
1042
+ run_params = fn_cls.run_signature().parameters
1043
+ kwargs: dict[str, Any] = {}
1044
+ if "ctx" in run_params:
1045
+ kwargs["ctx"] = ctx
1046
+ if "is_local" in run_params:
1047
+ kwargs["is_local"] = True
1048
+ for param_name, value in (("sdk", sdk), ("async_sdk", async_sdk)):
1049
+ param = run_params.get(param_name)
1050
+ if param is None:
1051
+ continue
1052
+ if value is not None:
1053
+ kwargs[param_name] = value
1054
+ continue
1055
+ if param.default is inspect.Parameter.empty:
1056
+ raise LocalRunError(
1057
+ f"{fn_cls.__name__}.run requires a `{param_name}` argument; "
1058
+ f"configure your `nemo` CLI context (e.g. `nemo config use-context ...`) "
1059
+ f"or pass `{param_name}` to the local invoker."
1060
+ )
1061
+
1062
+ result = instance.run(spec_obj, **kwargs)
1063
+ if returns_async_iterator(result):
1064
+ if renderer_cls is not None:
1065
+ rctx = _make_renderer_context(
1066
+ cli_kwargs=cli_kwargs or {},
1067
+ verb="run",
1068
+ is_local=True,
1069
+ )
1070
+ renderer = await _drive_async_renderer(result, renderer_cls, rctx=rctx)
1071
+ return renderer, rctx
1072
+ async for frame in result:
1073
+ typer.echo(_format_frame_for_stdout(frame))
1074
+ return
1075
+ awaited = await result
1076
+ typer.echo(_format_value_for_stdout(awaited))
1077
+
1078
+
1079
+ def _resolve_local_cli_sdks(
1080
+ typer_ctx: typer.Context,
1081
+ ) -> tuple[object | None, object | None]:
1082
+ """Build sync + async SDKs from a CLI-like context, if present."""
1083
+ state = typer_ctx.obj
1084
+ if not state:
1085
+ return None, None
1086
+ sdk = state.get_client() if hasattr(state, "get_client") else None
1087
+ async_sdk = state.get_async_client() if hasattr(state, "get_async_client") else None
1088
+ return sdk, async_sdk
1089
+
1090
+
1091
+ # ---- submit ------------------------------------------------------ #
1092
+
1093
+
1094
+ def _add_function_submit_command(
1095
+ group: typer.Typer,
1096
+ fn_cls: type[NemoFunction],
1097
+ *,
1098
+ cli: NemoCLI | None = None,
1099
+ ) -> None:
1100
+ """Register the ``submit`` verb. Generates per-field flags + static submit flags.
1101
+
1102
+ When *cli* supplies a renderer via ``get_function_renderer(verb="submit")``
1103
+ (and ``--output-format json`` is not set), the renderer's lifecycle drives
1104
+ the streamed NDJSON response instead of the default per-line echo.
1105
+ """
1106
+ leaves = walk_spec_leaves(fn_cls.spec_schema, reserved=_FN_SUBMIT_RESERVED_FLAGS)
1107
+
1108
+ def _submit(typer_ctx: typer.Context, **kwargs: object) -> None:
1109
+ original_kwargs = dict(kwargs)
1110
+ spec_str: str = kwargs.pop("spec", "{}") # type: ignore[assignment]
1111
+ spec_file: Path | None = kwargs.pop("spec_file", None) # type: ignore[assignment]
1112
+ cluster: str | None = kwargs.pop("cluster", None) # type: ignore[assignment]
1113
+ base_url: str | None = kwargs.pop("base_url", None) # type: ignore[assignment]
1114
+ workspace: str = kwargs.pop("workspace", "default") # type: ignore[assignment]
1115
+ request_id: str | None = kwargs.pop("request_id", None) # type: ignore[assignment]
1116
+
1117
+ base = _load_spec(spec_str, spec_file)
1118
+ overlay = build_overlay(leaves, kwargs, unset_sentinel=UNSET)
1119
+ spec_data = deep_merge(base, overlay)
1120
+ try:
1121
+ fn_cls.spec_schema.model_validate(spec_data)
1122
+ except ValidationError as exc:
1123
+ typer.echo(f"Error: invalid spec for {fn_cls.name}: {exc}", err=True)
1124
+ raise typer.Exit(code=1) from exc
1125
+
1126
+ url = _build_function_submit_url(
1127
+ typer_ctx,
1128
+ fn_cls,
1129
+ base_url=base_url,
1130
+ cluster=cluster,
1131
+ workspace=workspace,
1132
+ )
1133
+ headers: dict[str, str] = {}
1134
+ if request_id is not None:
1135
+ headers["X-Request-ID"] = request_id
1136
+
1137
+ renderer_cls: type[CLIRenderer] | None = None
1138
+ if cli is not None and not _output_format_is_json(typer_ctx):
1139
+ renderer_cls = cli.get_function_renderer(fn_cls, verb="submit")
1140
+
1141
+ try:
1142
+ _post_function_submit(
1143
+ url,
1144
+ spec_data,
1145
+ headers=headers,
1146
+ renderer_cls=renderer_cls,
1147
+ cli_kwargs=original_kwargs,
1148
+ )
1149
+ except httpx.HTTPStatusError as exc:
1150
+ print_http_status_error(exc, action=f"submit {fn_cls.name}")
1151
+ raise typer.Exit(code=2) from exc
1152
+ except httpx.RequestError as exc:
1153
+ print_http_request_error(exc, action=f"submit {fn_cls.name}")
1154
+ raise typer.Exit(code=2) from exc
1155
+ except httpx.HTTPError as exc:
1156
+ typer.echo(f"Error: submit {fn_cls.name} failed: {exc}", err=True)
1157
+ raise typer.Exit(code=2) from exc
1158
+
1159
+ help_text = f"Submit {fn_cls.name} over HTTP."
1160
+ epilog = build_epilog(schema=fn_cls.spec_schema, leaves=leaves, kind="Function")
1161
+ _submit.__signature__ = _build_function_submit_signature(leaves) # type: ignore[attr-defined]
1162
+ group.command(name="submit", help=help_text, epilog=epilog)(_submit)
1163
+
1164
+
1165
+ def _build_function_submit_signature(leaves: list[SpecLeafField]) -> inspect.Signature:
1166
+ """Compose the synthetic signature for the function ``submit`` verb."""
1167
+ static_params = [
1168
+ inspect.Parameter(
1169
+ "typer_ctx",
1170
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
1171
+ annotation=typer.Context,
1172
+ ),
1173
+ kw(
1174
+ "spec",
1175
+ str,
1176
+ typer.Option(
1177
+ "{}",
1178
+ "--spec",
1179
+ help="Spec as a JSON string.",
1180
+ rich_help_panel=_PANEL_SPEC_SOURCE,
1181
+ ),
1182
+ ),
1183
+ kw(
1184
+ "spec_file",
1185
+ Optional[Path],
1186
+ typer.Option(
1187
+ None,
1188
+ "--spec-file",
1189
+ help="Path to a YAML or JSON spec file (used as base; per-flag values override).",
1190
+ rich_help_panel=_PANEL_SPEC_SOURCE,
1191
+ ),
1192
+ ),
1193
+ kw(
1194
+ "cluster",
1195
+ Optional[str],
1196
+ typer.Option(
1197
+ None,
1198
+ "--cluster",
1199
+ help="Configured cluster name to resolve via the NeMo CLI config.",
1200
+ rich_help_panel=_PANEL_SUBMISSION,
1201
+ ),
1202
+ ),
1203
+ kw(
1204
+ "base_url",
1205
+ Optional[str],
1206
+ typer.Option(
1207
+ None,
1208
+ "--base-url",
1209
+ help=("Explicit plugin-service base URL (overrides --cluster and all other submit host resolution)."),
1210
+ rich_help_panel=_PANEL_SUBMISSION,
1211
+ ),
1212
+ ),
1213
+ kw(
1214
+ "workspace",
1215
+ str,
1216
+ typer.Option(
1217
+ "default",
1218
+ "--workspace",
1219
+ help="Workspace path segment used in the submit URL.",
1220
+ rich_help_panel=_PANEL_SUBMISSION,
1221
+ ),
1222
+ ),
1223
+ kw(
1224
+ "request_id",
1225
+ Optional[str],
1226
+ typer.Option(
1227
+ None,
1228
+ "--request-id",
1229
+ help="Set the X-Request-ID header (echoed back in ctx.request_id).",
1230
+ rich_help_panel=_PANEL_SUBMISSION,
1231
+ ),
1232
+ ),
1233
+ ]
1234
+ return build_callback_signature(
1235
+ static_params,
1236
+ leaves,
1237
+ rich_help_panel=_PANEL_FUNCTION_SPEC,
1238
+ )
1239
+
1240
+
1241
+ def _post_function_submit(
1242
+ url: str,
1243
+ body: dict,
1244
+ *,
1245
+ headers: dict[str, str],
1246
+ timeout: float = 30.0,
1247
+ renderer_cls: type[CLIRenderer] | None = None,
1248
+ cli_kwargs: Mapping[str, Any] | None = None,
1249
+ ) -> None:
1250
+ """POST *body* to *url* and stream/print the response.
1251
+
1252
+ Streams NDJSON line by line when the server returns
1253
+ :data:`NDJSON_MEDIA_TYPE`; otherwise pretty-prints the JSON body.
1254
+ Surfaces 4xx / 5xx as ``httpx.HTTPStatusError`` for the caller to
1255
+ translate into a Typer exit.
1256
+
1257
+ When *renderer_cls* is supplied, the renderer drives the per-line NDJSON
1258
+ iteration through its lifecycle. Each parsed JSON line is passed to
1259
+ :meth:`CLIRenderer.on_frame`. The non-NDJSON fallback path is unchanged.
1260
+ """
1261
+ logger.debug("submit %s", url)
1262
+ with httpx.Client(timeout=timeout) as client:
1263
+ with client.stream("POST", url, json=body, headers=headers) as response:
1264
+ if response.status_code >= 400:
1265
+ # Buffer the body so the caller's error formatter
1266
+ # can read ``exc.response.text`` without raising
1267
+ # ``ResponseNotRead`` — ``client.stream`` opens the
1268
+ # response unbuffered, and the ``with`` block closes
1269
+ # the stream before the caller sees the exception.
1270
+ response.read()
1271
+ response.raise_for_status()
1272
+ content_type = response.headers.get("content-type", "")
1273
+ if NDJSON_MEDIA_TYPE in content_type:
1274
+ if renderer_cls is not None:
1275
+ rctx = _make_renderer_context(
1276
+ cli_kwargs=cli_kwargs or {},
1277
+ verb="submit",
1278
+ is_local=False,
1279
+ )
1280
+ renderer = _drive_sync_renderer(response.iter_lines(), renderer_cls, rctx=rctx)
1281
+ renderer.on_complete(ctx=rctx)
1282
+ return
1283
+ for line in response.iter_lines():
1284
+ if not line:
1285
+ continue
1286
+ typer.echo(_pretty_print_jsonl_line(line))
1287
+ return
1288
+ response.read()
1289
+ try:
1290
+ typer.echo(json.dumps(response.json(), indent=2))
1291
+ except ValueError:
1292
+ typer.echo(response.text)
1293
+
1294
+
1295
+ # ---- helpers ----------------------------------------------------- #
1296
+
1297
+
1298
+ def _resolve_cluster_name_to_base_url(cluster_name: str) -> str:
1299
+ """Resolve a configured cluster name to its base URL."""
1300
+ from nemo_platform.config.config import Config
1301
+
1302
+ config = Config.load()
1303
+ for cluster in config.get_config_file().clusters:
1304
+ if cluster.name == cluster_name:
1305
+ return str(cluster.base_url)
1306
+ raise ValueError(
1307
+ f"Unknown cluster '{cluster_name}'. Use `nemo config view --all-contexts` to inspect configured clusters or pass `--base-url`."
1308
+ )
1309
+
1310
+
1311
+ def _resolve_submit_base_url(
1312
+ typer_ctx: typer.Context,
1313
+ *,
1314
+ base_url: str | None,
1315
+ cluster: str | None,
1316
+ ) -> str:
1317
+ """Resolve submit host precedence shared by function and job submit."""
1318
+ if base_url is not None:
1319
+ return base_url
1320
+ if cluster is not None:
1321
+ return _resolve_cluster_name_to_base_url(cluster)
1322
+
1323
+ state = typer_ctx.obj
1324
+ if state is not None and hasattr(state, "get_base_url"):
1325
+ resolved = state.get_base_url(default=None)
1326
+ if resolved:
1327
+ return cast(str, resolved)
1328
+
1329
+ return os.environ.get(_DEFAULT_BASE_URL_ENV_VAR) or _DEFAULT_BASE_URL
1330
+
1331
+
1332
+ def _build_function_submit_url(
1333
+ typer_ctx: typer.Context,
1334
+ fn_cls: type[NemoFunction],
1335
+ *,
1336
+ base_url: str | None,
1337
+ cluster: str | None,
1338
+ workspace: str,
1339
+ ) -> str:
1340
+ """Resolve the full POST URL for *fn_cls*.
1341
+
1342
+ Precedence for the host: explicit ``--base-url`` > configured
1343
+ ``--cluster`` > active context base URL > ``$NMP_BASE_URL`` >
1344
+ localhost. The path is the canonical
1345
+ ``/apis/<plugin>/v2/workspaces/<ws>/<name>``, with
1346
+ :attr:`NemoFunction.endpoint` substituting the trailing segment
1347
+ when set.
1348
+ """
1349
+ host = _resolve_submit_base_url(typer_ctx, base_url=base_url, cluster=cluster)
1350
+ api_segment = _api_segment_for_function(fn_cls)
1351
+ trailing = (fn_cls.endpoint or DEFAULT_FUNCTION_PATH).replace("{name}", fn_cls.name)
1352
+ if not trailing.startswith("/"):
1353
+ trailing = "/" + trailing
1354
+ return f"{host.rstrip('/')}/apis/{api_segment}/v2/workspaces/{workspace}{trailing}"
1355
+
1356
+
1357
+ def _api_segment_for_function(fn_cls: type[NemoFunction]) -> str:
1358
+ """Plugin-name segment of the URL for *fn_cls*.
1359
+
1360
+ Functions register under the ``nemo.functions`` entry-point group
1361
+ keyed as ``<plugin>.<function>``, and the platform mounts their
1362
+ routes under that ``<plugin>`` segment. The authoritative source of
1363
+ truth is therefore the entry-point key — not the Python module
1364
+ path. We resolve it via :func:`~nemo_platform_plugin.discovery.discover_functions`
1365
+ so a plugin registered as ``my-plugin.greet`` correctly maps to
1366
+ ``/apis/my-plugin/...``, even though its package directory is
1367
+ ``nemo_my_plugin/`` (which the old module-name heuristic would
1368
+ have collapsed to ``my`` and 404'd against).
1369
+
1370
+ When the function class isn't installed as an entry point — unit
1371
+ tests with inline classes, ad-hoc invocations from a checkout —
1372
+ fall back to deriving the segment from the top-level package name
1373
+ with the ``nemo_`` prefix stripped and underscores converted to
1374
+ dashes. This mirrors :func:`nemo_platform_plugin.scheduler._api_segment_for`
1375
+ so the two CLIs stay consistent. Crucially, the fallback no longer
1376
+ strips a trailing ``_plugin`` from the module name: a plugin whose
1377
+ actual key happens to be ``my-plugin`` would be silently rewritten
1378
+ to ``my``.
1379
+ """
1380
+ from nemo_platform_plugin.discovery import discover_functions
1381
+
1382
+ try:
1383
+ registered = discover_functions()
1384
+ except Exception:
1385
+ registered = {}
1386
+ for key, registered_cls in registered.items():
1387
+ if registered_cls is fn_cls and "." in key:
1388
+ return key.split(".", 1)[0]
1389
+
1390
+ module = fn_cls.__module__.split(".")[0]
1391
+ if module.startswith("nemo_"):
1392
+ module = module[len("nemo_") :]
1393
+ return module.replace("_", "-")
1394
+
1395
+
1396
+ def _format_frame_for_stdout(frame: Any) -> str:
1397
+ """Render a streaming frame as a single line of pretty JSON.
1398
+
1399
+ Pydantic models go through ``model_dump_json``; dicts and lists
1400
+ through ``json.dumps``; anything else through ``str()``. The
1401
+ output is one line per frame so consumers can pipe to ``jq -c``
1402
+ or grep for ``kind`` discriminators without a parser.
1403
+ """
1404
+ if isinstance(frame, BaseModel):
1405
+ return frame.model_dump_json()
1406
+ if isinstance(frame, (dict, list)):
1407
+ return json.dumps(frame, default=str)
1408
+ return str(frame)
1409
+
1410
+
1411
+ def _format_value_for_stdout(value: Any) -> str:
1412
+ """Render a non-streaming return value as multi-line pretty JSON."""
1413
+ if isinstance(value, BaseModel):
1414
+ return value.model_dump_json(indent=2)
1415
+ if isinstance(value, (dict, list)):
1416
+ return json.dumps(value, indent=2, default=str)
1417
+ return str(value)
1418
+
1419
+
1420
+ def _pretty_print_jsonl_line(line: str) -> str:
1421
+ """Best-effort pretty-print for an NDJSON line.
1422
+
1423
+ Falls back to the raw line when the line isn't valid JSON so
1424
+ operators see exactly what the server emitted (useful for
1425
+ debugging non-conforming streams). Streams are kept one frame per
1426
+ line — pretty-printing within a frame would defeat the JSONL
1427
+ contract for downstream piping.
1428
+ """
1429
+ try:
1430
+ parsed = json.loads(line)
1431
+ except json.JSONDecodeError:
1432
+ return line
1433
+ return json.dumps(parsed)