Add set_output tool (#205)
This commit is contained in:
committed by
pullfrog[bot]
parent
2daab6fc78
commit
c1f8247077
@@ -35,6 +35,10 @@ inputs:
|
||||
required: false
|
||||
default: ${{ github.token }}
|
||||
|
||||
outputs:
|
||||
result:
|
||||
description: "It's set when the prompt explicitly requests it. It can be used to capture an actionable output for the next step in the workflow."
|
||||
|
||||
runs:
|
||||
using: "node24"
|
||||
main: "entry"
|
||||
|
||||
@@ -19763,7 +19763,7 @@ var require_core = __commonJS({
|
||||
Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
||||
}
|
||||
exports.getBooleanInput = getBooleanInput;
|
||||
function setOutput(name, value2) {
|
||||
function setOutput2(name, value2) {
|
||||
const filePath = process.env["GITHUB_OUTPUT"] || "";
|
||||
if (filePath) {
|
||||
return (0, file_command_1.issueFileCommand)("OUTPUT", (0, file_command_1.prepareKeyValueMessage)(name, value2));
|
||||
@@ -19771,7 +19771,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
||||
process.stdout.write(os2.EOL);
|
||||
(0, command_1.issueCommand)("set-output", { name }, (0, utils_1.toCommandValue)(value2));
|
||||
}
|
||||
exports.setOutput = setOutput;
|
||||
exports.setOutput = setOutput2;
|
||||
function setCommandEcho(enabled) {
|
||||
(0, command_1.issue)("echo", enabled ? "on" : "off");
|
||||
}
|
||||
@@ -142448,6 +142448,22 @@ function AddLabelsTool(ctx) {
|
||||
});
|
||||
}
|
||||
|
||||
// mcp/output.ts
|
||||
var SetOutputParams = type({
|
||||
value: type.string.describe("the output value to expose as a GitHub Action output")
|
||||
});
|
||||
function SetOutputTool(ctx) {
|
||||
return tool({
|
||||
name: "set_output",
|
||||
description: "Set the action output for consumption by subsequent workflow steps. The value will be available as the 'result' output of the action.",
|
||||
parameters: SetOutputParams,
|
||||
execute: execute(async (params) => {
|
||||
ctx.toolState.output = params.value;
|
||||
return { success: true };
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// mcp/pr.ts
|
||||
var PullRequest = type({
|
||||
title: type.string.describe("the title of the pull request"),
|
||||
@@ -143218,7 +143234,8 @@ async function startMcpHttpServer(ctx) {
|
||||
CreateBranchTool(ctx),
|
||||
CommitFilesTool(ctx),
|
||||
PushBranchTool(ctx),
|
||||
UploadFileTool(ctx)
|
||||
UploadFileTool(ctx),
|
||||
SetOutputTool(ctx)
|
||||
];
|
||||
if (ctx.payload.bash === "restricted") {
|
||||
tools.push(BashTool(ctx));
|
||||
@@ -162114,6 +162131,12 @@ function getShellInstructions(bash) {
|
||||
}
|
||||
}
|
||||
}
|
||||
function getStandaloneModeInstructions(trigger) {
|
||||
if (trigger !== "unknown") {
|
||||
return "";
|
||||
}
|
||||
return `**Standalone mode**: You are running as a step in a user-defined CI workflow. When you complete your task, call \`${ghPullfrogMcpName}/set_output\` with the main result of your work (generated content, summary of changes, analysis results, etc.). This makes it available as a GitHub Action output named \`result\` for subsequent workflow steps to consume.`;
|
||||
}
|
||||
function resolveInstructions(ctx) {
|
||||
const eventTitleBody = buildEventTitleBody(ctx.payload.event);
|
||||
const eventMetadata = buildEventMetadata(ctx.payload.event);
|
||||
@@ -162172,6 +162195,8 @@ Tool names may be formatted as \`(server name)/(tool name)\`, for example: \`${g
|
||||
|
||||
${getShellInstructions(ctx.payload.bash)}
|
||||
|
||||
${getStandaloneModeInstructions(ctx.payload.event.trigger)}
|
||||
|
||||
**Command execution**: Never use \`sleep\` to wait for commands to complete. Commands run synchronously - when the bash tool returns, the command has finished.
|
||||
|
||||
**Commenting style**: When posting comments via ${ghPullfrogMcpName}, write as a professional team member would. Your final comments should be polished and actionable\u2014do not include intermediate reasoning like "I'll now look at the code" or "Let me respond to the question."
|
||||
@@ -162411,7 +162436,7 @@ function resolvePayload(repoSettings) {
|
||||
}
|
||||
|
||||
// utils/run.ts
|
||||
async function handleAgentResult(result) {
|
||||
function handleAgentResult(result) {
|
||||
if (!result.success) {
|
||||
return {
|
||||
success: false,
|
||||
@@ -162762,7 +162787,10 @@ async function main() {
|
||||
if (toolState.lastProgressBody) {
|
||||
await writeSummary(toolState.lastProgressBody);
|
||||
}
|
||||
return handleAgentResult(result);
|
||||
return {
|
||||
...handleAgentResult(result),
|
||||
result: toolState.output
|
||||
};
|
||||
} catch (_) {
|
||||
var _error = _, _hasError = true;
|
||||
} finally {
|
||||
@@ -162796,6 +162824,9 @@ async function run() {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error || "Agent execution failed");
|
||||
}
|
||||
if (result.result) {
|
||||
core5.setOutput("result", result.result);
|
||||
}
|
||||
} catch (error50) {
|
||||
const errorMessage = error50 instanceof Error ? error50.message : "Unknown error occurred";
|
||||
core5.setFailed(`Action failed: ${errorMessage}`);
|
||||
|
||||
@@ -15,6 +15,10 @@ async function run(): Promise<void> {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error || "Agent execution failed");
|
||||
}
|
||||
|
||||
if (result.result) {
|
||||
core.setOutput("result", result.result);
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
||||
core.setFailed(`Action failed: ${errorMessage}`);
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface MainResult {
|
||||
success: boolean;
|
||||
output?: string | undefined;
|
||||
error?: string | undefined;
|
||||
result?: string | undefined;
|
||||
}
|
||||
|
||||
export async function main(): Promise<MainResult> {
|
||||
@@ -153,7 +154,10 @@ export async function main(): Promise<MainResult> {
|
||||
await writeSummary(toolState.lastProgressBody);
|
||||
}
|
||||
|
||||
return handleAgentResult(result);
|
||||
return {
|
||||
...handleAgentResult(result),
|
||||
result: toolState.output,
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
||||
log.error(errorMessage);
|
||||
|
||||
@@ -154,11 +154,45 @@ await mcp.call("gh_pullfrog/reply_to_review_comment", {
|
||||
});
|
||||
```
|
||||
|
||||
### output tools
|
||||
|
||||
#### `set_output`
|
||||
set the action output for consumption by subsequent workflow steps. useful when pullfrog is used as a step in a user-defined CI workflow (e.g., generating release notes).
|
||||
|
||||
**parameters:**
|
||||
- `value` (string): the output value to expose
|
||||
|
||||
**returns:**
|
||||
- `success`: true on success
|
||||
|
||||
the value will be available as the `result` output of the action, accessible via `${{ steps.<step-id>.outputs.result }}`.
|
||||
|
||||
**example:**
|
||||
```typescript
|
||||
// when generating content for downstream consumption
|
||||
await mcp.call("gh_pullfrog/set_output", {
|
||||
value: "## Release Notes\n\n- Added new feature X\n- Fixed bug Y"
|
||||
});
|
||||
```
|
||||
|
||||
**usage in workflow:**
|
||||
```yaml
|
||||
- uses: pullfrog/pullfrog@v1
|
||||
id: notes
|
||||
with:
|
||||
prompt: "Generate release notes for v2.0.0"
|
||||
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body: ${{ steps.notes.outputs.result }}
|
||||
```
|
||||
|
||||
### other tools
|
||||
|
||||
see individual files for documentation on other tools:
|
||||
- `comment.ts` - create, edit, and update comments
|
||||
- `issue.ts` - create issues
|
||||
- `output.ts` - set action output for workflow consumption
|
||||
- `pr.ts` - create pull requests
|
||||
- `prInfo.ts` - get pull request information
|
||||
- `review.ts` - create pull request reviews
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { type } from "arktype";
|
||||
import type { ToolContext } from "./server.ts";
|
||||
import { execute, tool } from "./shared.ts";
|
||||
|
||||
export const SetOutputParams = type({
|
||||
value: type.string.describe("the output value to expose as a GitHub Action output"),
|
||||
});
|
||||
|
||||
export function SetOutputTool(ctx: ToolContext) {
|
||||
return tool({
|
||||
name: "set_output",
|
||||
description:
|
||||
"Set the action output for consumption by subsequent workflow steps. The value will be available as the 'result' output of the action.",
|
||||
parameters: SetOutputParams,
|
||||
execute: execute(async (params) => {
|
||||
ctx.toolState.output = params.value;
|
||||
return { success: true };
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -32,6 +32,7 @@ export interface ToolState {
|
||||
progressCommentId: number | null;
|
||||
lastProgressBody?: string;
|
||||
wasUpdated?: boolean;
|
||||
output?: string;
|
||||
}
|
||||
|
||||
import type { ResolveRunResult } from "../utils/workflow.ts";
|
||||
@@ -85,6 +86,7 @@ import { GetIssueCommentsTool } from "./issueComments.ts";
|
||||
import { GetIssueEventsTool } from "./issueEvents.ts";
|
||||
import { IssueInfoTool } from "./issueInfo.ts";
|
||||
import { AddLabelsTool } from "./labels.ts";
|
||||
import { SetOutputTool } from "./output.ts";
|
||||
import { CreatePullRequestTool } from "./pr.ts";
|
||||
import { PullRequestInfoTool } from "./prInfo.ts";
|
||||
import { CreatePullRequestReviewTool } from "./review.ts";
|
||||
@@ -179,6 +181,7 @@ export async function startMcpHttpServer(
|
||||
CommitFilesTool(ctx),
|
||||
PushBranchTool(ctx),
|
||||
UploadFileTool(ctx),
|
||||
SetOutputTool(ctx),
|
||||
];
|
||||
|
||||
// only add BashTool when bash is "restricted"
|
||||
|
||||
@@ -100,6 +100,13 @@ function getShellInstructions(bash: ResolvedPayload["bash"]): string {
|
||||
}
|
||||
}
|
||||
|
||||
function getStandaloneModeInstructions(trigger: string): string {
|
||||
if (trigger !== "unknown") {
|
||||
return "";
|
||||
}
|
||||
return `**Standalone mode**: You are running as a step in a user-defined CI workflow. When you complete your task, call \`${ghPullfrogMcpName}/set_output\` with the main result of your work (generated content, summary of changes, analysis results, etc.). This makes it available as a GitHub Action output named \`result\` for subsequent workflow steps to consume.`;
|
||||
}
|
||||
|
||||
export interface ResolvedInstructions {
|
||||
full: string;
|
||||
system: string;
|
||||
@@ -187,6 +194,8 @@ Tool names may be formatted as \`(server name)/(tool name)\`, for example: \`${g
|
||||
|
||||
${getShellInstructions(ctx.payload.bash)}
|
||||
|
||||
${getStandaloneModeInstructions(ctx.payload.event.trigger)}
|
||||
|
||||
**Command execution**: Never use \`sleep\` to wait for commands to complete. Commands run synchronously - when the bash tool returns, the command has finished.
|
||||
|
||||
**Commenting style**: When posting comments via ${ghPullfrogMcpName}, write as a professional team member would. Your final comments should be polished and actionable—do not include intermediate reasoning like "I'll now look at the code" or "Let me respond to the question."
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import type { AgentResult } from "../agents/shared.ts";
|
||||
import type { MainResult } from "../main.ts";
|
||||
import { log } from "./cli.ts";
|
||||
|
||||
export async function handleAgentResult(result: AgentResult): Promise<MainResult> {
|
||||
export function handleAgentResult(result: AgentResult): MainResult {
|
||||
if (!result.success) {
|
||||
return {
|
||||
success: false,
|
||||
|
||||
Reference in New Issue
Block a user