Compare commits

..

1 Commits

Author SHA1 Message Date
sdk-dev c0a6213b36 infra(sdk): add all-required sentinel to CI workflow
Test / test (3.13) (pull_request) Successful in 1m47s
Test / test (3.12) (pull_request) Successful in 1m50s
Test / test (3.11) (pull_request) Successful in 1m54s
Test / all-required (pull_request) Successful in 2s
Adds the `all-required` job to `.gitea/workflows/ci.yml` so the
`Test / all-required (pull_request)` context is available as a
single hard-gate status check for branch protection.

Uses `toJSON(needs)` + Python parser (matching molecule-core pattern)
to reliably detect non-green matrix job results.

Closes: molecule-ai/molecule-sdk-python#11

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 12:57:20 +00:00
6 changed files with 38 additions and 18 deletions
+29
View File
@@ -27,3 +27,32 @@ jobs:
- name: Lint
run: pip install ruff && ruff check molecule_agent/ molecule_plugin/
all-required:
name: all-required
needs: [test]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Assert every required dependency succeeded
run: |
set -euo pipefail
results='${{ toJSON(needs) }}'
echo "$results"
echo "$results" | python3 -c '
import json, sys
ns = json.load(sys.stdin)
bad = [(k, v.get("result")) for k, v in ns.items()
if v.get("result") not in ("success", None, "cancelled", "skipped")]
if bad:
print("FAIL: jobs not green:", file=sys.stderr)
for k, r in bad:
print(f" - {k}: {r}", file=sys.stderr)
sys.exit(1)
pending = [(k, v.get("result")) for k, v in ns.items()
if v.get("result") is None]
if pending:
print(f"WARN: {len(pending)} job(s) still in-flight (result=null): " +
", ".join(k for k, _ in pending), file=sys.stderr)
print(f"OK: all {len(ns)} required jobs succeeded")
'
+1 -1
View File
@@ -27,7 +27,7 @@ curl -s -X POST http://localhost:8080/workspaces/<UUID>/secrets \
# 3. Run the demo from any machine that can reach the platform:
WORKSPACE_ID=<UUID> PLATFORM_URL=http://localhost:8080 \
python3 examples/remote-agent/run.py
python3 sdk/python/examples/remote-agent/run.py
```
You should see log lines for each of the three phases, and then
+2 -2
View File
@@ -60,7 +60,7 @@ print(f"loop exited: {terminal}")
```
A runnable demo with full setup walkthrough lives at
[`examples/remote-agent/`](https://git.moleculesai.app/Molecule-AI/molecule-sdk-python/-/tree/main/examples/remote-agent) — the runnable demo with full setup walkthrough.
[`sdk/python/examples/remote-agent/`](../examples/remote-agent).
## What the SDK gives you
@@ -282,5 +282,5 @@ the security benefits of bearer auth until both sides upgrade.
- [`molecule_plugin`](../molecule_plugin) — the *other* SDK in this
package, for plugin authors. Different audience.
- [`examples/remote-agent/run.py`](https://git.moleculesai.app/Molecule-AI/molecule-sdk-python/-/blob/main/examples/remote-agent/run.py)
- [`sdk/python/examples/remote-agent/run.py`](../examples/remote-agent/run.py)
— the runnable demo that proves all of the above end-to-end.
+1 -1
View File
@@ -20,7 +20,7 @@ Intended usage::
env = client.pull_secrets() # decrypted secrets dict
client.run_heartbeat_loop() # background heartbeat + state-poll
See ``examples/remote-agent/`` for a runnable demo.
See ``sdk/python/examples/remote-agent/`` for a runnable demo.
Design notes:
* **No async.** The SDK uses blocking ``requests`` so a remote agent author
+4 -13
View File
@@ -11,19 +11,10 @@ a Phase 30 endpoint:
* :py:meth:`run_heartbeat_loop` — drives heartbeat + state-poll on a timer,
returns when the platform reports the workspace paused or deleted.
The client also exposes two inbound delivery paths for handling platform-initiated
A2A messages:
* **Push mode** — :class:`molecule_agent.a2a_server.A2AServer` hosts an HTTP server
in a background thread; platform pushes inbound A2A as HTTP requests. Use when the
agent has a publicly reachable URL (cloud VM, ngrok tunnel, etc.).
* **Poll mode** — :class:`molecule_agent.inbound.PollDelivery` polls
``GET /workspaces/:id/activity`` on a configurable interval; no public URL required.
The default when no explicit delivery is passed to :py:meth:`run_agent_loop`.
Both feed the same :py:class:`molecule_agent.inbound.MessageHandler` callback.
Reply routing (``/notify`` for canvas users, ``/a2a`` for peer agents) is handled
automatically by :py:meth:`reply`.
No inbound A2A server is bundled here yet — that requires hosting an HTTP
endpoint the platform's proxy can reach, which is network-dependent.
Use :class:`molecule_agent.a2a_server.A2AServer` to add inbound A2A support.
See that module for usage and the Phase 30.8b contract.
"""
from __future__ import annotations
+1 -1
View File
@@ -26,7 +26,7 @@ Example: a minimal plugin that's installable on Claude Code and DeepAgents
├── claude_code.py # `from molecule_plugin import AgentskillsAdaptor as Adaptor`
└── deepagents.py # same one-liner
Full docs + cookiecutter template: see the repo root ``README.md``.
Full docs + cookiecutter template: see ``sdk/python/README.md``.
"""
from __future__ import annotations