@a5c-ai/triggers-adapter 5.1.1-staging.0ad6ac75ae4a

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.
Files changed (55) hide show
  1. package/README.md +183 -0
  2. package/action.yml +418 -0
  3. package/dist/action.d.ts +15 -0
  4. package/dist/action.d.ts.map +1 -0
  5. package/dist/action.js +21 -0
  6. package/dist/action.js.map +1 -0
  7. package/dist/backends/bitbucket.d.ts +2 -0
  8. package/dist/backends/bitbucket.d.ts.map +1 -0
  9. package/dist/backends/bitbucket.js +36 -0
  10. package/dist/backends/bitbucket.js.map +1 -0
  11. package/dist/backends/generic-webhook.d.ts +2 -0
  12. package/dist/backends/generic-webhook.d.ts.map +1 -0
  13. package/dist/backends/generic-webhook.js +28 -0
  14. package/dist/backends/generic-webhook.js.map +1 -0
  15. package/dist/backends/github.d.ts +2 -0
  16. package/dist/backends/github.d.ts.map +1 -0
  17. package/dist/backends/github.js +36 -0
  18. package/dist/backends/github.js.map +1 -0
  19. package/dist/backends/gitlab.d.ts +2 -0
  20. package/dist/backends/gitlab.d.ts.map +1 -0
  21. package/dist/backends/gitlab.js +33 -0
  22. package/dist/backends/gitlab.js.map +1 -0
  23. package/dist/backends/index.d.ts +6 -0
  24. package/dist/backends/index.d.ts.map +1 -0
  25. package/dist/backends/index.js +20 -0
  26. package/dist/backends/index.js.map +1 -0
  27. package/dist/backends/utils.d.ts +7 -0
  28. package/dist/backends/utils.d.ts.map +1 -0
  29. package/dist/backends/utils.js +22 -0
  30. package/dist/backends/utils.js.map +1 -0
  31. package/dist/cli.d.ts +2 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +77 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/enrich.d.ts +2 -0
  36. package/dist/enrich.d.ts.map +1 -0
  37. package/dist/enrich.js +115 -0
  38. package/dist/enrich.js.map +1 -0
  39. package/dist/index.d.ts +6 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +5 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/query.d.ts +5 -0
  44. package/dist/query.d.ts.map +1 -0
  45. package/dist/query.js +145 -0
  46. package/dist/query.js.map +1 -0
  47. package/dist/triggers-adapter.d.ts +2 -0
  48. package/dist/triggers-adapter.d.ts.map +1 -0
  49. package/dist/triggers-adapter.js +10 -0
  50. package/dist/triggers-adapter.js.map +1 -0
  51. package/dist/types.d.ts +54 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/package.json +76 -0
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # @a5c-ai/triggers-adapter
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 adapters.
4
+
5
+ ## CLI
6
+
7
+ ```bash
8
+ triggers evaluate --backend github --query "event:issue_comment text:@develop-this path:packages/adapters/**"
9
+ triggers enrich --backend github --include-diff --output event.json
10
+ ```
11
+
12
+ ## GitHub Action
13
+
14
+ The reusable action at `packages/adapters/triggers/action.yml` supports all harnesses, providers, and invocation modes.
15
+
16
+ ### Quick Start
17
+
18
+ ```yaml
19
+ - uses: a5c-ai/babysitter/packages/adapters/triggers@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
+ AGENT_MUX_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/adapters/triggers@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 `adapters 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
+ AGENT_MUX_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` | Adapters exit code (empty if trigger didn't match) |
package/action.yml ADDED
@@ -0,0 +1,418 @@
1
+ name: Agent Adapter
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: adapters 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-adapter 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 adapters after the command.
71
+ required: false
72
+ args-json:
73
+ description: JSON string array of additional arguments passed to adapters 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 adapters 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 adapters 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 adapters.
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 adapters execution.
112
+ required: false
113
+ default: ${{ github.workspace }}
114
+ pre-run:
115
+ description: Optional shell commands to run after trigger match and before adapters.
116
+ required: false
117
+ post-run:
118
+ description: Optional shell commands to run after adapters 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: adapters exit code. Empty when trigger did not match.
130
+ value: ${{ steps.adapters.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/adapters/cli" ] && [ -f "$WORKSPACE/packages/adapters/triggers/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/adapters@$NPM_TAG @a5c-ai/babysitter-sdk@$NPM_TAG @a5c-ai/triggers-adapter@$NPM_TAG
173
+ npm install -g --legacy-peer-deps @a5c-ai/hooks-adapter-cli@$NPM_TAG 2>/dev/null || echo "adapters-hooks-cli install skipped (optional)"
174
+ which adapters && adapters --version || { echo "ERROR: adapters 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 adapters agent aliases
186
+ AGENT_MUX_AGENT="$INPUT_HARNESS"
187
+ case "$INPUT_HARNESS" in
188
+ claude-code) AGENT_MUX_AGENT="claude" ;;
189
+ gemini-cli) AGENT_MUX_AGENT="gemini" ;;
190
+ copilot-cli) AGENT_MUX_AGENT="copilot" ;;
191
+ cursor-cli) AGENT_MUX_AGENT="cursor" ;;
192
+ esac
193
+ # Remove stale global bin symlinks that cause EEXIST on npm install -g
194
+ NODE_BIN="$(dirname "$(which node)")"
195
+ for bin in codex claude gemini pi copilot cursor hermes opencode antigravity; do
196
+ [ -L "$NODE_BIN/$bin" ] && rm -f "$NODE_BIN/$bin" 2>/dev/null || true
197
+ done
198
+ adapters install "$AGENT_MUX_AGENT" || true
199
+
200
+ - name: Install babysitter plugin
201
+ if: ${{ inputs.babysitter-plugin == 'true' }}
202
+ shell: bash
203
+ env:
204
+ INPUT_HARNESS: ${{ inputs.harness || inputs.adapter }}
205
+ INPUT_WORKING_DIRECTORY: ${{ inputs.working-directory }}
206
+ INPUT_PROCESS_FILE: ${{ inputs.process-file }}
207
+ run: |
208
+ set -euo pipefail
209
+ cd "$INPUT_WORKING_DIRECTORY"
210
+
211
+ # Map to SDK harness names
212
+ SDK_HARNESS="$INPUT_HARNESS"
213
+ case "$INPUT_HARNESS" in
214
+ claude-code) SDK_HARNESS="claude" ;;
215
+ gemini-cli) SDK_HARNESS="gemini" ;;
216
+ copilot-cli) SDK_HARNESS="copilot" ;;
217
+ cursor-cli) SDK_HARNESS="cursor" ;;
218
+ esac
219
+
220
+ # Install babysitter plugin — try SDK installer first, fall back to direct harness commands
221
+ if ! babysitter harness:install-plugin "$SDK_HARNESS" --workspace "$INPUT_WORKING_DIRECTORY" 2>/dev/null; then
222
+ echo "Plugin installer unavailable — installing plugin directly"
223
+ case "$SDK_HARNESS" in
224
+ claude)
225
+ claude plugin marketplace add a5c-ai/babysitter-claude 2>/dev/null || true
226
+ claude plugin install --scope project babysitter@a5c.ai 2>/dev/null || true
227
+ ;;
228
+ *)
229
+ mkdir -p .a5c
230
+ echo '{"type":"module"}' > .a5c/package.json 2>/dev/null || true
231
+ ;;
232
+ esac
233
+ fi
234
+
235
+ # Copy process file if provided (skip if already in target dir)
236
+ if [ -n "$INPUT_PROCESS_FILE" ]; then
237
+ mkdir -p .a5c/processes
238
+ TARGET=".a5c/processes/$(basename "$INPUT_PROCESS_FILE")"
239
+ [ "$(realpath "$INPUT_PROCESS_FILE" 2>/dev/null)" = "$(realpath "$TARGET" 2>/dev/null)" ] || cp "$INPUT_PROCESS_FILE" .a5c/processes/
240
+ fi
241
+
242
+ - name: Install plugins (legacy)
243
+ if: ${{ inputs.plugins != '' }}
244
+ shell: bash
245
+ env:
246
+ ACTION_ROOT: ${{ github.action_path }}
247
+ INPUT_ADAPTER: ${{ inputs.adapter || inputs.harness }}
248
+ INPUT_PLUGINS: ${{ inputs.plugins }}
249
+ run: |
250
+ set -euo pipefail
251
+ while IFS= read -r plugin; do
252
+ [ -z "$plugin" ] && continue
253
+ adapters plugin install "$INPUT_ADAPTER" "$plugin"
254
+ done <<< "$INPUT_PLUGINS"
255
+
256
+ - name: Evaluate trigger
257
+ id: trigger
258
+ shell: bash
259
+ env:
260
+ ACTION_ROOT: ${{ github.action_path }}
261
+ INPUT_TRIGGER_BACKEND: ${{ inputs.trigger-backend }}
262
+ INPUT_TRIGGER_QUERY: ${{ inputs.trigger-query }}
263
+ INPUT_INCLUDE_DIFF: ${{ inputs.include-diff }}
264
+ EFFECTIVE_GITHUB_TOKEN: ${{ steps.a5c-token.outputs.a5c_token || inputs.github-token }}
265
+ run: |
266
+ set -euo pipefail
267
+ EVENT_FILE="$RUNNER_TEMP/adapters-event.json"
268
+ RESULT_FILE="$RUNNER_TEMP/adapters-trigger.json"
269
+ INCLUDE_DIFF_ARGS=()
270
+ if [ "$INPUT_INCLUDE_DIFF" = "true" ]; then
271
+ INCLUDE_DIFF_ARGS+=(--include-diff)
272
+ fi
273
+ adapters-triggers enrich \
274
+ --backend "$INPUT_TRIGGER_BACKEND" \
275
+ --token "$EFFECTIVE_GITHUB_TOKEN" \
276
+ "${INCLUDE_DIFF_ARGS[@]}" \
277
+ --output "$EVENT_FILE"
278
+ if [ -z "$INPUT_TRIGGER_QUERY" ]; then
279
+ echo '{"matched":true,"reasons":["no trigger query configured"]}' > "$RESULT_FILE"
280
+ elif adapters-triggers evaluate \
281
+ --backend "$INPUT_TRIGGER_BACKEND" \
282
+ --query "$INPUT_TRIGGER_QUERY" \
283
+ --token "$EFFECTIVE_GITHUB_TOKEN" \
284
+ "${INCLUDE_DIFF_ARGS[@]}" \
285
+ --output "$RESULT_FILE"; then
286
+ true
287
+ else
288
+ status=$?
289
+ if [ "$status" -ne 78 ]; then
290
+ exit "$status"
291
+ fi
292
+ fi
293
+ MATCHED=$(node -e "console.log(JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8')).matched ? 'true' : 'false')" "$RESULT_FILE")
294
+ echo "matched=$MATCHED" >> "$GITHUB_OUTPUT"
295
+ echo "event=$EVENT_FILE" >> "$GITHUB_OUTPUT"
296
+ cat "$RESULT_FILE"
297
+
298
+ - name: Pre-run pipeline commands
299
+ if: ${{ steps.trigger.outputs.matched == 'true' && inputs.pre-run != '' }}
300
+ shell: bash
301
+ working-directory: ${{ inputs.working-directory }}
302
+ env:
303
+ INPUT_PRE_RUN: ${{ inputs.pre-run }}
304
+ AGENT_MUX_TRIGGER_EVENT_PATH: ${{ steps.trigger.outputs.event }}
305
+ run: |
306
+ set -euo pipefail
307
+ bash -euo pipefail -c "$INPUT_PRE_RUN"
308
+
309
+ - name: Run adapters
310
+ id: adapters
311
+ if: ${{ steps.trigger.outputs.matched == 'true' }}
312
+ shell: bash
313
+ working-directory: ${{ inputs.working-directory }}
314
+ env:
315
+ ACTION_ROOT: ${{ github.action_path }}
316
+ INPUT_COMMAND: ${{ inputs.command }}
317
+ INPUT_HARNESS: ${{ inputs.harness || inputs.adapter }}
318
+ INPUT_PROVIDER: ${{ inputs.provider }}
319
+ INPUT_MODEL: ${{ inputs.model }}
320
+ INPUT_PROMPT: ${{ inputs.prompt }}
321
+ INPUT_INTERACTION_MODE: ${{ inputs.interaction-mode }}
322
+ INPUT_MAX_TURNS: ${{ inputs.max-turns }}
323
+ INPUT_WITH_PROXY: ${{ inputs.with-proxy }}
324
+ INPUT_PROXY_LOG_LEVEL: ${{ inputs.proxy-log-level }}
325
+ INPUT_BABYSITTER_PLUGIN: ${{ inputs.babysitter-plugin }}
326
+ INPUT_BABYSITTER_PREFIX: ${{ inputs.babysitter-prompt-prefix }}
327
+ INPUT_ARGS: ${{ inputs.args }}
328
+ INPUT_ARGS_JSON: ${{ inputs.args-json }}
329
+ AGENT_MUX_TRIGGER_EVENT_PATH: ${{ steps.trigger.outputs.event }}
330
+ run: |
331
+ set -euo pipefail
332
+ ADAPTERS="adapters"
333
+
334
+ # Map harness names to adapters aliases
335
+ AGENT_MUX_HARNESS="$INPUT_HARNESS"
336
+ case "$INPUT_HARNESS" in
337
+ claude-code) AGENT_MUX_HARNESS="claude" ;;
338
+ gemini-cli) AGENT_MUX_HARNESS="gemini" ;;
339
+ copilot-cli) AGENT_MUX_HARNESS="copilot" ;;
340
+ cursor-cli) AGENT_MUX_HARNESS="cursor" ;;
341
+ esac
342
+
343
+ # Build command args
344
+ ARGS=()
345
+ if [ "$INPUT_COMMAND" = "launch" ] || [ "$INPUT_COMMAND" = "run" ]; then
346
+ ARGS+=("$INPUT_COMMAND")
347
+ [ -n "$AGENT_MUX_HARNESS" ] && ARGS+=("$AGENT_MUX_HARNESS")
348
+ [ -n "$INPUT_PROVIDER" ] && ARGS+=("$INPUT_PROVIDER")
349
+ else
350
+ ARGS+=("$INPUT_COMMAND")
351
+ fi
352
+
353
+ # Model
354
+ [ -n "$INPUT_MODEL" ] && ARGS+=(--model "$INPUT_MODEL")
355
+
356
+ # Prompt — with optional babysitter prefix
357
+ if [ -n "$INPUT_PROMPT" ]; then
358
+ EFFECTIVE_PROMPT="$INPUT_PROMPT"
359
+ if [ "$INPUT_BABYSITTER_PLUGIN" = "true" ] && [ -n "$INPUT_BABYSITTER_PREFIX" ]; then
360
+ EFFECTIVE_PROMPT="$INPUT_BABYSITTER_PREFIX $INPUT_PROMPT"
361
+ fi
362
+ ARGS+=(--prompt "$EFFECTIVE_PROMPT")
363
+ fi
364
+
365
+ # Interaction mode flags
366
+ case "$INPUT_INTERACTION_MODE" in
367
+ non-interactive)
368
+ ARGS+=(--no-interactive)
369
+ ;;
370
+ bridged-hooks)
371
+ ARGS+=(--no-interactive --bridge-hooks)
372
+ ;;
373
+ bridged-interactive)
374
+ ARGS+=(--no-interactive --bridge-interactive)
375
+ ;;
376
+ esac
377
+
378
+ # Max turns
379
+ [ -n "$INPUT_MAX_TURNS" ] && ARGS+=(--max-turns "$INPUT_MAX_TURNS")
380
+
381
+ # Proxy
382
+ if [ "$INPUT_WITH_PROXY" = "true" ]; then
383
+ ARGS+=(--with-proxy-if-needed)
384
+ [ -n "$INPUT_PROXY_LOG_LEVEL" ] && ARGS+=(--proxy-log-level "$INPUT_PROXY_LOG_LEVEL")
385
+ fi
386
+
387
+ # Auto-approve permissions
388
+ ARGS+=(--yolo)
389
+
390
+ # Extra args
391
+ if [ -n "$INPUT_ARGS_JSON" ]; then
392
+ 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));")
393
+ ARGS+=("${EXTRA_ARGS[@]}")
394
+ elif [ -n "$INPUT_ARGS" ]; then
395
+ read -r -a EXTRA_ARGS <<< "$INPUT_ARGS"
396
+ ARGS+=("${EXTRA_ARGS[@]}")
397
+ fi
398
+
399
+ echo "::group::adapters ${ARGS[*]}"
400
+ if $ADAPTERS "${ARGS[@]}"; then
401
+ echo "exit-code=0" >> "$GITHUB_OUTPUT"
402
+ else
403
+ status=$?
404
+ echo "exit-code=$status" >> "$GITHUB_OUTPUT"
405
+ exit "$status"
406
+ fi
407
+ echo "::endgroup::"
408
+
409
+ - name: Post-run pipeline commands
410
+ if: ${{ steps.trigger.outputs.matched == 'true' && inputs.post-run != '' }}
411
+ shell: bash
412
+ working-directory: ${{ inputs.working-directory }}
413
+ env:
414
+ INPUT_POST_RUN: ${{ inputs.post-run }}
415
+ AGENT_MUX_TRIGGER_EVENT_PATH: ${{ steps.trigger.outputs.event }}
416
+ run: |
417
+ set -euo pipefail
418
+ bash -euo pipefail -c "$INPUT_POST_RUN"
@@ -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,2 @@
1
+ import type { NormalizedTriggerEvent } from '../types.js';
2
+ export declare function normalizeBitbucket(eventName: string, event: Record<string, unknown>, raw: unknown): NormalizedTriggerEvent;
@@ -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"}