Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/openclaw-acp-bridge-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: openclaw-acp-bridge smoke

# Runs the Plugin-bundled smoke test on every push that touches
# the Plugin and on every PR that does the same.
#
# v0.2.0 change: this workflow no longer checks out any external SDK.
# The HTTP client used by the Skills (`client/_acp_client.py`) is
# bundled inside the Plugin, so the smoke + no-redirect tests are now
# the runtime's own tests. There is no `actions/checkout` of
# `antianqi/openclaw-mcode-acp`, no `SMOKE_SKIP_LIVE=1`, and no
# `ACP_HOME` to set.
#
# A live ACP server is required for the inbox roundtrip check; the
# workflow stands one up via a pre-flight Python script and tears it
# down on exit. Health-check failures on an unreachable server are
# reported as failures (not silently skipped), so a regression on
# runtime reachability is caught in CI rather than masked.

on:
push:
paths:
- 'plugins/antianqi/openclaw-acp-bridge/**'
- '.github/workflows/openclaw-acp-bridge-smoke.yml'
pull_request:
paths:
- 'plugins/antianqi/openclaw-acp-bridge/**'
- '.github/workflows/openclaw-acp-bridge-smoke.yml'

permissions:
contents: read

jobs:
smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b18 # v7.0.1

- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.3.0
with:
python-version: '3.11'

- name: Run bundled no-redirect regression test
# Runs without a live server: stands up its own loopback
# redirector + capture pair and asserts the bundled client
# refuses 3xx. This is the property the v0.1.3 review asked for.
run: |
set -euo pipefail
python plugins/antianqi/openclaw-acp-bridge/scripts/test_no_redirect.py

- name: Run bundled smoke test
# Starts a stub ACP server (subclass of BaseHTTPRequestHandler)
# and runs the smoke test against it. The stub implements
# /acp/health, /acp/inbox/write, /acp/inbox/read with
# reproducible JSON, and a /acp/inbox/redirect path that
# returns 302 to make sure the bundled client refuses it.
#
# v0.2.1 change: the stub is now started with --token so its
# `_check_auth` actually rejects missing / wrong Authorization
# headers. The previous workflow started the stub without
# --token; `_check_auth` then took the "auth disabled" branch
# and the smoke roundtrip never proved the server enforces
# auth. The negative tests added in v0.2.1 (Check 8 missing
# auth, Check 9 wrong auth) require the stub to be in the
# "auth required" state.
env:
ACP_TOKEN: 'ci-test-token-xyzzy'
ACP_BASE_URL: 'http://127.0.0.1:19999'
run: |
set -euo pipefail
python plugins/antianqi/openclaw-acp-bridge/scripts/stub_server.py \
--token "$ACP_TOKEN" &
STUB_PID=$!
trap "kill $STUB_PID 2>/dev/null || true" EXIT
sleep 0.5
python plugins/antianqi/openclaw-acp-bridge/scripts/smoke.py

- name: Validate plugin manifest
run: |
set -euo pipefail
node scripts/validate.mjs
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules/
.DS_Store
coverage/
*.log
__pycache__/
*.pyc
15 changes: 15 additions & 0 deletions examples/hello-mcode-hooks/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
61 changes: 61 additions & 0 deletions examples/hello-mcode-hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# hello-mcode-hooks

A minimal Plugin that ships one Skill and one experimental `io.minimax.mcode` Hook entry under
the Agent Plugins 1.0 portable Hooks preview.

## What this example demonstrates

- A Skill-only Agent Plugin (the "hello-hooks" Skill).
- A single Hook entry in `io.minimax.mcode/hooks/hooks.json` that observes `SessionStart`,
`SessionEnd`, and `PreToolUse`.
- Atomic, cross-platform state file writes under the runtime-provided `PLUGIN_DATA` directory.
- Path resolution that uses runtime-injected environment values, not host-absolute literals.

This example is not a working integration; it is a structural reference. MiniMax Code 0.2.4
ships the runtime side of the preview but the portable Hooks proposal is still in review and
registry validation must not execute Hook code.

## Layout

```text
hello-mcode-hooks/
├── README.md
├── LICENSE
├── plugin.json
├── skills/
│ └── hello-hooks/
│ └── SKILL.md
└── io.minimax.mcode/
└── hooks/
├── hooks.json
└── scripts/
└── record.mjs
```

## Hook entry

The Hook entry is one `record.mjs` invocation per event. The script reads the event payload
from stdin (one UTF-8 JSON document, then EOF, as proposed in `proposals/hooks.md` § "Observe-only
runtime semantics") and appends a compact record to `${PLUGIN_DATA}/state.json` using a
staging-file rename. No tool input rewriting, no permission decisions, no network access, no
telemetry.

## Validation expectations

- `plugin.json` continues to target the published Agent Plugins 1.0 schema and remains valid
under `scripts/validate.mjs`.
- `io.minimax.mcode/hooks/hooks.json` is recognized as an experimental client extension
namespace. The validator accepts it but does not require it.
- The script resolves all paths from `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` only.

## Disclosure

This example contains:

- no credentials;
- no network access;
- no telemetry;
- no third-party services.

The same disclosure is repeated in `skills/hello-hooks/SKILL.md` per the
`hello-mcode-hooks` plugin convention.
48 changes: 48 additions & 0 deletions examples/hello-mcode-hooks/io.minimax.mcode/hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"$schema": "https://minimax.io/schemas/mcode-hooks/0.1.0/hooks.schema.json",
"hooks": {
"SessionStart": [
{
"command": "node",
"args": [
"${PLUGIN_ROOT}/io.minimax.mcode/hooks/scripts/record.mjs",
"--event",
"SessionStart",
"--state",
"${PLUGIN_DATA}/state.json"
],
"timeout": 5000,
"once": false
}
],
"SessionEnd": [
{
"command": "node",
"args": [
"${PLUGIN_ROOT}/io.minimax.mcode/hooks/scripts/record.mjs",
"--event",
"SessionEnd",
"--state",
"${PLUGIN_DATA}/state.json"
],
"timeout": 5000,
"once": false
}
],
"PreToolUse": [
{
"command": "node",
"args": [
"${PLUGIN_ROOT}/io.minimax.mcode/hooks/scripts/record.mjs",
"--event",
"PreToolUse",
"--state",
"${PLUGIN_DATA}/state.json"
],
"matcher": "*",
"timeout": 5000,
"once": false
}
]
}
}
Loading