cu-cli 0.1.0b1__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 (56) hide show
  1. cu_cli/__init__.py +17 -0
  2. cu_cli/__main__.py +11 -0
  3. cu_cli/apiversion.py +124 -0
  4. cu_cli/cli.py +138 -0
  5. cu_cli/client.py +138 -0
  6. cu_cli/commands/__init__.py +4 -0
  7. cu_cli/commands/_command_spec.py +94 -0
  8. cu_cli/commands/_help.py +33 -0
  9. cu_cli/commands/_infra_models.py +184 -0
  10. cu_cli/commands/_infra_wizard.py +630 -0
  11. cu_cli/commands/_model_setup.py +46 -0
  12. cu_cli/commands/_options.py +112 -0
  13. cu_cli/commands/analyze.py +631 -0
  14. cu_cli/commands/analyzer.py +1462 -0
  15. cu_cli/commands/defaults.py +172 -0
  16. cu_cli/commands/doctor.py +166 -0
  17. cu_cli/commands/env_var.py +67 -0
  18. cu_cli/commands/infra.py +302 -0
  19. cu_cli/commands/profile_cmd.py +525 -0
  20. cu_cli/commands/upgrade.py +120 -0
  21. cu_cli/core/__init__.py +17 -0
  22. cu_cli/core/analyze.py +44 -0
  23. cu_cli/core/analyzers.py +30 -0
  24. cu_cli/core/azure_resources.py +486 -0
  25. cu_cli/core/defaults.py +18 -0
  26. cu_cli/core/doctor.py +42 -0
  27. cu_cli/core/foundry.py +68 -0
  28. cu_cli/core/infra_models.py +367 -0
  29. cu_cli/core/inputs.py +209 -0
  30. cu_cli/core/schema.py +24 -0
  31. cu_cli/errors.py +174 -0
  32. cu_cli/exit_codes.py +20 -0
  33. cu_cli/modality.py +24 -0
  34. cu_cli/output.py +179 -0
  35. cu_cli/profile.py +30 -0
  36. cu_cli/py.typed +0 -0
  37. cu_cli/resources/__init__.py +4 -0
  38. cu_cli/resources/azd_template/README.md +187 -0
  39. cu_cli/resources/azd_template/azure.yaml +27 -0
  40. cu_cli/resources/azd_template/hooks/postprovision.ps1 +320 -0
  41. cu_cli/resources/azd_template/hooks/postprovision.sh +299 -0
  42. cu_cli/resources/azd_template/infra/main.bicep +115 -0
  43. cu_cli/resources/azd_template/infra/main.parameters.json +30 -0
  44. cu_cli/resources/azd_template/infra/models.json +1 -0
  45. cu_cli/resources/azd_template/infra/modules/foundry.bicep +122 -0
  46. cu_cli/schema_validate.py +28 -0
  47. cu_cli/spec_validate.py +18 -0
  48. cu_cli/telemetry.py +42 -0
  49. cu_cli/update_check.py +154 -0
  50. cu_cli/update_provider.py +92 -0
  51. cu_cli/windows_self_upgrade.py +245 -0
  52. cu_cli-0.1.0b1.dist-info/METADATA +345 -0
  53. cu_cli-0.1.0b1.dist-info/RECORD +56 -0
  54. cu_cli-0.1.0b1.dist-info/WHEEL +5 -0
  55. cu_cli-0.1.0b1.dist-info/entry_points.txt +3 -0
  56. cu_cli-0.1.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,172 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT license.
3
+
4
+ """``cu defaults`` — read and update Content Understanding defaults.
5
+
6
+ Wraps the CU SDK's ``get_defaults`` and ``update_defaults`` operations so users
7
+ can manage resource-level model deployment mappings from the CLI.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import rich_click as click
13
+
14
+ from cu_cli_core.command_spec import (
15
+ DEFAULTS_SET,
16
+ DEFAULTS_SHOW,
17
+ CommandBindingError,
18
+ build_request,
19
+ resolve_identifier,
20
+ )
21
+ from ..client import build_client, resolve
22
+ from ..profile import Profile
23
+ from cu_cli_core.defaults import (
24
+ extract_model_deployments as _extract_model_deployments,
25
+ parse_model_kv as _parse_model_kv,
26
+ )
27
+ from ..errors import CuCliError, friendly_errors
28
+ from ..output import console, dump_json, dump_markdown_kv
29
+ from ._help import common_commands
30
+ from ._command_spec import with_command_arguments
31
+ from ._options import calling_time, print_runtime_context, with_auth_options
32
+
33
+
34
+ def _client(profile: Profile, endpoint, api_key, api_version, entra, show_runtime_context):
35
+ auth = resolve(
36
+ profile,
37
+ endpoint_override=endpoint,
38
+ api_key_override=api_key,
39
+ api_version_override=api_version,
40
+ force_entra=entra,
41
+ )
42
+ if show_runtime_context:
43
+ print_runtime_context(auth, profile)
44
+ return profile, build_client(
45
+ profile,
46
+ endpoint_override=endpoint,
47
+ api_key_override=api_key,
48
+ api_version_override=api_version,
49
+ force_entra=entra,
50
+ )
51
+
52
+
53
+
54
+
55
+ @click.group(
56
+ "defaults",
57
+ help="Show or configure Content Understanding defaults (model-to-deployment mappings).",
58
+ epilog="[bold cyan]Common commands:[/bold cyan]\n\n"
59
+ "[bold green]cu defaults show[/bold green]\n\n"
60
+ "[white]\u00a0\u00a0Show Content Understanding model-to-deployment mappings.[/white]\n\n"
61
+ "[bold green]cu defaults set[/bold green] "
62
+ "[bold cyan]--from-profile[/bold cyan]\n\n"
63
+ "[white]\u00a0\u00a0Apply model mappings from the current profile as defaults.[/white]",
64
+ )
65
+ def defaults_group() -> None:
66
+ pass
67
+
68
+
69
+ @defaults_group.command(
70
+ "show",
71
+ help=DEFAULTS_SHOW.help,
72
+ epilog=common_commands(
73
+ ("cu defaults show", "Print model deployment mappings as JSON."),
74
+ ("cu defaults show --table", "Print model mappings as a readable table."),
75
+ ),
76
+ )
77
+ @with_command_arguments(DEFAULTS_SHOW)
78
+ @with_auth_options
79
+ @friendly_errors
80
+ def cmd_show(
81
+ table_output, endpoint, api_key, api_version, entra, profile_name, show_runtime_context,
82
+ show_calling_time
83
+ ) -> None:
84
+ try:
85
+ build_request(DEFAULTS_SHOW, {"table_output": table_output})
86
+ except CommandBindingError as exc:
87
+ raise CuCliError(str(exc)) from exc
88
+ profile = Profile.load(profile_name=profile_name)
89
+ _, client = _client(profile, endpoint, api_key, api_version, entra, show_runtime_context)
90
+ with calling_time(show_calling_time) as calling_timer:
91
+ defaults = resolve_identifier(DEFAULTS_SHOW.operation)(client)
92
+
93
+ if not table_output:
94
+ dump_json(defaults)
95
+ calling_timer.print()
96
+ return
97
+
98
+ mappings = _extract_model_deployments(defaults)
99
+ if mappings:
100
+ dump_markdown_kv(mappings, headers=("Model", "Deployment"))
101
+ calling_timer.print()
102
+ return
103
+ console.print("[yellow]Content Understanding defaults are not configured.[/yellow]")
104
+ calling_timer.print()
105
+
106
+
107
+ @defaults_group.command(
108
+ "set",
109
+ help=DEFAULTS_SET.help,
110
+ epilog=common_commands(
111
+ ("cu defaults set --from-profile", "Push mappings from the effective profile."),
112
+ (
113
+ "cu defaults set --model MODEL=DEPLOYMENT",
114
+ "Add or update one model-to-deployment mapping.",
115
+ ),
116
+ ),
117
+ )
118
+ @with_command_arguments(DEFAULTS_SET)
119
+ @with_auth_options
120
+ @friendly_errors
121
+ def cmd_set(
122
+ model_kv, from_profile, replace, json_output,
123
+ endpoint, api_key, api_version, entra, profile_name,
124
+ show_runtime_context, show_calling_time
125
+ ) -> None:
126
+ try:
127
+ request = build_request(
128
+ DEFAULTS_SET,
129
+ {
130
+ "model_kv": model_kv,
131
+ "from_profile": from_profile,
132
+ "replace": replace,
133
+ "json_output": json_output,
134
+ },
135
+ )
136
+ except CommandBindingError as exc:
137
+ raise CuCliError(str(exc)) from exc
138
+ profile = Profile.load(profile_name=profile_name)
139
+ desired: dict[str, str] = {}
140
+ if request.from_profile:
141
+ desired.update({str(k): str(v) for k, v in profile.model_deployments.items()})
142
+ desired.update(_parse_model_kv(request.models))
143
+
144
+ if not desired:
145
+ raise CuCliError(
146
+ "no model deployment mappings provided.",
147
+ hint="pass `--from-profile` to use the effective profile mappings "
148
+ "or pass `--model MODEL=DEPLOYMENT`.",
149
+ )
150
+
151
+ _, client = _client(
152
+ profile, endpoint, api_key, api_version, entra, show_runtime_context
153
+ )
154
+
155
+ with calling_time(show_calling_time) as calling_timer:
156
+ updated, merged = resolve_identifier(DEFAULTS_SET.operation)(
157
+ client,
158
+ desired,
159
+ replace=request.replace,
160
+ )
161
+
162
+ if json_output:
163
+ dump_json(updated)
164
+ calling_timer.print()
165
+ return
166
+
167
+ console.print(
168
+ f"[green]ok[/green] updated Content Understanding defaults "
169
+ f"with {len(merged)} mapping(s)."
170
+ )
171
+ dump_markdown_kv(merged, headers=("Model", "Deployment"))
172
+ calling_timer.print()
@@ -0,0 +1,166 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT license.
3
+
4
+ """``cu doctor`` — verify endpoint, auth, api-version, and model deployments.
5
+
6
+ Exits non-zero when a required check fails so scripts and coding agents can gate
7
+ on setup readiness.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import rich_click as click
13
+
14
+ from ..apiversion import API_VERSION_HELP, SUPPORTED_API_VERSIONS, is_supported
15
+ from ..client import build_client, resolve
16
+ from cu_cli_core.defaults import with_prebuilt_default_mappings
17
+ from ..profile import Profile
18
+ from ..core.defaults import is_defaults_not_set as _is_defaults_not_set
19
+ from ..core.doctor import missing_requirements as _missing_requirements
20
+ from ..errors import CuCliError, friendly_errors
21
+ from ..exit_codes import GENERIC_ERROR
22
+ from ..output import console
23
+ from ._options import CALLING_TIME_OPTION, calling_time
24
+ from ._help import common_commands
25
+ from ._model_setup import print_model_free_analyzers, print_model_setup_steps
26
+
27
+
28
+ @click.command(
29
+ "doctor",
30
+ help="Verify a Microsoft Foundry resource connection and Content Understanding defaults.",
31
+ epilog=common_commands(
32
+ ("cu doctor", "Check the active CU CLI profile and resource readiness."),
33
+ ("cu doctor --profile NAME", "Check one profile without activating it."),
34
+ ("cu doctor --fix-defaults", "Check readiness and apply profile mappings as defaults."),
35
+ ),
36
+ )
37
+ @click.option("-p", "--profile", "profile_name", default=None,
38
+ help="Named CU CLI profile to use (from cu profile).")
39
+ @click.option("--fix-defaults", is_flag=True,
40
+ help="Configure Content Understanding defaults from profile model mappings.")
41
+ @click.option("--endpoint", default=None, help="Override configured endpoint.")
42
+ @click.option("--auth-mode", type=click.Choice(["login", "key"]), default=None,
43
+ help="Authentication mode; defaults to the selected CU CLI profile.")
44
+ @click.option("--api-key", default=None, help="Override configured API key.")
45
+ @click.option("--api-version", "api_version", default=None,
46
+ help=API_VERSION_HELP)
47
+ @CALLING_TIME_OPTION
48
+ @friendly_errors
49
+ def cmd_doctor(endpoint: str | None, api_key: str | None, api_version: str | None,
50
+ auth_mode: str | None, profile_name: str | None, fix_defaults: bool,
51
+ show_calling_time: bool) -> None:
52
+ profile = Profile.load(profile_name=profile_name)
53
+ failures: list[str] = []
54
+
55
+ console.print("[bold]CU CLI configuration[/bold]\n")
56
+
57
+ effective_version = api_version or profile.api_version
58
+ if is_supported(effective_version):
59
+ console.print(
60
+ f"[bold]API version:[/bold] {effective_version} [green](supported)[/green]"
61
+ )
62
+ else:
63
+ failures.append(
64
+ f"api-version {effective_version} is not supported by this build "
65
+ f"(supported: {', '.join(SUPPORTED_API_VERSIONS)})."
66
+ )
67
+ console.print(
68
+ f"[bold]API version:[/bold] {effective_version} [red](unsupported)[/red]"
69
+ )
70
+
71
+ auth = resolve(profile, endpoint_override=endpoint, api_key_override=api_key,
72
+ api_version_override=api_version, auth_mode_override=auth_mode)
73
+ authentication = (
74
+ "Microsoft Entra ID" if auth.auth_mode == "entra" else "resource key"
75
+ )
76
+ console.print(f"[bold]Microsoft Foundry resource:[/bold] {auth.endpoint}")
77
+ console.print(f"[bold]Authentication:[/bold] {authentication}")
78
+ if profile.default_analyzer:
79
+ console.print(f"[bold]Default analyzer:[/bold] {profile.default_analyzer}")
80
+ else:
81
+ console.print("[bold]Default analyzer:[/bold] not configured")
82
+ console.print(
83
+ " [dim]`cu analyze` requires --analyzer until you configure one:\n"
84
+ " cu profile set default_analyzer <analyzer-id>[/dim]"
85
+ )
86
+
87
+ client = build_client(profile, endpoint_override=endpoint, api_key_override=api_key,
88
+ api_version_override=api_version, auth_mode_override=auth_mode)
89
+
90
+ current: dict[str, str] = {}
91
+ service_reachable = False
92
+ with calling_time(show_calling_time) as calling_timer:
93
+ console.print("\n[bold]Checking Content Understanding defaults...[/bold]\n")
94
+ try:
95
+ defaults = client.get_defaults()
96
+ service_reachable = True
97
+ current = getattr(defaults, "model_deployments", None) or {}
98
+ console.print("Connected to the Microsoft Foundry resource.")
99
+ if current:
100
+ console.print("[bold]Content Understanding defaults:[/bold]")
101
+ for model, deployment in current.items():
102
+ console.print(f" - {model} -> {deployment}")
103
+ else:
104
+ console.print(
105
+ "[yellow]Content Understanding defaults have no model "
106
+ "deployment mappings.[/yellow]"
107
+ )
108
+ except Exception as exc:
109
+ if _is_defaults_not_set(exc):
110
+ service_reachable = True
111
+ console.print("Connected to the Microsoft Foundry resource.")
112
+ console.print(
113
+ "[yellow]Content Understanding defaults are not configured.[/yellow]"
114
+ )
115
+ else:
116
+ failures.append(f"could not reach the service: {exc}")
117
+ console.print("[red]Could not connect to the service (details below).[/red]")
118
+
119
+ missing = _missing_requirements(current) if service_reachable else []
120
+ if fix_defaults and service_reachable:
121
+ merged = dict(current)
122
+ merged.update(profile.model_deployments)
123
+ merged = with_prebuilt_default_mappings(merged)
124
+ if not merged:
125
+ raise CuCliError(
126
+ "cannot set defaults: no model deployment mapping is configured",
127
+ hint="set model mappings first, e.g. `cu profile set "
128
+ "model_deployments.gpt-5.2 <deployment-name>` then rerun "
129
+ "`cu doctor --fix-defaults`.",
130
+ )
131
+ console.print("\n[bold]Applying Content Understanding defaults...[/bold]")
132
+ client.update_defaults(model_deployments=merged)
133
+ console.print("[green]Content Understanding defaults updated.[/green]")
134
+ missing = _missing_requirements(merged)
135
+
136
+ if missing:
137
+ console.print(
138
+ "\n[bold yellow]Setup needed for analyzers that use generative AI:"
139
+ "[/bold yellow]"
140
+ )
141
+ for requirement in missing:
142
+ console.print(f" - {requirement}")
143
+ print_model_setup_steps(
144
+ auth.endpoint,
145
+ profile_name=profile_name,
146
+ )
147
+ print_model_free_analyzers()
148
+
149
+ if failures:
150
+ console.print()
151
+ for f in failures:
152
+ console.print(f"[bold red]x[/bold red] {f}")
153
+ calling_timer.print()
154
+ raise CuCliError("doctor found problems; see above.", exit_code=GENERIC_ERROR)
155
+
156
+ if missing:
157
+ console.print(
158
+ "\n[bold]Configuration check complete.[/bold]\n"
159
+ "Content extraction analyzers are ready. Analyzers that use "
160
+ "generative AI require the setup above."
161
+ )
162
+ else:
163
+ console.print(
164
+ "\n[bold green]Configuration check complete. CU CLI is ready.[/bold green]"
165
+ )
166
+ calling_timer.print()
@@ -0,0 +1,67 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT license.
3
+
4
+ """Discover and inspect supported CU CLI environment variables."""
5
+
6
+ from __future__ import annotations
7
+
8
+ import rich_click as click
9
+ from rich.table import Table
10
+
11
+ from cu_cli_core.command_spec import ENV_VAR_LIST, build_request, resolve_identifier
12
+ from cu_cli_core.environment import ENVIRONMENT_VARIABLES
13
+
14
+ from ..output import dump_json, result_console
15
+ from ._command_spec import with_command_arguments
16
+ from ._help import common_commands
17
+
18
+
19
+ def _environment_help() -> str:
20
+ blocks = ["[bold cyan]Supported environment variables:[/bold cyan]"]
21
+ for spec in ENVIRONMENT_VARIABLES:
22
+ sensitivity = " (sensitive; always redacted)" if spec.sensitive else ""
23
+ blocks.append(
24
+ f"[bold green]{spec.name}[/bold green]{sensitivity}\n"
25
+ f" {spec.description}\n"
26
+ f" Values: {spec.accepted_values}. Default: {spec.default}.\n"
27
+ f" Scope: {spec.scope}. {spec.precedence}"
28
+ )
29
+ return "\n\n[white] [/white]\n\n".join(blocks)
30
+
31
+
32
+ @click.group(
33
+ "env-var",
34
+ help="Show help for supported environment variables and inspect values that are set.",
35
+ epilog=_environment_help()
36
+ + "\n\n"
37
+ + common_commands(
38
+ ("cu env-var list --json", "Print the set variables as redacted JSON."),
39
+ ),
40
+ )
41
+ def env_var_group() -> None:
42
+ pass
43
+
44
+
45
+ @env_var_group.command(
46
+ "list",
47
+ help=ENV_VAR_LIST.help,
48
+ epilog=common_commands(
49
+ ("cu env-var list", "List set variables as a table."),
50
+ ("cu env-var list --json", "Print set variables as redacted JSON."),
51
+ ),
52
+ )
53
+ @with_command_arguments(ENV_VAR_LIST)
54
+ def cmd_list(json_output: bool) -> None:
55
+ build_request(ENV_VAR_LIST, {"json_output": json_output})
56
+ rows = resolve_identifier(ENV_VAR_LIST.operation)()
57
+ if json_output:
58
+ dump_json(rows)
59
+ return
60
+
61
+ table = Table(title="Set CU environment variables", show_lines=False)
62
+ table.add_column("Name", style="bold")
63
+ table.add_column("Value")
64
+ table.add_column("Scope")
65
+ for row in rows:
66
+ table.add_row(str(row["name"]), str(row["value"]), str(row["scope"]))
67
+ result_console.print(table)