From b3565d0645f758a05c74500cd56a327785d89275 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 06:37:02 +0000
Subject: [PATCH 01/17] Initial plan
From ce8b3ef848b71436bfc53e2e2766426d84b1f31f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 07:07:54 +0000
Subject: [PATCH 02/17] feat: add safe-output actions support for mounting
custom GitHub Actions as MCP tools
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.../setup/js/safe_output_action_handler.cjs | 102 ++++
.../setup/js/safe_output_handler_manager.cjs | 31 +-
actions/setup/js/safe_output_helpers.cjs | 32 ++
pkg/workflow/compiler_safe_outputs_job.go | 21 +-
pkg/workflow/compiler_safe_outputs_steps.go | 7 +
pkg/workflow/compiler_types.go | 1 +
pkg/workflow/safe_outputs_actions.go | 447 ++++++++++++++++++
pkg/workflow/safe_outputs_actions_test.go | 417 ++++++++++++++++
pkg/workflow/safe_outputs_config.go | 8 +
pkg/workflow/safe_outputs_state.go | 11 +
pkg/workflow/safe_outputs_tools_filtering.go | 39 +-
11 files changed, 1113 insertions(+), 3 deletions(-)
create mode 100644 actions/setup/js/safe_output_action_handler.cjs
create mode 100644 pkg/workflow/safe_outputs_actions.go
create mode 100644 pkg/workflow/safe_outputs_actions_test.go
diff --git a/actions/setup/js/safe_output_action_handler.cjs b/actions/setup/js/safe_output_action_handler.cjs
new file mode 100644
index 0000000000..836d04c0b2
--- /dev/null
+++ b/actions/setup/js/safe_output_action_handler.cjs
@@ -0,0 +1,102 @@
+// @ts-check
+///
+
+/**
+ * @typedef {import('./types/handler-factory').HandlerFactoryFunction} HandlerFactoryFunction
+ */
+
+const { replaceTemporaryIdReferences } = require("./temporary_id.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
+
+/**
+ * Main handler factory for a custom safe output action.
+ *
+ * Each configured safe-output action gets its own instance of this factory function,
+ * invoked with a config that includes `action_name` (the normalized tool name).
+ *
+ * The handler:
+ * 1. Enforces that the action is called at most once (per the spec).
+ * 2. Applies temporary ID substitutions to all string-valued fields in the payload.
+ * 3. Exports the processed payload as a step output named `action__payload`.
+ *
+ * The compiler generates a corresponding GitHub Actions step with:
+ * if: steps.process_safe_outputs.outputs.action__payload != ''
+ * uses:
+ * with:
+ * : ${{ fromJSON(steps.process_safe_outputs.outputs.action__payload). }}
+ *
+ * @type {HandlerFactoryFunction}
+ */
+async function main(config = {}) {
+ const actionName = config.action_name || "unknown_action";
+ const outputKey = `action_${actionName}_payload`;
+
+ core.info(`Custom action handler initialized: action_name=${actionName}, output_key=${outputKey}`);
+
+ // Track whether this action has been called (enforces once-only constraint)
+ let called = false;
+
+ /**
+ * Handler function that processes a single tool call for this action.
+ * Applies temporary ID substitutions and exports the payload as a step output.
+ *
+ * @param {Object} message - The tool call message from the agent output
+ * @param {Object} resolvedTemporaryIds - Map of temp IDs to resolved values (plain object)
+ * @param {Map} temporaryIdMap - Live map of temporary IDs (for substitution)
+ * @returns {Promise