add schedule & workflow dispatch paths. Also make prepare logic conditional (#353)

* feat: add agent mode for automation scenarios

- Add agent mode that always triggers without checking for mentions
- Implement Mode interface with support for mode-specific tool configuration
- Add getAllowedTools() and getDisallowedTools() methods to Mode interface
- Simplify tests by combining related test cases
- Update documentation and examples to include agent mode
- Fix TypeScript imports to prevent circular dependencies

Agent mode is designed for automation and workflow_dispatch scenarios
where Claude should always run without requiring trigger phrases.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Minor update to readme (from @main to @beta)

* Since workflow_dispatch isn't in the base action, update the examples accordingly

* minor formatting issue

* Update to say beta instead of main

* Fix missed tracking comment to be false

* add schedule & workflow dispatch paths. Also make prepare logic conditional

* tests

* Add test workflow for workflow_dispatch functionality

* Update workflow to use correct branch reference

* remove test workflow dispatch file

* minor lint update

* update workflow dispatch agent example

* minor lint update

* refactor: simplify prepare logic with mode-specific implementations

* ensure tag mode can't work with workflow dispatch and schedule tasks

* simplify: remove workflow_dispatch/schedule from create-prompt

- Remove workflow_dispatch and schedule event handling from create-prompt
  since agent mode doesn't use the standard prompt generation flow
- Enforce mode compatibility at selection time in the registry instead
  of runtime validation in tag mode
- Add explanatory comment in agent mode about why prompt file is needed
- Update tests to reflect simplified event handling

This reduces code duplication and makes the separation between tag mode
(entity-based events) and agent mode (automation events) clearer.

* simplify PR by making agent mode only work with workflow dispatch and schedule events

* remove unnecessary changes

* remove unnecessary changes from PR

- Revert update-comment-link.ts changes (agent mode doesn't use this)
- Revert create-initial.ts changes (agent mode doesn't create comments)
- Remove unused default-branch.ts file
- Revert install-mcp-server.ts changes (agent mode uses minimal MCP)

These files are only used by tag mode for entity-based events, not needed
for workflow_dispatch/schedule support via agent mode.

* fix: handle optional entityNumber for TypeScript

- Add runtime checks in files that require entityNumber
- These files are only used by tag mode which always has entityNumber
- Agent mode (workflow_dispatch/schedule) doesn't use these files

* linting update

---------

Co-authored-by: km-anthropic <km-anthropic@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
km-anthropic
2025-07-29 11:52:45 -07:00
committed by GitHub
parent af32fd318a
commit ec0e9b4f87
15 changed files with 447 additions and 147 deletions

View File

@@ -7,6 +7,33 @@ import type {
PullRequestReviewEvent,
PullRequestReviewCommentEvent,
} from "@octokit/webhooks-types";
// Custom types for GitHub Actions events that aren't webhooks
export type WorkflowDispatchEvent = {
action?: never;
inputs?: Record<string, any>;
ref?: string;
repository: {
name: string;
owner: {
login: string;
};
};
sender: {
login: string;
};
workflow: string;
};
export type ScheduleEvent = {
action?: never;
schedule?: string;
repository: {
name: string;
owner: {
login: string;
};
};
};
import type { ModeName } from "../modes/types";
import { DEFAULT_MODE, isValidMode } from "../modes/registry";
@@ -25,9 +52,11 @@ export type ParsedGitHubContext = {
| IssueCommentEvent
| PullRequestEvent
| PullRequestReviewEvent
| PullRequestReviewCommentEvent;
entityNumber: number;
isPR: boolean;
| PullRequestReviewCommentEvent
| WorkflowDispatchEvent
| ScheduleEvent;
entityNumber?: number;
isPR?: boolean;
inputs: {
mode: ModeName;
triggerPhrase: string;
@@ -129,6 +158,20 @@ export function parseGitHubContext(): ParsedGitHubContext {
isPR: true,
};
}
case "workflow_dispatch": {
return {
...commonFields,
payload: context.payload as unknown as WorkflowDispatchEvent,
// No entityNumber or isPR for workflow_dispatch
};
}
case "schedule": {
return {
...commonFields,
payload: context.payload as unknown as ScheduleEvent,
// No entityNumber or isPR for schedule
};
}
default:
throw new Error(`Unsupported event type: ${context.eventName}`);
}

View File

@@ -22,6 +22,12 @@ export async function createInitialComment(
) {
const { owner, repo } = context.repository;
// This function is only called for entity-based events
if (!context.entityNumber) {
throw new Error("createInitialComment requires an entity number");
}
const entityNumber = context.entityNumber;
const jobRunLink = createJobRunLink(owner, repo, context.runId);
const initialBody = createCommentBody(jobRunLink);
@@ -36,7 +42,7 @@ export async function createInitialComment(
const comments = await octokit.rest.issues.listComments({
owner,
repo,
issue_number: context.entityNumber,
issue_number: entityNumber,
});
const existingComment = comments.data.find((comment) => {
const idMatch = comment.user?.id === CLAUDE_APP_BOT_ID;
@@ -59,7 +65,7 @@ export async function createInitialComment(
response = await octokit.rest.issues.createComment({
owner,
repo,
issue_number: context.entityNumber,
issue_number: entityNumber,
body: initialBody,
});
}
@@ -68,7 +74,7 @@ export async function createInitialComment(
response = await octokit.rest.pulls.createReplyForReviewComment({
owner,
repo,
pull_number: context.entityNumber,
pull_number: entityNumber,
comment_id: context.payload.comment.id,
body: initialBody,
});
@@ -77,7 +83,7 @@ export async function createInitialComment(
response = await octokit.rest.issues.createComment({
owner,
repo,
issue_number: context.entityNumber,
issue_number: entityNumber,
body: initialBody,
});
}
@@ -95,7 +101,7 @@ export async function createInitialComment(
const response = await octokit.rest.issues.createComment({
owner,
repo,
issue_number: context.entityNumber,
issue_number: entityNumber,
body: initialBody,
});