@a5c-ai/triggers-mux 5.0.1-staging.40a93c240e7b
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.
- package/README.md +183 -0
- package/action.yml +413 -0
- package/dist/action.d.ts +15 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +21 -0
- package/dist/action.js.map +1 -0
- package/dist/backends/bitbucket.d.ts +2 -0
- package/dist/backends/bitbucket.d.ts.map +1 -0
- package/dist/backends/bitbucket.js +36 -0
- package/dist/backends/bitbucket.js.map +1 -0
- package/dist/backends/generic-webhook.d.ts +2 -0
- package/dist/backends/generic-webhook.d.ts.map +1 -0
- package/dist/backends/generic-webhook.js +28 -0
- package/dist/backends/generic-webhook.js.map +1 -0
- package/dist/backends/github.d.ts +2 -0
- package/dist/backends/github.d.ts.map +1 -0
- package/dist/backends/github.js +36 -0
- package/dist/backends/github.js.map +1 -0
- package/dist/backends/gitlab.d.ts +2 -0
- package/dist/backends/gitlab.d.ts.map +1 -0
- package/dist/backends/gitlab.js +33 -0
- package/dist/backends/gitlab.js.map +1 -0
- package/dist/backends/index.d.ts +6 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +20 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/utils.d.ts +7 -0
- package/dist/backends/utils.d.ts.map +1 -0
- package/dist/backends/utils.js +22 -0
- package/dist/backends/utils.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +77 -0
- package/dist/cli.js.map +1 -0
- package/dist/enrich.d.ts +2 -0
- package/dist/enrich.d.ts.map +1 -0
- package/dist/enrich.js +115 -0
- package/dist/enrich.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/query.d.ts +5 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +145 -0
- package/dist/query.js.map +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# @a5c-ai/triggers-mux
|
|
2
|
+
|
|
3
|
+
Trigger glue for running any coding agent from CI. Normalizes GitHub, GitLab, Bitbucket, and generic webhook payloads into one event shape, enriches GitHub events with changed files and optional diffs, and evaluates compact trigger queries before launching agent-mux.
|
|
4
|
+
|
|
5
|
+
## CLI
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
triggers evaluate --backend github --query "event:issue_comment text:@develop-this path:packages/agent-mux/**"
|
|
9
|
+
triggers enrich --backend github --include-diff --output event.json
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## GitHub Action
|
|
13
|
+
|
|
14
|
+
The reusable action at `packages/triggers-mux/action.yml` supports all harnesses, providers, and invocation modes.
|
|
15
|
+
|
|
16
|
+
### Quick Start
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- uses: a5c-ai/babysitter/packages/triggers-mux@main
|
|
20
|
+
with:
|
|
21
|
+
harness: claude
|
|
22
|
+
provider: foundry
|
|
23
|
+
model: gpt-5.5
|
|
24
|
+
prompt: Review this PR for bugs and style issues
|
|
25
|
+
env:
|
|
26
|
+
AZURE_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
|
27
|
+
AMUX_API_BASE: ${{ vars.AZURE_OPENAI_ENDPOINT }}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Supported Harnesses
|
|
31
|
+
|
|
32
|
+
| Harness | `harness:` value | Provider examples | Notes |
|
|
33
|
+
|---------|-----------------|-------------------|-------|
|
|
34
|
+
| Claude Code | `claude` | foundry, google, anthropic | Full bridge support |
|
|
35
|
+
| Codex | `codex` | foundry | Native OpenAI support |
|
|
36
|
+
| Pi | `pi` | foundry | Proxy via models.json |
|
|
37
|
+
| Gemini CLI | `gemini` | google, foundry | Needs `GEMINI_CLI_TRUST_WORKSPACE` (auto-set) |
|
|
38
|
+
| Copilot CLI | `copilot` | foundry | Via `gh extension` |
|
|
39
|
+
| Cursor | `cursor` | foundry | Manual install |
|
|
40
|
+
| OpenCode | `opencode` | foundry, anthropic | Multiple install methods |
|
|
41
|
+
| Hermes | `hermes` | foundry | NousResearch agent |
|
|
42
|
+
|
|
43
|
+
## Invocation Modes
|
|
44
|
+
|
|
45
|
+
Set `interaction-mode` to control how the harness runs in CI:
|
|
46
|
+
|
|
47
|
+
| Mode | Flag | Description | Use case |
|
|
48
|
+
|------|------|-------------|----------|
|
|
49
|
+
| `non-interactive` | `--no-interactive` | Plain NI — harness runs with `-p` / `exec` | Simple one-shot tasks |
|
|
50
|
+
| `bridged-hooks` | `--no-interactive --bridge-hooks` | NI + emulated babysitter lifecycle hooks | Babysitter-plugin orchestrated tasks |
|
|
51
|
+
| `bridged-interactive` | `--no-interactive --bridge-interactive` | NI externally, interactive via PTY internally | Tool-heavy tasks needing full harness capabilities |
|
|
52
|
+
|
|
53
|
+
### When to use each mode
|
|
54
|
+
|
|
55
|
+
- **`non-interactive`** (default) — fastest, simplest. The harness gets a prompt, does the work, exits. Good for single-task automation.
|
|
56
|
+
- **`bridged-hooks`** — use with `babysitter-plugin: true`. The BridgeHookEmulator wraps the harness execution with session-start/stop/end hooks, enabling the babysitter orchestration lifecycle.
|
|
57
|
+
- **`bridged-interactive`** — spawns the harness via PTY for full interactive capabilities (tool use, multi-turn) while presenting structured NDJSON output externally. Use when the harness needs TTY features but you want machine-readable output.
|
|
58
|
+
|
|
59
|
+
## Babysitter Plugin
|
|
60
|
+
|
|
61
|
+
Set `babysitter-plugin: true` to install the babysitter plugin before running:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
- uses: a5c-ai/babysitter/packages/triggers-mux@main
|
|
65
|
+
with:
|
|
66
|
+
harness: claude
|
|
67
|
+
provider: foundry
|
|
68
|
+
model: gpt-5.5
|
|
69
|
+
interaction-mode: bridged-hooks
|
|
70
|
+
babysitter-plugin: 'true'
|
|
71
|
+
babysitter-prompt-prefix: '/babysitter:yolo'
|
|
72
|
+
prompt: Implement the feature described in the issue
|
|
73
|
+
process-file: .a5c/processes/feature-impl.mjs
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The action will:
|
|
77
|
+
1. Install the harness CLI
|
|
78
|
+
2. Generate per-harness plugins (`npm run generate:plugins`)
|
|
79
|
+
3. Install the babysitter SDK globally
|
|
80
|
+
4. Install the babysitter plugin into the harness (`babysitter harness:install-plugin`)
|
|
81
|
+
5. Copy the process file to `.a5c/processes/` (if provided)
|
|
82
|
+
6. Launch with the appropriate bridge flags
|
|
83
|
+
|
|
84
|
+
### Babysitter prompt prefixes
|
|
85
|
+
|
|
86
|
+
Each harness uses a different prefix to invoke the babysitter skill:
|
|
87
|
+
|
|
88
|
+
| Harness | Prefix |
|
|
89
|
+
|---------|--------|
|
|
90
|
+
| Claude Code | `/babysitter:yolo` |
|
|
91
|
+
| Codex | `$babysitter:yolo` |
|
|
92
|
+
| Others | `Invoke the babysitter:yolo command to:` |
|
|
93
|
+
|
|
94
|
+
## Provider Configuration
|
|
95
|
+
|
|
96
|
+
The action uses `amux launch` which handles provider resolution and proxy setup automatically. Set credentials via environment variables:
|
|
97
|
+
|
|
98
|
+
### Azure Foundry (OpenAI)
|
|
99
|
+
```yaml
|
|
100
|
+
env:
|
|
101
|
+
AZURE_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
|
102
|
+
AMUX_API_BASE: https://your-resource.services.ai.azure.com
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Google / Vertex AI
|
|
106
|
+
```yaml
|
|
107
|
+
env:
|
|
108
|
+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
|
109
|
+
GOOGLE_CLOUD_PROJECT: ${{ secrets.GOOGLE_CLOUD_PROJECT }}
|
|
110
|
+
GOOGLE_GENAI_USE_VERTEXAI: 'true'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Anthropic (direct)
|
|
114
|
+
```yaml
|
|
115
|
+
env:
|
|
116
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Trigger Queries
|
|
120
|
+
|
|
121
|
+
Filter which events trigger the agent using `trigger-query`:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
trigger-query: |
|
|
125
|
+
event: pull_request
|
|
126
|
+
action: [opened, synchronize]
|
|
127
|
+
paths: src/**/*.ts
|
|
128
|
+
labels: needs-review
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Query fields
|
|
132
|
+
|
|
133
|
+
| Field | Description | Example |
|
|
134
|
+
|-------|-------------|---------|
|
|
135
|
+
| `event` | GitHub event name | `push`, `pull_request`, `issues` |
|
|
136
|
+
| `action` | Event action | `opened`, `synchronize`, `created` |
|
|
137
|
+
| `text` | Match text in title/body | `@develop-this`, `fix:` |
|
|
138
|
+
| `diff` | Match text in diff patches | `TODO`, `FIXME` |
|
|
139
|
+
| `paths` | Match changed file paths | `src/**/*.ts`, `packages/sdk/**` |
|
|
140
|
+
| `branch` | Match target branch | `main`, `release/*` |
|
|
141
|
+
| `labels` | Match issue/PR labels | `bug`, `needs-review` |
|
|
142
|
+
|
|
143
|
+
## Inputs Reference
|
|
144
|
+
|
|
145
|
+
| Input | Required | Default | Description |
|
|
146
|
+
|-------|----------|---------|-------------|
|
|
147
|
+
| `harness` | **yes** | — | Coding agent to use |
|
|
148
|
+
| `provider` | no | — | Model provider |
|
|
149
|
+
| `model` | no | — | Model name |
|
|
150
|
+
| `prompt` | no | — | Task prompt |
|
|
151
|
+
| `interaction-mode` | no | `non-interactive` | NI mode variant |
|
|
152
|
+
| `max-turns` | no | `15` | Max model turns |
|
|
153
|
+
| `with-proxy` | no | `true` | Start proxy if needed |
|
|
154
|
+
| `babysitter-plugin` | no | `false` | Install babysitter plugin |
|
|
155
|
+
| `process-file` | no | — | Babysitter process definition |
|
|
156
|
+
| `babysitter-prompt-prefix` | no | — | Skill invocation prefix |
|
|
157
|
+
| `trigger-backend` | no | `github` | Event backend |
|
|
158
|
+
| `trigger-query` | no | — | Event filter query |
|
|
159
|
+
| `include-diff` | no | `true` | Include diffs in enrichment |
|
|
160
|
+
| `github-token` | no | `${{ github.token }}` | GitHub API token |
|
|
161
|
+
| `pre-run` | no | — | Shell commands before agent |
|
|
162
|
+
| `post-run` | no | — | Shell commands after agent |
|
|
163
|
+
| `working-directory` | no | `${{ github.workspace }}` | Working directory |
|
|
164
|
+
| `node-version` | no | `22` | Node.js version |
|
|
165
|
+
|
|
166
|
+
## Example Workflows
|
|
167
|
+
|
|
168
|
+
See [`.github/workflows/`](./.github/workflows/) for complete examples:
|
|
169
|
+
|
|
170
|
+
- **[claude-code-pr-review.yml](./.github/workflows/claude-code-pr-review.yml)** — Claude Code + Foundry + babysitter-plugin + bridged-hooks for PR review
|
|
171
|
+
- **[codex-issue-triage.yml](./.github/workflows/codex-issue-triage.yml)** — Codex + Foundry + vanilla NI for issue classification
|
|
172
|
+
- **[gemini-scheduled-audit.yml](./.github/workflows/gemini-scheduled-audit.yml)** — Gemini CLI + Google/Vertex + scheduled docs audit
|
|
173
|
+
- **[multi-harness-quality-gates.yml](./.github/workflows/multi-harness-quality-gates.yml)** — Matrix of claude + codex + pi with babysitter-plugin
|
|
174
|
+
- **[copilot-webhook-dispatch.yml](./.github/workflows/copilot-webhook-dispatch.yml)** — Copilot CLI + bridged-interactive for repository_dispatch
|
|
175
|
+
- **[pi-comment-command.yml](./.github/workflows/pi-comment-command.yml)** — Pi + NI triggered by `/agent` comment commands
|
|
176
|
+
|
|
177
|
+
## Outputs
|
|
178
|
+
|
|
179
|
+
| Output | Description |
|
|
180
|
+
|--------|-------------|
|
|
181
|
+
| `matched` | Whether the trigger query matched (`true`/`false`) |
|
|
182
|
+
| `event` | Path to the enriched event JSON file |
|
|
183
|
+
| `exit-code` | Agent-mux exit code (empty if trigger didn't match) |
|
package/action.yml
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
name: Agent Mux
|
|
2
|
+
description: Run any coding agent from GitHub Actions — supports all harnesses (Claude Code, Codex, Pi, Gemini CLI, Copilot CLI, etc.) with trigger evaluation, provider proxy, babysitter plugin, and bridge modes.
|
|
3
|
+
author: a5c-ai
|
|
4
|
+
|
|
5
|
+
branding:
|
|
6
|
+
icon: terminal
|
|
7
|
+
color: purple
|
|
8
|
+
|
|
9
|
+
inputs:
|
|
10
|
+
# ── Core inputs ──────────────────────────────────────────────────────
|
|
11
|
+
command:
|
|
12
|
+
description: agent-mux command to execute after trigger evaluation.
|
|
13
|
+
required: false
|
|
14
|
+
default: launch
|
|
15
|
+
harness:
|
|
16
|
+
description: Coding agent harness to use (claude, codex, pi, gemini, copilot, cursor, opencode, hermes).
|
|
17
|
+
required: true
|
|
18
|
+
provider:
|
|
19
|
+
description: Model provider (foundry, google, anthropic, bedrock, openai).
|
|
20
|
+
required: false
|
|
21
|
+
model:
|
|
22
|
+
description: Model name to use (e.g. gpt-5.5, gemini-3.1-pro-preview, claude-sonnet-4).
|
|
23
|
+
required: false
|
|
24
|
+
prompt:
|
|
25
|
+
description: Prompt or task to send to the agent.
|
|
26
|
+
required: false
|
|
27
|
+
|
|
28
|
+
# ── Invocation mode ──────────────────────────────────────────────────
|
|
29
|
+
interaction-mode:
|
|
30
|
+
description: |
|
|
31
|
+
How to launch the harness in CI:
|
|
32
|
+
non-interactive — plain NI mode (-p / exec)
|
|
33
|
+
bridged-hooks — NI + emulated babysitter lifecycle hooks (--bridge-hooks)
|
|
34
|
+
bridged-interactive — NI externally, interactive internally via PTY (--bridge-interactive)
|
|
35
|
+
required: false
|
|
36
|
+
default: non-interactive
|
|
37
|
+
max-turns:
|
|
38
|
+
description: Maximum model turns before the agent exits.
|
|
39
|
+
required: false
|
|
40
|
+
default: '15'
|
|
41
|
+
|
|
42
|
+
# ── Provider / proxy ─────────────────────────────────────────────────
|
|
43
|
+
with-proxy:
|
|
44
|
+
description: Start transport-mux proxy if the harness doesn't support the provider natively.
|
|
45
|
+
required: false
|
|
46
|
+
default: 'true'
|
|
47
|
+
proxy-log-level:
|
|
48
|
+
description: Proxy log level (error, warn, info, debug).
|
|
49
|
+
required: false
|
|
50
|
+
default: error
|
|
51
|
+
|
|
52
|
+
# ── Babysitter plugin ────────────────────────────────────────────────
|
|
53
|
+
babysitter-plugin:
|
|
54
|
+
description: Install the babysitter plugin into the harness before running.
|
|
55
|
+
required: false
|
|
56
|
+
default: 'false'
|
|
57
|
+
process-file:
|
|
58
|
+
description: Path to a babysitter process definition (.mjs) to copy into .a5c/processes/.
|
|
59
|
+
required: false
|
|
60
|
+
babysitter-prompt-prefix:
|
|
61
|
+
description: |
|
|
62
|
+
Slash command prefix for babysitter invocation. Harness-specific:
|
|
63
|
+
claude → /babysitter:yolo
|
|
64
|
+
codex → $babysitter:yolo
|
|
65
|
+
other → Invoke the babysitter:yolo command to:
|
|
66
|
+
required: false
|
|
67
|
+
|
|
68
|
+
# ── Legacy / compatibility ───────────────────────────────────────────
|
|
69
|
+
args:
|
|
70
|
+
description: Space-delimited fallback arguments passed to amux after the command.
|
|
71
|
+
required: false
|
|
72
|
+
args-json:
|
|
73
|
+
description: JSON string array of additional arguments passed to amux after the command. Prefer this for values containing spaces or shell-sensitive characters.
|
|
74
|
+
required: false
|
|
75
|
+
adapter:
|
|
76
|
+
description: Alias for harness (backward compatibility).
|
|
77
|
+
required: false
|
|
78
|
+
plugins:
|
|
79
|
+
description: Newline-delimited plugin specs installed after harness setup. Each line is passed to amux plugin install <adapter> <plugin>.
|
|
80
|
+
required: false
|
|
81
|
+
|
|
82
|
+
# ── Trigger evaluation ───────────────────────────────────────────────
|
|
83
|
+
trigger-backend:
|
|
84
|
+
description: Trigger backend to normalize. Supports github, gitlab, bitbucket, generic-webhook.
|
|
85
|
+
required: false
|
|
86
|
+
default: github
|
|
87
|
+
trigger-query:
|
|
88
|
+
description: Query used to decide whether agent-mux should run.
|
|
89
|
+
required: false
|
|
90
|
+
include-diff:
|
|
91
|
+
description: Include local git diff patches in trigger enrichment.
|
|
92
|
+
required: false
|
|
93
|
+
default: 'true'
|
|
94
|
+
|
|
95
|
+
# ── Auth / tokens ────────────────────────────────────────────────────
|
|
96
|
+
use-a5c-token-exchange:
|
|
97
|
+
description: Use a5c-ai/generate-token-action@main before running trigger enrichment and agent-mux.
|
|
98
|
+
required: false
|
|
99
|
+
default: 'false'
|
|
100
|
+
github-token:
|
|
101
|
+
description: GitHub token fallback for API enrichment.
|
|
102
|
+
required: false
|
|
103
|
+
default: ${{ github.token }}
|
|
104
|
+
|
|
105
|
+
# ── Environment ──────────────────────────────────────────────────────
|
|
106
|
+
node-version:
|
|
107
|
+
description: Node.js version.
|
|
108
|
+
required: false
|
|
109
|
+
default: '22'
|
|
110
|
+
working-directory:
|
|
111
|
+
description: Working directory for amux execution.
|
|
112
|
+
required: false
|
|
113
|
+
default: ${{ github.workspace }}
|
|
114
|
+
pre-run:
|
|
115
|
+
description: Optional shell commands to run after trigger match and before amux.
|
|
116
|
+
required: false
|
|
117
|
+
post-run:
|
|
118
|
+
description: Optional shell commands to run after amux when trigger matched.
|
|
119
|
+
required: false
|
|
120
|
+
|
|
121
|
+
outputs:
|
|
122
|
+
matched:
|
|
123
|
+
description: Whether trigger-query matched the enriched event.
|
|
124
|
+
value: ${{ steps.trigger.outputs.matched }}
|
|
125
|
+
event:
|
|
126
|
+
description: Path to enriched event JSON.
|
|
127
|
+
value: ${{ steps.trigger.outputs.event }}
|
|
128
|
+
exit-code:
|
|
129
|
+
description: agent-mux exit code. Empty when trigger did not match.
|
|
130
|
+
value: ${{ steps.amux.outputs.exit-code }}
|
|
131
|
+
|
|
132
|
+
runs:
|
|
133
|
+
using: composite
|
|
134
|
+
steps:
|
|
135
|
+
- name: Setup Node.js
|
|
136
|
+
uses: actions/setup-node@v4
|
|
137
|
+
with:
|
|
138
|
+
node-version: ${{ inputs.node-version }}
|
|
139
|
+
|
|
140
|
+
- name: Generate a5c GitHub App token
|
|
141
|
+
id: a5c-token
|
|
142
|
+
if: ${{ inputs.use-a5c-token-exchange == 'true' }}
|
|
143
|
+
continue-on-error: true
|
|
144
|
+
uses: a5c-ai/generate-token-action@main
|
|
145
|
+
|
|
146
|
+
- name: Resolve action runtime
|
|
147
|
+
id: resolve-runtime
|
|
148
|
+
shell: bash
|
|
149
|
+
env:
|
|
150
|
+
ACTION_REF: ${{ github.action_ref }}
|
|
151
|
+
run: |
|
|
152
|
+
set -euo pipefail
|
|
153
|
+
WORKSPACE="${GITHUB_WORKSPACE:-$(pwd)}"
|
|
154
|
+
if [ -d "$WORKSPACE/packages/agent-mux/cli" ] && [ -f "$WORKSPACE/packages/triggers-mux/action.yml" ]; then
|
|
155
|
+
echo "mode=monorepo" >> "$GITHUB_OUTPUT"
|
|
156
|
+
echo "tag=staging" >> "$GITHUB_OUTPUT"
|
|
157
|
+
elif [ "$ACTION_REF" = "staging" ]; then
|
|
158
|
+
echo "mode=external" >> "$GITHUB_OUTPUT"
|
|
159
|
+
echo "tag=staging" >> "$GITHUB_OUTPUT"
|
|
160
|
+
else
|
|
161
|
+
echo "mode=external" >> "$GITHUB_OUTPUT"
|
|
162
|
+
echo "tag=latest" >> "$GITHUB_OUTPUT"
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
- name: Install runtime packages
|
|
166
|
+
shell: bash
|
|
167
|
+
env:
|
|
168
|
+
NPM_TAG: ${{ steps.resolve-runtime.outputs.tag }}
|
|
169
|
+
run: |
|
|
170
|
+
set -euo pipefail
|
|
171
|
+
echo "Installing @a5c-ai packages with tag: $NPM_TAG"
|
|
172
|
+
npm install -g --legacy-peer-deps @a5c-ai/agent-mux-cli@$NPM_TAG @a5c-ai/babysitter-sdk@$NPM_TAG @a5c-ai/triggers-mux@$NPM_TAG
|
|
173
|
+
npm install -g --legacy-peer-deps @a5c-ai/hooks-mux-cli@$NPM_TAG 2>/dev/null || echo "hooks-mux-cli install skipped (optional)"
|
|
174
|
+
which amux && amux --version || { echo "ERROR: amux not found after install"; exit 1; }
|
|
175
|
+
|
|
176
|
+
- name: Install harness
|
|
177
|
+
if: ${{ inputs.harness != '' || inputs.adapter != '' }}
|
|
178
|
+
shell: bash
|
|
179
|
+
env:
|
|
180
|
+
INPUT_HARNESS: ${{ inputs.harness || inputs.adapter }}
|
|
181
|
+
INPUT_WORKING_DIRECTORY: ${{ inputs.working-directory }}
|
|
182
|
+
run: |
|
|
183
|
+
set -euo pipefail
|
|
184
|
+
cd "$INPUT_WORKING_DIRECTORY"
|
|
185
|
+
# Map adapter names to amux agent aliases
|
|
186
|
+
AMUX_AGENT="$INPUT_HARNESS"
|
|
187
|
+
case "$INPUT_HARNESS" in
|
|
188
|
+
claude-code) AMUX_AGENT="claude" ;;
|
|
189
|
+
gemini-cli) AMUX_AGENT="gemini" ;;
|
|
190
|
+
copilot-cli) AMUX_AGENT="copilot" ;;
|
|
191
|
+
cursor-cli) AMUX_AGENT="cursor" ;;
|
|
192
|
+
esac
|
|
193
|
+
amux install "$AMUX_AGENT" || true
|
|
194
|
+
|
|
195
|
+
- name: Install babysitter plugin
|
|
196
|
+
if: ${{ inputs.babysitter-plugin == 'true' }}
|
|
197
|
+
shell: bash
|
|
198
|
+
env:
|
|
199
|
+
INPUT_HARNESS: ${{ inputs.harness || inputs.adapter }}
|
|
200
|
+
INPUT_WORKING_DIRECTORY: ${{ inputs.working-directory }}
|
|
201
|
+
INPUT_PROCESS_FILE: ${{ inputs.process-file }}
|
|
202
|
+
run: |
|
|
203
|
+
set -euo pipefail
|
|
204
|
+
cd "$INPUT_WORKING_DIRECTORY"
|
|
205
|
+
|
|
206
|
+
# Map to SDK harness names
|
|
207
|
+
SDK_HARNESS="$INPUT_HARNESS"
|
|
208
|
+
case "$INPUT_HARNESS" in
|
|
209
|
+
claude-code) SDK_HARNESS="claude" ;;
|
|
210
|
+
gemini-cli) SDK_HARNESS="gemini" ;;
|
|
211
|
+
copilot-cli) SDK_HARNESS="copilot" ;;
|
|
212
|
+
cursor-cli) SDK_HARNESS="cursor" ;;
|
|
213
|
+
esac
|
|
214
|
+
|
|
215
|
+
# Install babysitter plugin — try SDK installer first, fall back to direct harness commands
|
|
216
|
+
if ! babysitter harness:install-plugin "$SDK_HARNESS" --workspace "$INPUT_WORKING_DIRECTORY" 2>/dev/null; then
|
|
217
|
+
echo "Plugin installer unavailable — installing plugin directly"
|
|
218
|
+
case "$SDK_HARNESS" in
|
|
219
|
+
claude)
|
|
220
|
+
claude plugin marketplace add a5c-ai/babysitter-claude 2>/dev/null || true
|
|
221
|
+
claude plugin install --scope project babysitter@a5c.ai 2>/dev/null || true
|
|
222
|
+
;;
|
|
223
|
+
*)
|
|
224
|
+
mkdir -p .a5c
|
|
225
|
+
echo '{"type":"module"}' > .a5c/package.json 2>/dev/null || true
|
|
226
|
+
;;
|
|
227
|
+
esac
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
# Copy process file if provided (skip if already in target dir)
|
|
231
|
+
if [ -n "$INPUT_PROCESS_FILE" ]; then
|
|
232
|
+
mkdir -p .a5c/processes
|
|
233
|
+
TARGET=".a5c/processes/$(basename "$INPUT_PROCESS_FILE")"
|
|
234
|
+
[ "$(realpath "$INPUT_PROCESS_FILE" 2>/dev/null)" = "$(realpath "$TARGET" 2>/dev/null)" ] || cp "$INPUT_PROCESS_FILE" .a5c/processes/
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
- name: Install plugins (legacy)
|
|
238
|
+
if: ${{ inputs.plugins != '' }}
|
|
239
|
+
shell: bash
|
|
240
|
+
env:
|
|
241
|
+
ACTION_ROOT: ${{ github.action_path }}
|
|
242
|
+
INPUT_ADAPTER: ${{ inputs.adapter || inputs.harness }}
|
|
243
|
+
INPUT_PLUGINS: ${{ inputs.plugins }}
|
|
244
|
+
run: |
|
|
245
|
+
set -euo pipefail
|
|
246
|
+
while IFS= read -r plugin; do
|
|
247
|
+
[ -z "$plugin" ] && continue
|
|
248
|
+
amux plugin install "$INPUT_ADAPTER" "$plugin"
|
|
249
|
+
done <<< "$INPUT_PLUGINS"
|
|
250
|
+
|
|
251
|
+
- name: Evaluate trigger
|
|
252
|
+
id: trigger
|
|
253
|
+
shell: bash
|
|
254
|
+
env:
|
|
255
|
+
ACTION_ROOT: ${{ github.action_path }}
|
|
256
|
+
INPUT_TRIGGER_BACKEND: ${{ inputs.trigger-backend }}
|
|
257
|
+
INPUT_TRIGGER_QUERY: ${{ inputs.trigger-query }}
|
|
258
|
+
INPUT_INCLUDE_DIFF: ${{ inputs.include-diff }}
|
|
259
|
+
EFFECTIVE_GITHUB_TOKEN: ${{ steps.a5c-token.outputs.a5c_token || inputs.github-token }}
|
|
260
|
+
run: |
|
|
261
|
+
set -euo pipefail
|
|
262
|
+
EVENT_FILE="$RUNNER_TEMP/agent-mux-event.json"
|
|
263
|
+
RESULT_FILE="$RUNNER_TEMP/agent-mux-trigger.json"
|
|
264
|
+
INCLUDE_DIFF_ARGS=()
|
|
265
|
+
if [ "$INPUT_INCLUDE_DIFF" = "true" ]; then
|
|
266
|
+
INCLUDE_DIFF_ARGS+=(--include-diff)
|
|
267
|
+
fi
|
|
268
|
+
triggers-mux enrich \
|
|
269
|
+
--backend "$INPUT_TRIGGER_BACKEND" \
|
|
270
|
+
--token "$EFFECTIVE_GITHUB_TOKEN" \
|
|
271
|
+
"${INCLUDE_DIFF_ARGS[@]}" \
|
|
272
|
+
--output "$EVENT_FILE"
|
|
273
|
+
if [ -z "$INPUT_TRIGGER_QUERY" ]; then
|
|
274
|
+
echo '{"matched":true,"reasons":["no trigger query configured"]}' > "$RESULT_FILE"
|
|
275
|
+
elif triggers-mux evaluate \
|
|
276
|
+
--backend "$INPUT_TRIGGER_BACKEND" \
|
|
277
|
+
--query "$INPUT_TRIGGER_QUERY" \
|
|
278
|
+
--token "$EFFECTIVE_GITHUB_TOKEN" \
|
|
279
|
+
"${INCLUDE_DIFF_ARGS[@]}" \
|
|
280
|
+
--output "$RESULT_FILE"; then
|
|
281
|
+
true
|
|
282
|
+
else
|
|
283
|
+
status=$?
|
|
284
|
+
if [ "$status" -ne 78 ]; then
|
|
285
|
+
exit "$status"
|
|
286
|
+
fi
|
|
287
|
+
fi
|
|
288
|
+
MATCHED=$(node -e "console.log(JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8')).matched ? 'true' : 'false')" "$RESULT_FILE")
|
|
289
|
+
echo "matched=$MATCHED" >> "$GITHUB_OUTPUT"
|
|
290
|
+
echo "event=$EVENT_FILE" >> "$GITHUB_OUTPUT"
|
|
291
|
+
cat "$RESULT_FILE"
|
|
292
|
+
|
|
293
|
+
- name: Pre-run pipeline commands
|
|
294
|
+
if: ${{ steps.trigger.outputs.matched == 'true' && inputs.pre-run != '' }}
|
|
295
|
+
shell: bash
|
|
296
|
+
working-directory: ${{ inputs.working-directory }}
|
|
297
|
+
env:
|
|
298
|
+
INPUT_PRE_RUN: ${{ inputs.pre-run }}
|
|
299
|
+
AMUX_TRIGGER_EVENT_PATH: ${{ steps.trigger.outputs.event }}
|
|
300
|
+
run: |
|
|
301
|
+
set -euo pipefail
|
|
302
|
+
bash -euo pipefail -c "$INPUT_PRE_RUN"
|
|
303
|
+
|
|
304
|
+
- name: Run agent-mux
|
|
305
|
+
id: amux
|
|
306
|
+
if: ${{ steps.trigger.outputs.matched == 'true' }}
|
|
307
|
+
shell: bash
|
|
308
|
+
working-directory: ${{ inputs.working-directory }}
|
|
309
|
+
env:
|
|
310
|
+
ACTION_ROOT: ${{ github.action_path }}
|
|
311
|
+
INPUT_COMMAND: ${{ inputs.command }}
|
|
312
|
+
INPUT_HARNESS: ${{ inputs.harness || inputs.adapter }}
|
|
313
|
+
INPUT_PROVIDER: ${{ inputs.provider }}
|
|
314
|
+
INPUT_MODEL: ${{ inputs.model }}
|
|
315
|
+
INPUT_PROMPT: ${{ inputs.prompt }}
|
|
316
|
+
INPUT_INTERACTION_MODE: ${{ inputs.interaction-mode }}
|
|
317
|
+
INPUT_MAX_TURNS: ${{ inputs.max-turns }}
|
|
318
|
+
INPUT_WITH_PROXY: ${{ inputs.with-proxy }}
|
|
319
|
+
INPUT_PROXY_LOG_LEVEL: ${{ inputs.proxy-log-level }}
|
|
320
|
+
INPUT_BABYSITTER_PLUGIN: ${{ inputs.babysitter-plugin }}
|
|
321
|
+
INPUT_BABYSITTER_PREFIX: ${{ inputs.babysitter-prompt-prefix }}
|
|
322
|
+
INPUT_ARGS: ${{ inputs.args }}
|
|
323
|
+
INPUT_ARGS_JSON: ${{ inputs.args-json }}
|
|
324
|
+
AMUX_TRIGGER_EVENT_PATH: ${{ steps.trigger.outputs.event }}
|
|
325
|
+
run: |
|
|
326
|
+
set -euo pipefail
|
|
327
|
+
AMUX="amux"
|
|
328
|
+
|
|
329
|
+
# Map harness names to amux aliases
|
|
330
|
+
AMUX_HARNESS="$INPUT_HARNESS"
|
|
331
|
+
case "$INPUT_HARNESS" in
|
|
332
|
+
claude-code) AMUX_HARNESS="claude" ;;
|
|
333
|
+
gemini-cli) AMUX_HARNESS="gemini" ;;
|
|
334
|
+
copilot-cli) AMUX_HARNESS="copilot" ;;
|
|
335
|
+
cursor-cli) AMUX_HARNESS="cursor" ;;
|
|
336
|
+
esac
|
|
337
|
+
|
|
338
|
+
# Build command args
|
|
339
|
+
ARGS=()
|
|
340
|
+
if [ "$INPUT_COMMAND" = "launch" ] || [ "$INPUT_COMMAND" = "run" ]; then
|
|
341
|
+
ARGS+=("$INPUT_COMMAND")
|
|
342
|
+
[ -n "$AMUX_HARNESS" ] && ARGS+=("$AMUX_HARNESS")
|
|
343
|
+
[ -n "$INPUT_PROVIDER" ] && ARGS+=("$INPUT_PROVIDER")
|
|
344
|
+
else
|
|
345
|
+
ARGS+=("$INPUT_COMMAND")
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
# Model
|
|
349
|
+
[ -n "$INPUT_MODEL" ] && ARGS+=(--model "$INPUT_MODEL")
|
|
350
|
+
|
|
351
|
+
# Prompt — with optional babysitter prefix
|
|
352
|
+
if [ -n "$INPUT_PROMPT" ]; then
|
|
353
|
+
EFFECTIVE_PROMPT="$INPUT_PROMPT"
|
|
354
|
+
if [ "$INPUT_BABYSITTER_PLUGIN" = "true" ] && [ -n "$INPUT_BABYSITTER_PREFIX" ]; then
|
|
355
|
+
EFFECTIVE_PROMPT="$INPUT_BABYSITTER_PREFIX $INPUT_PROMPT"
|
|
356
|
+
fi
|
|
357
|
+
ARGS+=(--prompt "$EFFECTIVE_PROMPT")
|
|
358
|
+
fi
|
|
359
|
+
|
|
360
|
+
# Interaction mode flags
|
|
361
|
+
case "$INPUT_INTERACTION_MODE" in
|
|
362
|
+
non-interactive)
|
|
363
|
+
ARGS+=(--no-interactive)
|
|
364
|
+
;;
|
|
365
|
+
bridged-hooks)
|
|
366
|
+
ARGS+=(--no-interactive --bridge-hooks)
|
|
367
|
+
;;
|
|
368
|
+
bridged-interactive)
|
|
369
|
+
ARGS+=(--no-interactive --bridge-interactive)
|
|
370
|
+
;;
|
|
371
|
+
esac
|
|
372
|
+
|
|
373
|
+
# Max turns
|
|
374
|
+
[ -n "$INPUT_MAX_TURNS" ] && ARGS+=(--max-turns "$INPUT_MAX_TURNS")
|
|
375
|
+
|
|
376
|
+
# Proxy
|
|
377
|
+
if [ "$INPUT_WITH_PROXY" = "true" ]; then
|
|
378
|
+
ARGS+=(--with-proxy-if-needed)
|
|
379
|
+
[ -n "$INPUT_PROXY_LOG_LEVEL" ] && ARGS+=(--proxy-log-level "$INPUT_PROXY_LOG_LEVEL")
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
# Auto-approve permissions
|
|
383
|
+
ARGS+=(--yolo)
|
|
384
|
+
|
|
385
|
+
# Extra args
|
|
386
|
+
if [ -n "$INPUT_ARGS_JSON" ]; then
|
|
387
|
+
mapfile -t EXTRA_ARGS < <(node -e "const value = JSON.parse(process.env.INPUT_ARGS_JSON || '[]'); if (!Array.isArray(value)) throw new Error('args-json must be a JSON array'); for (const item of value) console.log(String(item));")
|
|
388
|
+
ARGS+=("${EXTRA_ARGS[@]}")
|
|
389
|
+
elif [ -n "$INPUT_ARGS" ]; then
|
|
390
|
+
read -r -a EXTRA_ARGS <<< "$INPUT_ARGS"
|
|
391
|
+
ARGS+=("${EXTRA_ARGS[@]}")
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
echo "::group::amux ${ARGS[*]}"
|
|
395
|
+
if $AMUX "${ARGS[@]}"; then
|
|
396
|
+
echo "exit-code=0" >> "$GITHUB_OUTPUT"
|
|
397
|
+
else
|
|
398
|
+
status=$?
|
|
399
|
+
echo "exit-code=$status" >> "$GITHUB_OUTPUT"
|
|
400
|
+
exit "$status"
|
|
401
|
+
fi
|
|
402
|
+
echo "::endgroup::"
|
|
403
|
+
|
|
404
|
+
- name: Post-run pipeline commands
|
|
405
|
+
if: ${{ steps.trigger.outputs.matched == 'true' && inputs.post-run != '' }}
|
|
406
|
+
shell: bash
|
|
407
|
+
working-directory: ${{ inputs.working-directory }}
|
|
408
|
+
env:
|
|
409
|
+
INPUT_POST_RUN: ${{ inputs.post-run }}
|
|
410
|
+
AMUX_TRIGGER_EVENT_PATH: ${{ steps.trigger.outputs.event }}
|
|
411
|
+
run: |
|
|
412
|
+
set -euo pipefail
|
|
413
|
+
bash -euo pipefail -c "$INPUT_POST_RUN"
|
package/dist/action.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TriggerEvaluation } from './types.js';
|
|
2
|
+
export interface ActionOptions {
|
|
3
|
+
backend?: string;
|
|
4
|
+
eventName?: string;
|
|
5
|
+
eventPath?: string;
|
|
6
|
+
query?: string;
|
|
7
|
+
includeDiff?: boolean;
|
|
8
|
+
githubToken?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function evaluateActionTrigger(options?: ActionOptions): Promise<TriggerEvaluation>;
|
|
11
|
+
export interface CommandResult {
|
|
12
|
+
code: number;
|
|
13
|
+
signal: NodeJS.Signals | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function runCommand(command: string, args: string[], env?: NodeJS.ProcessEnv): Promise<CommandResult>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CASnG;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,aAAa,CAAC,CAMxH"}
|
package/dist/action.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { evaluateTrigger } from './query.js';
|
|
3
|
+
import { enrichEvent } from './enrich.js';
|
|
4
|
+
export async function evaluateActionTrigger(options = {}) {
|
|
5
|
+
const event = await enrichEvent({
|
|
6
|
+
backend: options.backend,
|
|
7
|
+
eventName: options.eventName,
|
|
8
|
+
eventPath: options.eventPath,
|
|
9
|
+
token: options.githubToken,
|
|
10
|
+
includeDiff: options.includeDiff,
|
|
11
|
+
});
|
|
12
|
+
return evaluateTrigger(event, options.query);
|
|
13
|
+
}
|
|
14
|
+
export function runCommand(command, args, env = process.env) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const child = spawn(command, args, { stdio: 'inherit', env, shell: process.platform === 'win32' });
|
|
17
|
+
child.on('error', reject);
|
|
18
|
+
child.on('close', (code, signal) => resolve({ code: code ?? 1, signal }));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY1C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAAyB,EAAE;IACrE,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;QAC9B,OAAO,EAAE,OAAO,CAAC,OAAc;QAC/B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,KAAK,EAAE,OAAO,CAAC,WAAW;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;AAC/C,CAAC;AAOD,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,IAAc,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC9F,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;QACnG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitbucket.d.ts","sourceRoot":"","sources":["../../src/backends/bitbucket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAiB,MAAM,aAAa,CAAC;AAGzE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAkC1H"}
|