astrodynamics-mcp 0.1.0__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.
- astrodynamics_mcp-0.1.0/.github/CODEOWNERS +2 -0
- astrodynamics_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug.yml +75 -0
- astrodynamics_mcp-0.1.0/.github/ISSUE_TEMPLATE/client-compatibility.yml +81 -0
- astrodynamics_mcp-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- astrodynamics_mcp-0.1.0/.github/ISSUE_TEMPLATE/tool-request.yml +54 -0
- astrodynamics_mcp-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +35 -0
- astrodynamics_mcp-0.1.0/.github/workflows/ci.yml +107 -0
- astrodynamics_mcp-0.1.0/.github/workflows/docs.yml +57 -0
- astrodynamics_mcp-0.1.0/.github/workflows/eval.yml +159 -0
- astrodynamics_mcp-0.1.0/.github/workflows/release.yml +74 -0
- astrodynamics_mcp-0.1.0/.gitignore +43 -0
- astrodynamics_mcp-0.1.0/.python-version +1 -0
- astrodynamics_mcp-0.1.0/CHANGELOG.md +99 -0
- astrodynamics_mcp-0.1.0/CONTRIBUTING.md +93 -0
- astrodynamics_mcp-0.1.0/LICENSE +21 -0
- astrodynamics_mcp-0.1.0/PKG-INFO +187 -0
- astrodynamics_mcp-0.1.0/README.md +146 -0
- astrodynamics_mcp-0.1.0/docs/_hooks.py +70 -0
- astrodynamics_mcp-0.1.0/docs/api.md +60 -0
- astrodynamics_mcp-0.1.0/docs/data-sources.md +125 -0
- astrodynamics_mcp-0.1.0/docs/eval-suite.md +97 -0
- astrodynamics_mcp-0.1.0/docs/faq.md +124 -0
- astrodynamics_mcp-0.1.0/docs/getting-started.md +115 -0
- astrodynamics_mcp-0.1.0/docs/index.md +76 -0
- astrodynamics_mcp-0.1.0/docs/output-shaping.md +76 -0
- astrodynamics_mcp-0.1.0/docs/pick-a-client.md +128 -0
- astrodynamics_mcp-0.1.0/docs/recipes.md +143 -0
- astrodynamics_mcp-0.1.0/docs/supported-clients.md +50 -0
- astrodynamics_mcp-0.1.0/docs/tool-reference.md +29 -0
- astrodynamics_mcp-0.1.0/eval/README.md +390 -0
- astrodynamics_mcp-0.1.0/eval/__init__.py +5 -0
- astrodynamics_mcp-0.1.0/eval/_ci_report.py +240 -0
- astrodynamics_mcp-0.1.0/eval/_constraints.py +306 -0
- astrodynamics_mcp-0.1.0/eval/_functional.py +410 -0
- astrodynamics_mcp-0.1.0/eval/_prompts.py +160 -0
- astrodynamics_mcp-0.1.0/eval/prompts/access_windows_iss_explicit_coords_range_filter.yaml +23 -0
- astrodynamics_mcp-0.1.0/eval/prompts/access_windows_iss_madrid.yaml +31 -0
- astrodynamics_mcp-0.1.0/eval/prompts/bplane_target_mars_approach_readonly.yaml +28 -0
- astrodynamics_mcp-0.1.0/eval/prompts/bplane_target_mars_btr_with_dv.yaml +22 -0
- astrodynamics_mcp-0.1.0/eval/prompts/frame_transform_icrf_to_itrs_with_iers.yaml +18 -0
- astrodynamics_mcp-0.1.0/eval/prompts/frame_transform_teme_to_icrf.yaml +24 -0
- astrodynamics_mcp-0.1.0/eval/prompts/lambert_earth_orbit_curtis_5_2.yaml +31 -0
- astrodynamics_mcp-0.1.0/eval/prompts/lambert_gooding_algorithm.yaml +23 -0
- astrodynamics_mcp-0.1.0/eval/prompts/lambert_multi_revolution.yaml +20 -0
- astrodynamics_mcp-0.1.0/eval/prompts/planning_hubble_madrid_passes.yaml +32 -0
- astrodynamics_mcp-0.1.0/eval/prompts/planning_mars_2028_transfer.yaml +28 -0
- astrodynamics_mcp-0.1.0/eval/prompts/porkchop_earth_mars_2026.yaml +27 -0
- astrodynamics_mcp-0.1.0/eval/prompts/porkchop_earth_venus_2027.yaml +22 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_hubble_lookup_then_goldstone_access.yaml +30 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_lambert_then_bplane_jupiter.yaml +26 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_lambert_then_frame_transform_itrs.yaml +24 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_porkchop_then_lambert.yaml +27 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_sgp4_then_frame_to_itrs.yaml +25 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_time_convert_utc_tai_roundtrip.yaml +22 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_tle_lookup_sgp4_frame_three_step.yaml +27 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sequential_tle_lookup_then_sgp4_24h.yaml +27 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sgp4_propagate_iss_default_teme.yaml +26 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sgp4_propagate_iss_gcrs_explicit_frame.yaml +22 -0
- astrodynamics_mcp-0.1.0/eval/prompts/sgp4_propagate_iss_multiple_epochs.yaml +28 -0
- astrodynamics_mcp-0.1.0/eval/prompts/time_convert_utc_to_jd_format.yaml +19 -0
- astrodynamics_mcp-0.1.0/eval/prompts/time_convert_utc_to_tai.yaml +18 -0
- astrodynamics_mcp-0.1.0/eval/prompts/time_convert_utc_to_ut1_with_iers.yaml +23 -0
- astrodynamics_mcp-0.1.0/eval/prompts/tle_lookup_hubble_by_name.yaml +20 -0
- astrodynamics_mcp-0.1.0/eval/prompts/tle_lookup_iss_by_norad_id.yaml +18 -0
- astrodynamics_mcp-0.1.0/eval/prompts/tle_lookup_weather_group.yaml +18 -0
- astrodynamics_mcp-0.1.0/eval/scoring.py +171 -0
- astrodynamics_mcp-0.1.0/eval/tasks.py +145 -0
- astrodynamics_mcp-0.1.0/examples/01_hohmann_dv.md +106 -0
- astrodynamics_mcp-0.1.0/examples/02_hubble_passes_madrid.md +160 -0
- astrodynamics_mcp-0.1.0/examples/03_mars_launch_window_2028.md +130 -0
- astrodynamics_mcp-0.1.0/examples/README.md +60 -0
- astrodynamics_mcp-0.1.0/examples/__init__.py +1 -0
- astrodynamics_mcp-0.1.0/examples/_fixtures.py +272 -0
- astrodynamics_mcp-0.1.0/examples/run_example_01_hohmann.py +117 -0
- astrodynamics_mcp-0.1.0/examples/run_example_02_hubble_passes.py +109 -0
- astrodynamics_mcp-0.1.0/examples/run_example_03_mars_launch_window.py +91 -0
- astrodynamics_mcp-0.1.0/mkdocs.yml +76 -0
- astrodynamics_mcp-0.1.0/pyproject.toml +163 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/__init__.py +15 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/cache.py +214 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/cli.py +130 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/data/__init__.py +27 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/data/celestrak.py +269 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/data/horizons.py +159 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/data/iers.py +81 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/errors.py +138 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/py.typed +0 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/schemas/__init__.py +35 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/schemas/base.py +493 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/server.py +116 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/server_lint.py +137 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/__init__.py +14 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/_astropy_frames.py +109 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/access.py +321 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/bplane.py +392 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/frames.py +176 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/lambert.py +411 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/porkchop.py +576 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/propagation.py +211 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/time.py +263 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/tools/tle.py +127 -0
- astrodynamics_mcp-0.1.0/src/astrodynamics_mcp/units.py +321 -0
- astrodynamics_mcp-0.1.0/tests/__init__.py +0 -0
- astrodynamics_mcp-0.1.0/tests/_regenerate_goldens.py +55 -0
- astrodynamics_mcp-0.1.0/tests/_sample_calls.py +440 -0
- astrodynamics_mcp-0.1.0/tests/conftest.py +3 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/access_windows.json +154 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/bplane_target.json +24 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/frame_transform.json +23 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/lambert_solve.json +96 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/porkchop.json +150 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/sgp4_iss_24h.json +2904 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/sgp4_propagate.json +44 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/time_convert.json +7 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/tle_lookup.json +31 -0
- astrodynamics_mcp-0.1.0/tests/data/golden/tle_lookup_iss.json +31 -0
- astrodynamics_mcp-0.1.0/tests/test_cache.py +364 -0
- astrodynamics_mcp-0.1.0/tests/test_cli.py +123 -0
- astrodynamics_mcp-0.1.0/tests/test_cli_http_smoke.py +112 -0
- astrodynamics_mcp-0.1.0/tests/test_data_celestrak.py +518 -0
- astrodynamics_mcp-0.1.0/tests/test_data_horizons.py +335 -0
- astrodynamics_mcp-0.1.0/tests/test_data_iers.py +101 -0
- astrodynamics_mcp-0.1.0/tests/test_data_source_failure_modes.py +144 -0
- astrodynamics_mcp-0.1.0/tests/test_errors.py +177 -0
- astrodynamics_mcp-0.1.0/tests/test_eval_ci_report.py +284 -0
- astrodynamics_mcp-0.1.0/tests/test_eval_constraints.py +176 -0
- astrodynamics_mcp-0.1.0/tests/test_eval_coverage.py +105 -0
- astrodynamics_mcp-0.1.0/tests/test_eval_functional.py +223 -0
- astrodynamics_mcp-0.1.0/tests/test_eval_prompts.py +125 -0
- astrodynamics_mcp-0.1.0/tests/test_eval_scoring.py +292 -0
- astrodynamics_mcp-0.1.0/tests/test_examples.py +52 -0
- astrodynamics_mcp-0.1.0/tests/test_frame_unit_equivalence.py +141 -0
- astrodynamics_mcp-0.1.0/tests/test_import.py +13 -0
- astrodynamics_mcp-0.1.0/tests/test_reference_output.py +118 -0
- astrodynamics_mcp-0.1.0/tests/test_schemas_base.py +433 -0
- astrodynamics_mcp-0.1.0/tests/test_server.py +238 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_access_windows.py +479 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_bplane_target.py +504 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_description_lint.py +198 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_frame_transform.py +320 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_lambert_solve.py +422 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_output_roundtrip.py +72 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_porkchop.py +956 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_sgp4_propagate.py +374 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_time_convert.py +407 -0
- astrodynamics_mcp-0.1.0/tests/test_tool_tle.py +276 -0
- astrodynamics_mcp-0.1.0/tests/test_transport_equivalence.py +229 -0
- astrodynamics_mcp-0.1.0/tests/test_unit_discipline.py +277 -0
- astrodynamics_mcp-0.1.0/tests/test_units.py +176 -0
- astrodynamics_mcp-0.1.0/tests/test_upstream_pins.py +100 -0
- astrodynamics_mcp-0.1.0/uv.lock +4300 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Bug
|
|
2
|
+
description: Report a defect in astrodynamics-mcp.
|
|
3
|
+
title: "<short summary>"
|
|
4
|
+
labels: ["type:bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: what_happened
|
|
8
|
+
attributes:
|
|
9
|
+
label: What happened
|
|
10
|
+
description: Observed behavior. Include error messages, MCP error envelopes, and tracebacks verbatim.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: what_expected
|
|
15
|
+
attributes:
|
|
16
|
+
label: What you expected
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: repro
|
|
21
|
+
attributes:
|
|
22
|
+
label: Minimal reproduction
|
|
23
|
+
description: Smallest snippet that triggers the bug. A tool name plus the arguments you called it with (or the natural-language prompt that produced the broken call) is ideal.
|
|
24
|
+
render: python
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: input
|
|
28
|
+
id: server_version
|
|
29
|
+
attributes:
|
|
30
|
+
label: astrodynamics-mcp version
|
|
31
|
+
placeholder: "e.g. 0.1.0, or git sha"
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: dropdown
|
|
35
|
+
id: transport
|
|
36
|
+
attributes:
|
|
37
|
+
label: Transport
|
|
38
|
+
options:
|
|
39
|
+
- stdio
|
|
40
|
+
- http
|
|
41
|
+
- Both
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
- type: input
|
|
45
|
+
id: client
|
|
46
|
+
attributes:
|
|
47
|
+
label: MCP client
|
|
48
|
+
description: Which client surfaced the bug, and its version.
|
|
49
|
+
placeholder: "e.g. Claude Code 2.4.1, Cursor 0.45, raw Python script using `mcp` SDK"
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
52
|
+
- type: input
|
|
53
|
+
id: python_version
|
|
54
|
+
attributes:
|
|
55
|
+
label: Python version
|
|
56
|
+
placeholder: "e.g. 3.12.3"
|
|
57
|
+
validations:
|
|
58
|
+
required: true
|
|
59
|
+
- type: dropdown
|
|
60
|
+
id: os
|
|
61
|
+
attributes:
|
|
62
|
+
label: Operating system
|
|
63
|
+
options:
|
|
64
|
+
- Linux
|
|
65
|
+
- Windows
|
|
66
|
+
- macOS
|
|
67
|
+
- Other
|
|
68
|
+
validations:
|
|
69
|
+
required: true
|
|
70
|
+
- type: textarea
|
|
71
|
+
id: logs
|
|
72
|
+
attributes:
|
|
73
|
+
label: Logs
|
|
74
|
+
description: Server stderr, MCP error payloads, client-side traces.
|
|
75
|
+
render: shell
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Client compatibility report
|
|
2
|
+
description: Tell us how astrodynamics-mcp works (or doesn't) inside a specific MCP client.
|
|
3
|
+
title: "<client name + version>: <one-line outcome>"
|
|
4
|
+
labels: ["type:client-compatibility"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Use this template to report on a specific MCP client's behaviour:
|
|
10
|
+
whether stdio / http transports work, whether tools are visible, whether
|
|
11
|
+
tool descriptions and units survive the round-trip, and any client-side
|
|
12
|
+
quirks. These reports populate the "supported clients" matrix in the
|
|
13
|
+
docs. Even a successful "everything works" report is welcome.
|
|
14
|
+
- type: input
|
|
15
|
+
id: client
|
|
16
|
+
attributes:
|
|
17
|
+
label: MCP client and version
|
|
18
|
+
placeholder: "e.g. Claude Code 2.4.1, Cursor 0.45, ChatGPT desktop 1.2024.345, custom LangGraph agent on mcp 1.27.0"
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: input
|
|
22
|
+
id: server_version
|
|
23
|
+
attributes:
|
|
24
|
+
label: astrodynamics-mcp version
|
|
25
|
+
placeholder: "e.g. 0.1.0, or git sha"
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: dropdown
|
|
29
|
+
id: transport
|
|
30
|
+
attributes:
|
|
31
|
+
label: Transport used
|
|
32
|
+
options:
|
|
33
|
+
- stdio
|
|
34
|
+
- http (Streamable HTTP)
|
|
35
|
+
- http (SSE — deprecated, backward-compat only)
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
- type: dropdown
|
|
39
|
+
id: os
|
|
40
|
+
attributes:
|
|
41
|
+
label: Operating system
|
|
42
|
+
options:
|
|
43
|
+
- Linux
|
|
44
|
+
- Windows
|
|
45
|
+
- macOS
|
|
46
|
+
- Other
|
|
47
|
+
validations:
|
|
48
|
+
required: true
|
|
49
|
+
- type: dropdown
|
|
50
|
+
id: outcome
|
|
51
|
+
attributes:
|
|
52
|
+
label: Overall outcome
|
|
53
|
+
options:
|
|
54
|
+
- "Works — tools visible, calls succeed, results render."
|
|
55
|
+
- "Partial — some tools or call patterns are broken."
|
|
56
|
+
- "Broken — server doesn't load, or no tools visible to the client."
|
|
57
|
+
validations:
|
|
58
|
+
required: true
|
|
59
|
+
- type: textarea
|
|
60
|
+
id: setup
|
|
61
|
+
attributes:
|
|
62
|
+
label: Setup
|
|
63
|
+
description: Paste the exact MCP server config block (with secrets redacted).
|
|
64
|
+
render: json
|
|
65
|
+
validations:
|
|
66
|
+
required: true
|
|
67
|
+
- type: textarea
|
|
68
|
+
id: tools_observed
|
|
69
|
+
attributes:
|
|
70
|
+
label: Tools the client sees
|
|
71
|
+
description: List which of the v0.1 tools the client surfaces (or "all 8" / "none"). If the client doesn't surface a `tools/list`, paste the closest observable equivalent.
|
|
72
|
+
- type: textarea
|
|
73
|
+
id: tools_called
|
|
74
|
+
attributes:
|
|
75
|
+
label: Tools you actually called
|
|
76
|
+
description: One or two example tool calls you ran end-to-end. Include the natural-language prompt that triggered each.
|
|
77
|
+
- type: textarea
|
|
78
|
+
id: problems
|
|
79
|
+
attributes:
|
|
80
|
+
label: Problems observed
|
|
81
|
+
description: Quirks, edge cases, broken units, awkward error rendering, slow timeouts — anything that worked but felt wrong.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Question or discussion
|
|
4
|
+
url: https://github.com/orgs/astro-tools/discussions
|
|
5
|
+
about: Open a discussion for usage questions, ideas, or general chat. The astro-tools org runs a single shared discussions space — there is no per-repo discussions board.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Tool request
|
|
2
|
+
description: I want astrodynamics-mcp to compute X — does it fit?
|
|
3
|
+
title: "<short summary of the X you want>"
|
|
4
|
+
labels: ["type:tool-request"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
astrodynamics-mcp wraps vetted upstream astrodynamics libraries (sgp4,
|
|
10
|
+
lamberthub, skyfield, astropy, …) so LLM clients can call them as tools.
|
|
11
|
+
Before filing, please skim `CONTRIBUTING.md` — the "Scope discipline"
|
|
12
|
+
section names the libraries we wrap and the orthogonal projects that
|
|
13
|
+
own neighbouring surfaces. If your need is squarely in one of those
|
|
14
|
+
adjacent projects, you'll get a faster answer there.
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: what_i_want
|
|
17
|
+
attributes:
|
|
18
|
+
label: What you want to compute
|
|
19
|
+
description: One or two sentences. What's the natural-language question you'd ask an LLM client that should drop into a tool call?
|
|
20
|
+
placeholder: "e.g. 'For a TLE I provide, when is the next eclipse of the satellite by Earth?'"
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
- type: textarea
|
|
24
|
+
id: example_session
|
|
25
|
+
attributes:
|
|
26
|
+
label: Example session
|
|
27
|
+
description: How would you prompt an MCP-enabled client (Claude Code, Cursor, ChatGPT desktop, …) to invoke this? What inputs / units / outputs do you expect?
|
|
28
|
+
placeholder: |
|
|
29
|
+
> User: "When does Hubble enter eclipse during the next 7 days?"
|
|
30
|
+
> # LLM should call: eclipse_predict(tle=..., start=..., duration_days=7)
|
|
31
|
+
> # Expected output: list of {entry_utc, exit_utc, duration_s, type: umbra|penumbra}
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: upstream_library
|
|
36
|
+
attributes:
|
|
37
|
+
label: Upstream library that could back this
|
|
38
|
+
description: Which existing Python library (or libraries) implements the computation? If unsure, say so — we'll dig.
|
|
39
|
+
placeholder: "e.g. skyfield has eclipse helpers via dark_twilight_day; astropy.coordinates.get_sun + custom shadow geometry."
|
|
40
|
+
- type: textarea
|
|
41
|
+
id: what_i_tried
|
|
42
|
+
attributes:
|
|
43
|
+
label: What you tried instead
|
|
44
|
+
description: Did you try to use an existing tool (poorly) or a different MCP server? What broke or felt wrong?
|
|
45
|
+
- type: dropdown
|
|
46
|
+
id: priority
|
|
47
|
+
attributes:
|
|
48
|
+
label: How important is this to you
|
|
49
|
+
options:
|
|
50
|
+
- "Blocker — I can't use astrodynamics-mcp for my work without it."
|
|
51
|
+
- "Strong wish — I have a workaround but it's awkward."
|
|
52
|
+
- "Nice to have — drop into the backlog and ship when convenient."
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Thanks for contributing to astrodynamics-mcp. Keep PRs small and scoped to one issue.
|
|
3
|
+
-->
|
|
4
|
+
|
|
5
|
+
## Summary
|
|
6
|
+
|
|
7
|
+
<!-- One or two sentences: what this PR changes and why. -->
|
|
8
|
+
|
|
9
|
+
Closes #
|
|
10
|
+
|
|
11
|
+
## Changes
|
|
12
|
+
|
|
13
|
+
<!-- Short bullet list of the substantive changes. Omit trivia (formatting, imports). -->
|
|
14
|
+
|
|
15
|
+
-
|
|
16
|
+
|
|
17
|
+
## Tested with
|
|
18
|
+
|
|
19
|
+
<!-- Tick what you ran locally. CI will re-run on both Ubuntu and Windows. -->
|
|
20
|
+
|
|
21
|
+
- [ ] `pytest`
|
|
22
|
+
- [ ] `ruff check`
|
|
23
|
+
- [ ] `ruff format --check`
|
|
24
|
+
- [ ] `mypy`
|
|
25
|
+
- [ ] End-to-end smoke against an MCP client (if this PR touches a tool, transport, or schema)
|
|
26
|
+
|
|
27
|
+
## Breaking changes
|
|
28
|
+
|
|
29
|
+
<!-- "None" if none. Otherwise: what breaks, who is affected, migration notes. -->
|
|
30
|
+
|
|
31
|
+
None.
|
|
32
|
+
|
|
33
|
+
## Notes for reviewers
|
|
34
|
+
|
|
35
|
+
<!-- Optional. Things to look at first, known rough edges, questions for the reviewer. -->
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: test (${{ matrix.os }}, py${{ matrix.python-version }})
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
timeout-minutes: 30
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
# Ubuntu + Windows × 3 Python minors = 6 cells. macOS is deferred
|
|
20
|
+
# to v0.2 per the project charter.
|
|
21
|
+
matrix:
|
|
22
|
+
os: [ubuntu-latest, windows-latest]
|
|
23
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
|
|
27
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
28
|
+
uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
31
|
+
|
|
32
|
+
- name: Install uv
|
|
33
|
+
uses: astral-sh/setup-uv@v4
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
cache-dependency-glob: uv.lock
|
|
37
|
+
|
|
38
|
+
- name: Install project
|
|
39
|
+
run: uv sync --all-groups
|
|
40
|
+
|
|
41
|
+
- name: Run pytest
|
|
42
|
+
# `-m "integration or not integration"` overrides the default
|
|
43
|
+
# marker filter in pyproject.toml so CI runs both unit and
|
|
44
|
+
# integration suites in a single invocation.
|
|
45
|
+
run: uv run pytest -m "integration or not integration" --cov --cov-report=term-missing
|
|
46
|
+
|
|
47
|
+
- name: Enforce coverage gates
|
|
48
|
+
# Per CONTRIBUTING.md: 90% overall, 95% on the layers whose
|
|
49
|
+
# correctness the LLM consumer can't sanity-check (units,
|
|
50
|
+
# schemas, data adapters). Run only on Ubuntu / Python 3.12 to
|
|
51
|
+
# avoid platform-specific differences inflating misses.
|
|
52
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
|
|
53
|
+
run: |
|
|
54
|
+
uv run coverage report --fail-under=90
|
|
55
|
+
uv run coverage report --include='src/astrodynamics_mcp/units.py' --fail-under=95
|
|
56
|
+
uv run coverage report --include='src/astrodynamics_mcp/schemas/*' --fail-under=95
|
|
57
|
+
uv run coverage report --include='src/astrodynamics_mcp/data/*' --fail-under=95
|
|
58
|
+
|
|
59
|
+
lint:
|
|
60
|
+
name: lint
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
timeout-minutes: 5
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v4
|
|
65
|
+
- uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: '3.12'
|
|
68
|
+
- uses: astral-sh/setup-uv@v4
|
|
69
|
+
with:
|
|
70
|
+
enable-cache: true
|
|
71
|
+
cache-dependency-glob: uv.lock
|
|
72
|
+
- run: uv sync --all-groups
|
|
73
|
+
- run: uv run ruff check
|
|
74
|
+
- run: uv run ruff format --check
|
|
75
|
+
|
|
76
|
+
typecheck:
|
|
77
|
+
name: typecheck
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
timeout-minutes: 10
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
- uses: actions/setup-python@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: '3.12'
|
|
85
|
+
- uses: astral-sh/setup-uv@v4
|
|
86
|
+
with:
|
|
87
|
+
enable-cache: true
|
|
88
|
+
cache-dependency-glob: uv.lock
|
|
89
|
+
- run: uv sync --all-groups
|
|
90
|
+
- run: uv run mypy
|
|
91
|
+
|
|
92
|
+
# Smoke-check that `pip install astrodynamics-mcp` (no extras, no dev group)
|
|
93
|
+
# imports cleanly and the console script resolves. Catches an extras-only
|
|
94
|
+
# dependency leaking into the default install path. The full test job above
|
|
95
|
+
# exercises every dev dep via the dev group; this is a small canary.
|
|
96
|
+
minimal-install:
|
|
97
|
+
name: minimal install smoke
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
timeout-minutes: 5
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
- uses: actions/setup-python@v5
|
|
103
|
+
with:
|
|
104
|
+
python-version: '3.12'
|
|
105
|
+
- run: pip install .
|
|
106
|
+
- run: python -c "import astrodynamics_mcp"
|
|
107
|
+
- run: astrodynamics-mcp --version
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ['v*']
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: docs-${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: build
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 5
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
- uses: astral-sh/setup-uv@v4
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
cache-dependency-glob: uv.lock
|
|
28
|
+
- run: uv sync --all-groups
|
|
29
|
+
- run: uv run mkdocs build --strict
|
|
30
|
+
|
|
31
|
+
deploy:
|
|
32
|
+
name: deploy
|
|
33
|
+
needs: build
|
|
34
|
+
if: |
|
|
35
|
+
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
|
|
36
|
+
github.event_name == 'workflow_dispatch'
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
timeout-minutes: 5
|
|
39
|
+
permissions:
|
|
40
|
+
contents: write
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
with:
|
|
44
|
+
fetch-depth: 0
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: '3.12'
|
|
48
|
+
- uses: astral-sh/setup-uv@v4
|
|
49
|
+
with:
|
|
50
|
+
enable-cache: true
|
|
51
|
+
cache-dependency-glob: uv.lock
|
|
52
|
+
- run: uv sync --all-groups
|
|
53
|
+
- name: Configure git identity
|
|
54
|
+
run: |
|
|
55
|
+
git config user.name "github-actions[bot]"
|
|
56
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
57
|
+
- run: uv run mkdocs gh-deploy --force --no-history
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
name: Eval
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# Manual-only for now while the gate is being shaken down. Once it
|
|
5
|
+
# passes consistently, add `push: branches: [main]` and a weekly
|
|
6
|
+
# cron so regressions surface without per-PR cost.
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tier:
|
|
10
|
+
description: "Optional tier filter (single_tool | sequential | planning). Empty runs the full suite."
|
|
11
|
+
required: false
|
|
12
|
+
default: ""
|
|
13
|
+
type: choice
|
|
14
|
+
options: ['', 'single_tool', 'sequential', 'planning']
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: eval-${{ github.workflow }}-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
eval:
|
|
22
|
+
name: eval
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 30
|
|
25
|
+
permissions:
|
|
26
|
+
# `models: read` lets the workflow call api.github.com/inference
|
|
27
|
+
# via the auto-generated GITHUB_TOKEN.
|
|
28
|
+
models: read
|
|
29
|
+
contents: read
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
|
|
33
|
+
- uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: '3.12'
|
|
36
|
+
|
|
37
|
+
- uses: astral-sh/setup-uv@v4
|
|
38
|
+
with:
|
|
39
|
+
enable-cache: true
|
|
40
|
+
cache-dependency-glob: uv.lock
|
|
41
|
+
|
|
42
|
+
- run: uv sync --all-groups
|
|
43
|
+
|
|
44
|
+
- name: Probe GitHub Models auth
|
|
45
|
+
# Run a one-token call against the eval model before the full
|
|
46
|
+
# suite so any auth failure surfaces here as a clear HTTP status
|
|
47
|
+
# and error body, rather than buried inside the Inspect AI stack
|
|
48
|
+
# trace. Prefer the MODELS_PAT secret when present — on Free-plan
|
|
49
|
+
# orgs the workflow-issued GITHUB_TOKEN is an unreliable inference
|
|
50
|
+
# auth path (observed 403 and 429 without obvious cause). Use a
|
|
51
|
+
# personal-owned PAT with `Models: Read` for MODELS_PAT; org-owned
|
|
52
|
+
# PATs return 403 no_access from this endpoint regardless of
|
|
53
|
+
# granted permissions. See eval/README.md for provisioning.
|
|
54
|
+
#
|
|
55
|
+
# Retries with exponential backoff because GitHub's secondary
|
|
56
|
+
# anti-abuse rate limit returns 429 for ~5-30 min when the
|
|
57
|
+
# triggering account has been making many recent requests. The
|
|
58
|
+
# retry loop lets routine CI churn ride through it.
|
|
59
|
+
env:
|
|
60
|
+
MODELS_PAT: ${{ secrets.MODELS_PAT }}
|
|
61
|
+
WORKFLOW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
62
|
+
run: |
|
|
63
|
+
TOKEN="${MODELS_PAT:-$WORKFLOW_TOKEN}"
|
|
64
|
+
status=""
|
|
65
|
+
for delay in 0 30 60 120 180; do
|
|
66
|
+
[ "$delay" -gt 0 ] && { echo "Backing off ${delay}s before retry"; sleep "$delay"; }
|
|
67
|
+
status=$(curl -s -o /tmp/probe.json -w '%{http_code}' \
|
|
68
|
+
https://models.github.ai/inference/chat/completions \
|
|
69
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
70
|
+
-H "Content-Type: application/json" \
|
|
71
|
+
-d '{"model":"openai/gpt-4.1-mini","messages":[{"role":"user","content":"PING"}],"max_tokens":2}')
|
|
72
|
+
echo "HTTP $status"
|
|
73
|
+
head -c 500 /tmp/probe.json; echo
|
|
74
|
+
case "$status" in
|
|
75
|
+
200) break ;;
|
|
76
|
+
429) continue ;;
|
|
77
|
+
*) echo "Non-retriable status $status"; break ;;
|
|
78
|
+
esac
|
|
79
|
+
done
|
|
80
|
+
test "$status" = "200"
|
|
81
|
+
|
|
82
|
+
- name: Run eval suite
|
|
83
|
+
env:
|
|
84
|
+
# The openai-api/github/* provider in Inspect AI derives env vars
|
|
85
|
+
# from the segment after the slash; here `github` maps to GITHUB_*.
|
|
86
|
+
# MODELS_PAT (if set) overrides the workflow-issued GITHUB_TOKEN —
|
|
87
|
+
# see the probe step above for the rationale.
|
|
88
|
+
GITHUB_API_KEY: ${{ secrets.MODELS_PAT || secrets.GITHUB_TOKEN }}
|
|
89
|
+
GITHUB_BASE_URL: https://models.github.ai/inference
|
|
90
|
+
run: |
|
|
91
|
+
# Flags explained:
|
|
92
|
+
# * -M strict_tools=false : pydantic unions in our schemas use
|
|
93
|
+
# anyOf + $ref, which OpenAI strict-mode tool-calling rejects.
|
|
94
|
+
# * --max-samples 3 : prompts processed concurrently. GH
|
|
95
|
+
# Models Free-plan Low-tier (gpt-4.1-mini) caps concurrent
|
|
96
|
+
# requests at 5; we sit 2 below the ceiling to absorb
|
|
97
|
+
# multi-turn tool-call bursts within each sample.
|
|
98
|
+
# * --max-connections 4 : max in-flight HTTP requests across
|
|
99
|
+
# all samples (covers retries + tool-call turns); 1 below
|
|
100
|
+
# the 5-concurrent ceiling so a transient retry can fire
|
|
101
|
+
# without hitting the cap.
|
|
102
|
+
# * --no-fail-on-error : let every sample run to completion
|
|
103
|
+
# even when others error. Errored samples count against
|
|
104
|
+
# accuracy in eval/_ci_report.py (zero-scored), so the
|
|
105
|
+
# gate still fails them; we just don't want to lose data
|
|
106
|
+
# from in-flight samples being cancelled when an error
|
|
107
|
+
# threshold trips. Inspect AI's default ('fail on any
|
|
108
|
+
# error') is too aggressive for a survey gate.
|
|
109
|
+
if [ -n "${{ inputs.tier }}" ]; then
|
|
110
|
+
uv run inspect eval eval/tasks.py@astrodynamics_mcp_eval_subset \
|
|
111
|
+
-T tier="${{ inputs.tier }}" \
|
|
112
|
+
--model openai-api/github/openai/gpt-4.1-mini \
|
|
113
|
+
-M strict_tools=false \
|
|
114
|
+
--max-samples 3 \
|
|
115
|
+
--max-connections 4 \
|
|
116
|
+
--no-fail-on-error \
|
|
117
|
+
--temperature 0 \
|
|
118
|
+
--log-dir logs
|
|
119
|
+
else
|
|
120
|
+
uv run inspect eval eval/tasks.py@astrodynamics_mcp_eval \
|
|
121
|
+
--model openai-api/github/openai/gpt-4.1-mini \
|
|
122
|
+
-M strict_tools=false \
|
|
123
|
+
--max-samples 3 \
|
|
124
|
+
--max-connections 4 \
|
|
125
|
+
--no-fail-on-error \
|
|
126
|
+
--temperature 0 \
|
|
127
|
+
--log-dir logs
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
- name: Upload Inspect log artifact
|
|
131
|
+
if: always()
|
|
132
|
+
uses: actions/upload-artifact@v4
|
|
133
|
+
with:
|
|
134
|
+
name: inspect-eval-logs
|
|
135
|
+
path: logs/
|
|
136
|
+
retention-days: 14
|
|
137
|
+
|
|
138
|
+
- name: Generate report
|
|
139
|
+
id: report
|
|
140
|
+
if: always()
|
|
141
|
+
# `set +e` so we capture the exit code; the workflow fails on it
|
|
142
|
+
# in the dedicated step below so the report still lands in the
|
|
143
|
+
# run summary even when the gate fails. The report body is
|
|
144
|
+
# appended to GITHUB_STEP_SUMMARY — that's where the score
|
|
145
|
+
# appears at the top of the workflow run page.
|
|
146
|
+
run: |
|
|
147
|
+
set +e
|
|
148
|
+
uv run python eval/_ci_report.py \
|
|
149
|
+
--log-dir logs \
|
|
150
|
+
--threshold 0.80 >> "$GITHUB_STEP_SUMMARY"
|
|
151
|
+
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
|
|
152
|
+
|
|
153
|
+
- name: Enforce threshold
|
|
154
|
+
# The report step uses `set +e`, so we fail here based on its exit code.
|
|
155
|
+
# Code 0 = passed gate, 1 = below threshold, 2 = missing or empty log.
|
|
156
|
+
if: steps.report.outputs.exit_code != '0'
|
|
157
|
+
run: |
|
|
158
|
+
echo "Eval gate failed: _ci_report.py exited with ${{ steps.report.outputs.exit_code }}."
|
|
159
|
+
exit 1
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ['v*']
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: release-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: build sdist + wheel
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 5
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
- uses: astral-sh/setup-uv@v4
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
cache-dependency-glob: uv.lock
|
|
28
|
+
- run: uv build
|
|
29
|
+
- uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
if-no-files-found: error
|
|
34
|
+
|
|
35
|
+
publish-pypi:
|
|
36
|
+
name: publish to PyPI
|
|
37
|
+
needs: build
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
timeout-minutes: 10
|
|
40
|
+
environment:
|
|
41
|
+
name: pypi
|
|
42
|
+
url: https://pypi.org/p/astrodynamics-mcp
|
|
43
|
+
permissions:
|
|
44
|
+
id-token: write
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/download-artifact@v4
|
|
47
|
+
with:
|
|
48
|
+
name: dist
|
|
49
|
+
path: dist/
|
|
50
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
51
|
+
with:
|
|
52
|
+
skip-existing: true
|
|
53
|
+
|
|
54
|
+
github-release:
|
|
55
|
+
name: github release
|
|
56
|
+
needs: publish-pypi
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
timeout-minutes: 5
|
|
59
|
+
permissions:
|
|
60
|
+
contents: write
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/download-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: dist
|
|
65
|
+
path: dist/
|
|
66
|
+
- name: Create GitHub Release
|
|
67
|
+
env:
|
|
68
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
69
|
+
run: |
|
|
70
|
+
gh release create "${GITHUB_REF_NAME}" \
|
|
71
|
+
--repo "${GITHUB_REPOSITORY}" \
|
|
72
|
+
--title "${GITHUB_REF_NAME}" \
|
|
73
|
+
--generate-notes \
|
|
74
|
+
dist/*
|