From 6cc57fa31408f21df640dfd000183af0aa4fbaba Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 29 Dec 2025 02:00:26 +0000
Subject: [PATCH 01/30] Initial plan
From 1e95458a3ca46913c0e14fe3bc7c556b0143e1b2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 29 Dec 2025 02:08:34 +0000
Subject: [PATCH 02/30] Add safe output handler manager and tests
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.../setup/js/safe_output_handler_manager.cjs | 250 ++++++++++++++++++
.../js/safe_output_handler_manager.test.cjs | 210 +++++++++++++++
pkg/workflow/compiler_safe_outputs_core.go | 74 ++++++
3 files changed, 534 insertions(+)
create mode 100644 actions/setup/js/safe_output_handler_manager.cjs
create mode 100644 actions/setup/js/safe_output_handler_manager.test.cjs
diff --git a/actions/setup/js/safe_output_handler_manager.cjs b/actions/setup/js/safe_output_handler_manager.cjs
new file mode 100644
index 0000000000..684524401d
--- /dev/null
+++ b/actions/setup/js/safe_output_handler_manager.cjs
@@ -0,0 +1,250 @@
+// @ts-check
+///
+
+/**
+ * Safe Output Handler Manager
+ *
+ * This module manages the dispatch of safe output messages to dedicated handlers.
+ * It reads configuration, loads the appropriate handlers for enabled safe output types,
+ * and processes messages from the agent output file while maintaining a shared temporary ID map.
+ */
+
+const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
+const fs = require("fs");
+const path = require("path");
+
+/**
+ * Handler map configuration
+ * Maps safe output types to their handler module file paths
+ */
+const HANDLER_MAP = {
+ create_issue: "./create_issue.cjs",
+ add_comment: "./add_comment.cjs",
+ create_discussion: "./create_discussion.cjs",
+ close_issue: "./close_issue.cjs",
+ close_discussion: "./close_discussion.cjs",
+};
+
+/**
+ * Load configuration for safe outputs
+ * @returns {Object} Safe outputs configuration
+ */
+function loadConfig() {
+ const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json";
+
+ try {
+ if (fs.existsSync(configPath)) {
+ const configContent = fs.readFileSync(configPath, "utf8");
+ const config = JSON.parse(configContent);
+
+ // Normalize config keys: convert hyphens to underscores
+ return Object.fromEntries(
+ Object.entries(config).map(([k, v]) => [k.replace(/-/g, "_"), v])
+ );
+ }
+ } catch (error) {
+ core.debug(`Failed to load config: ${getErrorMessage(error)}`);
+ }
+
+ return {};
+}
+
+/**
+ * Load handlers for enabled safe output types
+ * @param {Object} config - Safe outputs configuration
+ * @returns {Map} Map of type to handler module
+ */
+function loadHandlers(config) {
+ const handlers = new Map();
+
+ core.info("Loading safe output handlers based on configuration...");
+
+ for (const [type, handlerPath] of Object.entries(HANDLER_MAP)) {
+ // Check if this safe output type is enabled in the config
+ // Config keys use underscores (e.g., create_issue)
+ const configKey = type;
+
+ // Check if handler is enabled (config entry exists and is not false)
+ if (config[configKey] && config[configKey].enabled !== false) {
+ try {
+ const handler = require(handlerPath);
+ if (handler && typeof handler.main === "function") {
+ handlers.set(type, handler);
+ core.info(`✓ Loaded handler for: ${type}`);
+ } else {
+ core.warning(`Handler module ${type} does not export a main function`);
+ }
+ } catch (error) {
+ core.warning(`Failed to load handler for ${type}: ${getErrorMessage(error)}`);
+ }
+ } else {
+ core.debug(`Handler not enabled: ${type}`);
+ }
+ }
+
+ core.info(`Loaded ${handlers.size} handler(s)`);
+ return handlers;
+}
+
+/**
+ * Group messages by type for batch processing
+ * @param {Array