maxc-cli 0.1.6__tar.gz → 0.1.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/PKG-INFO +1 -1
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/setup.py +1 -1
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/__init__.py +1 -1
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/query.py +13 -6
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/cli.py +5 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/exceptions.py +12 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli.egg-info/PKG-INFO +1 -1
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/MANIFEST.in +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/README.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/pyproject.toml +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/scripts/regression_test.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/setup.cfg +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/__main__.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/app.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/audit.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/auth_providers.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/__init__.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/auth.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/catalog.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/data.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/job.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/meta.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/backend/odps.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/cache.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/config.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/helpers.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/masking.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/models.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/output.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/setting_parser.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/SKILL.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/agents/openai.yaml +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/nohup.out +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/references/bootstrap-auth.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/references/command-patterns.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/references/maxcompute-sql-notes.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/references/migrate-from-odpscmd.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/references/partition-guide.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/skills/references/setup-install.md +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/store.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli/utils.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli.egg-info/SOURCES.txt +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli.egg-info/dependency_links.txt +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli.egg-info/entry_points.txt +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli.egg-info/requires.txt +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/src/maxc_cli.egg-info/top_level.txt +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_agent_hints_and_cli.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_agent_skill_commands_context.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_cache.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_catalog.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_cli_mock.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_compat.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_e2e_smoke.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_error_self_correction.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_external_auth.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_integration.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_integration_real.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_job_improvements.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_masking.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_phase1_improvements.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_query_auto_promote.py +0 -0
- {maxc_cli-0.1.6 → maxc_cli-0.1.8}/tests/test_setting_parser.py +0 -0
|
@@ -9,7 +9,7 @@ README = ROOT / "README.md"
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="maxc-cli",
|
|
12
|
-
version="0.1.
|
|
12
|
+
version="0.1.8",
|
|
13
13
|
description="Agent-native MaxCompute CLI for external coding agents",
|
|
14
14
|
long_description=README.read_text(encoding="utf-8"),
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
@@ -112,13 +112,20 @@ class QueryMixin:
|
|
|
112
112
|
)
|
|
113
113
|
|
|
114
114
|
try:
|
|
115
|
-
instance = self.client.
|
|
115
|
+
instance = self.client.run_sql(
|
|
116
116
|
actual_sql, project=project, hints=hints,
|
|
117
117
|
)
|
|
118
|
+
except Exception as exc:
|
|
119
|
+
raise translate_odps_error(exc) from exc
|
|
120
|
+
|
|
121
|
+
try:
|
|
118
122
|
# Default timeout: 300 seconds (5 minutes) to prevent indefinite blocking
|
|
119
123
|
instance.wait_for_success(timeout=timeout or 300)
|
|
120
124
|
except Exception as exc:
|
|
121
|
-
|
|
125
|
+
err = translate_odps_error(exc)
|
|
126
|
+
err.instance_id = instance.id
|
|
127
|
+
err.logview = self._safe_logview(instance)
|
|
128
|
+
raise err from exc
|
|
122
129
|
|
|
123
130
|
elapsed_ms = int((monotonic() - started_monotonic) * 1000)
|
|
124
131
|
result = self._instance_to_query_result(
|
|
@@ -200,9 +207,9 @@ class QueryMixin:
|
|
|
200
207
|
):
|
|
201
208
|
"""Submit a query for async execution without waiting.
|
|
202
209
|
|
|
203
|
-
Calls ``client.
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
Calls ``client.run_sql()`` to create the instance without waiting
|
|
211
|
+
for completion. Returns immediately with a job ID that can be
|
|
212
|
+
polled via ``wait_job`` / ``get_job``.
|
|
206
213
|
|
|
207
214
|
Args:
|
|
208
215
|
sql: SQL query, optionally prefixed with SET statements.
|
|
@@ -218,7 +225,7 @@ class QueryMixin:
|
|
|
218
225
|
actual_sql, hints = _parse_sql_with_hints(sql, force=force)
|
|
219
226
|
|
|
220
227
|
try:
|
|
221
|
-
instance = self.client.
|
|
228
|
+
instance = self.client.run_sql(
|
|
222
229
|
actual_sql,
|
|
223
230
|
project=project,
|
|
224
231
|
hints=hints,
|
|
@@ -512,6 +512,7 @@ def run(
|
|
|
512
512
|
"BACKEND_CONNECTION_ERROR": _AUTH_HINTS,
|
|
513
513
|
"PERMISSION_DENIED": AgentHints(
|
|
514
514
|
actions=[action("auth.can-i"), action("auth.whoami")],
|
|
515
|
+
insights=[f"Current project: {app.config.default_project}"] if app else [],
|
|
515
516
|
),
|
|
516
517
|
"NOT_FOUND": AgentHints(
|
|
517
518
|
actions=[action("meta.search"), action("meta.list-tables")],
|
|
@@ -572,6 +573,10 @@ def run(
|
|
|
572
573
|
emit_json(payload.to_dict(), stdout)
|
|
573
574
|
else:
|
|
574
575
|
stderr.write(render_error(exc.error_code, exc.message, exc.suggestion) + "\n")
|
|
576
|
+
if getattr(exc, "instance_id", None):
|
|
577
|
+
stderr.write(f" Instance ID: {exc.instance_id}\n")
|
|
578
|
+
if getattr(exc, "logview", None):
|
|
579
|
+
stderr.write(f" LogView: {exc.logview}\n")
|
|
575
580
|
return exc.exit_code
|
|
576
581
|
except Exception as exc:
|
|
577
582
|
error_payload = ErrorPayload(
|
|
@@ -10,6 +10,8 @@ class ErrorPayload:
|
|
|
10
10
|
suggestion: 'str | None'
|
|
11
11
|
recoverable: 'bool'
|
|
12
12
|
recovery_steps: 'list[str]' = field(default_factory=list)
|
|
13
|
+
instance_id: 'str | None' = None
|
|
14
|
+
logview: 'str | None' = None
|
|
13
15
|
|
|
14
16
|
def to_dict(self) -> 'dict[str, Any]':
|
|
15
17
|
payload: 'dict[str, Any]' = {
|
|
@@ -21,6 +23,10 @@ class ErrorPayload:
|
|
|
21
23
|
payload["suggestion"] = self.suggestion
|
|
22
24
|
if self.recovery_steps:
|
|
23
25
|
payload["recovery_steps"] = self.recovery_steps
|
|
26
|
+
if self.instance_id:
|
|
27
|
+
payload["instance_id"] = self.instance_id
|
|
28
|
+
if self.logview:
|
|
29
|
+
payload["logview"] = self.logview
|
|
24
30
|
return payload
|
|
25
31
|
|
|
26
32
|
|
|
@@ -35,10 +41,14 @@ class MaxCError(Exception):
|
|
|
35
41
|
*,
|
|
36
42
|
suggestion: 'str | None' = None,
|
|
37
43
|
recoverable: 'bool | None' = None,
|
|
44
|
+
instance_id: 'str | None' = None,
|
|
45
|
+
logview: 'str | None' = None,
|
|
38
46
|
) -> 'None':
|
|
39
47
|
super().__init__(message)
|
|
40
48
|
self.message = message
|
|
41
49
|
self.suggestion = suggestion
|
|
50
|
+
self.instance_id = instance_id
|
|
51
|
+
self.logview = logview
|
|
42
52
|
if recoverable is None:
|
|
43
53
|
self.recoverable = self.__class__.recoverable
|
|
44
54
|
else:
|
|
@@ -52,6 +62,8 @@ class MaxCError(Exception):
|
|
|
52
62
|
suggestion=self.suggestion,
|
|
53
63
|
recoverable=self.recoverable,
|
|
54
64
|
recovery_steps=steps,
|
|
65
|
+
instance_id=self.instance_id,
|
|
66
|
+
logview=self.logview,
|
|
55
67
|
)
|
|
56
68
|
|
|
57
69
|
def _default_recovery_steps(self) -> 'list[str]':
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|