MCPcopy Create free account
hub / github.com/github/gh-aw / processSafeOutput

Function processSafeOutput

actions/setup/js/safe_output_processor.cjs:61–206  ·  view source on GitHub ↗

* Process the initial steps common to safe-output scripts: * 1. Load agent output * 2. Find matching item(s) * 3. Handle staged mode * 4. Parse configuration (from passed config or fallback to env vars) * 5. Resolve target (for single-item processors) * * @param {ProcessorConfig} config - Pro

(config, stagedPreviewOptions, handlerConfig = null)

Source from the content-addressed store, hash-verified

59 * @returns {Promise<ProcessorResult>} Processing result
60 */
61async function processSafeOutput(config, stagedPreviewOptions, handlerConfig = null) {
62 const { itemType, configKey, displayName, itemTypeName, supportsPR = false, supportsIssue = false, findMultiple = false, envVars } = config;
63
64 // Step 1: Load agent output
65 const result = loadAgentOutput();
66 if (!result.success) {
67 return { success: false, reason: "Agent output not available" };
68 }
69
70 // Step 2: Find matching item(s)
71 let items;
72 if (findMultiple) {
73 items = result.items.filter(item => item.type === itemType);
74 if (items.length === 0) {
75 core.info(`No ${itemType} items found in agent output`);
76 return { success: false, reason: `No ${itemType} items found` };
77 }
78 core.info(`Found ${items.length} ${itemType} item(s)`);
79 } else {
80 const item = result.items.find(item => item.type === itemType);
81 if (!item) {
82 core.warning(`No ${itemType.replace(/_/g, "-")} item found in agent output`);
83 return { success: false, reason: `No ${itemType} item found` };
84 }
85 items = [item];
86 // Log item details based on common fields
87 const itemDetails = getItemDetails(item);
88 if (itemDetails) {
89 core.info(`Found ${itemType.replace(/_/g, "-")} item with ${itemDetails}`);
90 }
91 }
92
93 // Step 3: Handle 🎭 Staged Mode Preview — output preview via generateStagedPreview, skip real writes
94 if (process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true") {
95 await generateStagedPreview({
96 title: stagedPreviewOptions.title,
97 description: stagedPreviewOptions.description,
98 items: items,
99 renderItem: stagedPreviewOptions.renderItem,
100 });
101 return { success: false, reason: "Staged mode - preview generated" };
102 }
103
104 // Step 4: Parse configuration
105 // If handlerConfig is provided (from handler manager), use it; otherwise fall back to file config + env vars
106 let allowed, maxCount, target;
107
108 if (handlerConfig) {
109 // Use config passed from handler manager
110 core.debug(`Using handler config: ${JSON.stringify(handlerConfig)}`);
111
112 // Parse allowed items from handlerConfig
113 allowed = handlerConfig.allowed || handlerConfig.allowed_labels || handlerConfig.allowed_repos;
114 if (Array.isArray(allowed)) {
115 core.info(`Allowed ${itemTypeName}s: ${JSON.stringify(allowed)}`);
116 } else if (typeof allowed === "string") {
117 allowed = parseAllowedItems(allowed);
118 core.info(`Allowed ${itemTypeName}s: ${JSON.stringify(allowed)}`);

Callers

nothing calls this directly

Calls 7

loadAgentOutputFunction · 0.85
getItemDetailsFunction · 0.85
generateStagedPreviewFunction · 0.85
parseAllowedItemsFunction · 0.85
getSafeOutputConfigFunction · 0.85
validateMaxCountFunction · 0.85
resolveTargetFunction · 0.70

Tested by

no test coverage detected