@geminixiang/mikan 1.0.0-beta.85 → 1.0.0-beta.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +8 -8
- package/dist/adapters/commands/session-view.js +1 -1
- package/dist/adapters/commands/session-view.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +1 -8
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/github/activity.d.ts +3 -0
- package/dist/adapters/github/activity.d.ts.map +1 -0
- package/dist/adapters/github/activity.js +154 -0
- package/dist/adapters/github/activity.js.map +1 -0
- package/dist/adapters/github/bot.d.ts +10 -20
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +119 -342
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +9 -19
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +28 -104
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +29 -20
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +2 -10
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +28 -91
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/policy.d.ts +19 -0
- package/dist/adapters/github/policy.d.ts.map +1 -0
- package/dist/adapters/github/policy.js +79 -0
- package/dist/adapters/github/policy.js.map +1 -0
- package/dist/adapters/github/tool-pack.d.ts +2 -2
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +4 -9
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +6 -8
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +7 -9
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/types.d.ts +66 -67
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/github/webhook.d.ts +2 -1
- package/dist/adapters/github/webhook.d.ts.map +1 -1
- package/dist/adapters/github/webhook.js +46 -4
- package/dist/adapters/github/webhook.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +3 -0
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/shared.d.ts +3 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +45 -23
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +65 -2
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +3 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +76 -34
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/jev-context.js +2 -2
- package/dist/adapters/slack/jev-context.js.map +1 -1
- package/dist/adapters/slack/task-status.d.ts +3 -2
- package/dist/adapters/slack/task-status.d.ts.map +1 -1
- package/dist/adapters/slack/task-status.js +12 -15
- package/dist/adapters/slack/task-status.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +1 -8
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/web/admin/portal.js +1 -1
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/adapters/web/admin/provider-models.d.ts.map +1 -1
- package/dist/adapters/web/admin/provider-models.js +10 -3
- package/dist/adapters/web/admin/provider-models.js.map +1 -1
- package/dist/adapters/web/login/portal.js +6 -1
- package/dist/adapters/web/login/portal.js.map +1 -1
- package/dist/adapters/web/server.d.ts.map +1 -1
- package/dist/adapters/web/server.js +5 -3
- package/dist/adapters/web/server.js.map +1 -1
- package/dist/adapters/web/session-view/portal.d.ts +2 -1
- package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
- package/dist/adapters/web/session-view/portal.js +18 -27
- package/dist/adapters/web/session-view/portal.js.map +1 -1
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +1 -2
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/onboard.d.ts +0 -1
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +1 -7
- package/dist/cli/onboard.js.map +1 -1
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +24 -22
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +1 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +11 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/scheduler.d.ts.map +1 -1
- package/dist/events/scheduler.js +3 -0
- package/dist/events/scheduler.js.map +1 -1
- package/dist/file-guards.d.ts +7 -0
- package/dist/file-guards.d.ts.map +1 -1
- package/dist/file-guards.js +63 -1
- package/dist/file-guards.js.map +1 -1
- package/dist/harness/mcp.d.ts.map +1 -1
- package/dist/harness/mcp.js +75 -31
- package/dist/harness/mcp.js.map +1 -1
- package/dist/harness/models.js +2 -2
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/open-connector.d.ts.map +1 -1
- package/dist/harness/open-connector.js +14 -7
- package/dist/harness/open-connector.js.map +1 -1
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +2 -0
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.d.ts +1 -1
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +13 -31
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +6 -9
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +6 -0
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/tools/event.d.ts.map +1 -1
- package/dist/harness/tools/event.js +19 -2
- package/dist/harness/tools/event.js.map +1 -1
- package/dist/harness/tools/generate-image.d.ts.map +1 -1
- package/dist/harness/tools/generate-image.js +17 -3
- package/dist/harness/tools/generate-image.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +1 -2
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +75 -50
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.js +34 -45
- package/dist/main.js.map +1 -1
- package/dist/memory-capture/index.d.ts.map +1 -1
- package/dist/memory-capture/index.js +3 -3
- package/dist/memory-capture/index.js.map +1 -1
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +2 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/office-sessions.d.ts +3 -0
- package/dist/migrations/office-sessions.d.ts.map +1 -0
- package/dist/migrations/office-sessions.js +81 -0
- package/dist/migrations/office-sessions.js.map +1 -0
- package/dist/office/index.d.ts +0 -1
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +3 -5
- package/dist/office/index.js.map +1 -1
- package/dist/runtime/conversation-runtime.js +12 -12
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/sandbox/provisioner.d.ts +1 -1
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +20 -5
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +28 -40
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/store.d.ts +2 -3
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +8 -14
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +6 -5
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -6
- package/dist/adapters/github/repo.d.ts +0 -8
- package/dist/adapters/github/repo.d.ts.map +0 -1
- package/dist/adapters/github/repo.js +0 -92
- package/dist/adapters/github/repo.js.map +0 -1
- package/dist/adapters/github/tools/sync.d.ts +0 -13
- package/dist/adapters/github/tools/sync.d.ts.map +0 -1
- package/dist/adapters/github/tools/sync.js +0 -29
- package/dist/adapters/github/tools/sync.js.map +0 -1
|
@@ -3,6 +3,34 @@ import { resolveChatSessionKey } from "../../sessions/session-key.js";
|
|
|
3
3
|
import { createProgressiveRenderer, formatMarkdownToolResult } from "../progressive-renderer.js";
|
|
4
4
|
import { formatGithubContinuation } from "./bot.js";
|
|
5
5
|
import { GITHUB_MAX_COMMENT_LENGTH } from "./client.js";
|
|
6
|
+
function repositoryGuide(capabilities, ref, identity) {
|
|
7
|
+
const author = identity
|
|
8
|
+
? `Commit as the agent account: git config user.name "${identity.login}" and ` +
|
|
9
|
+
`git config user.email "${identity.email}". `
|
|
10
|
+
: "";
|
|
11
|
+
const clone = `## Repository & pull requests\n` +
|
|
12
|
+
`Nothing is cloned for you. When you need the code, clone it into your scratch ` +
|
|
13
|
+
`directory with git clone https://github.com/${ref.owner}/${ref.repo}.git; if this ` +
|
|
14
|
+
`conversation is a pull request, run gh pr checkout ${ref.number} inside the clone. ` +
|
|
15
|
+
`git and gh use the GitHub credentials of this sandbox, if it has any; without them ` +
|
|
16
|
+
`only public repositories are reachable. ${author}\n`;
|
|
17
|
+
const shipping = capabilities.has("push")
|
|
18
|
+
? `To ship code changes: push a new branch (for example pi/fix-${ref.number}), never ` +
|
|
19
|
+
`the default branch, which is protected, then call github_pr with that branch to ` +
|
|
20
|
+
`open a pull request (draft: true for a draft). To update this pull request, push ` +
|
|
21
|
+
`to its head branch; no github_pr call is needed. Use github_checks to read CI ` +
|
|
22
|
+
`results for your branch (or this PR) — pass a failing check's job id to read its ` +
|
|
23
|
+
`log — and iterate until they pass. Humans review and merge every PR.\n`
|
|
24
|
+
: `Do not push branches or open pull requests here: propose code changes in your ` +
|
|
25
|
+
`reply (for example as a diff or suggestion block) for a human to apply. Use ` +
|
|
26
|
+
`github_checks to read this pull request's CI results.\n`;
|
|
27
|
+
const lookup = `github_read looks up PR/issue metadata that a clone does not show (diff stats, ` +
|
|
28
|
+
`changed files, review state, other issues in this repo)` +
|
|
29
|
+
(capabilities.has("triage")
|
|
30
|
+
? `; github_issue manages labels, assignees, and close/reopen for triage.`
|
|
31
|
+
: `.`);
|
|
32
|
+
return clone + shipping + lookup;
|
|
33
|
+
}
|
|
6
34
|
export function createGithubAdapters(event, bot) {
|
|
7
35
|
const conversationId = event.address.conversationId;
|
|
8
36
|
const ref = parseGithubConversationId(conversationId);
|
|
@@ -37,26 +65,7 @@ export function createGithubAdapters(event, bot) {
|
|
|
37
65
|
`tagged [PR review comment rc-<id> …] are inline review threads on a diff line: ` +
|
|
38
66
|
`answer those with the github_review_reply tool (comment_id = that id) so the reply ` +
|
|
39
67
|
`lands in-thread — your normal response posts as a plain PR comment.\n\n` +
|
|
40
|
-
|
|
41
|
-
`The repository is cloned at ./repo — a snapshot from this conversation's first ` +
|
|
42
|
-
`trigger; run github_sync when it may be stale to pull the latest PR head or base ` +
|
|
43
|
-
`branch. If this conversation is a pull request, its head branch is checked out ` +
|
|
44
|
-
`under its real name (run git branch --show-current in ./repo to see it; fork PRs ` +
|
|
45
|
-
`fall back to pr-${ref.number}). You have no git credentials, so git fetch/push ` +
|
|
46
|
-
`fail by design.\n` +
|
|
47
|
-
`To ship code changes: commit inside ./repo (the git author is preconfigured) on a ` +
|
|
48
|
-
`pi/<name> branch, then call the github_pr tool to push it. When this conversation's ` +
|
|
49
|
-
`checked-out PR head branch is already named pi/<name> — e.g. a PR you opened ` +
|
|
50
|
-
`earlier — commit directly on it and pass that branch to github_pr: the push ` +
|
|
51
|
-
`updates THIS pull request instead of opening a new one. Any other branch opens a ` +
|
|
52
|
-
`new pull request (draft: true for a draft); calling github_pr again with the same ` +
|
|
53
|
-
`branch pushes new commits to its existing PR. Use github_checks to read CI results ` +
|
|
54
|
-
`for your branch (or this PR) — pass a failing check's job id to read its log — and ` +
|
|
55
|
-
`iterate until they pass. You cannot push the default branch or ` +
|
|
56
|
-
`merge — humans review and merge every PR.\n` +
|
|
57
|
-
`github_read looks up PR/issue metadata this clone cannot show (diff stats, changed ` +
|
|
58
|
-
`files, review state, other issues in this repo); github_issue manages labels, ` +
|
|
59
|
-
`assignees, and close/reopen for triage.`,
|
|
68
|
+
repositoryGuide(bot.capabilities, ref, bot.agentIdentity),
|
|
60
69
|
diagnostics: {
|
|
61
70
|
showUsageSummary: false,
|
|
62
71
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/github/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjG,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/github/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConversationContext } from \"../../types.js\";\nimport { createConversationMessage, parseGithubConversationId } from \"../../office/index.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport { createProgressiveRenderer, formatMarkdownToolResult } from \"../progressive-renderer.js\";\nimport { formatGithubContinuation } from \"./bot.js\";\nimport { GITHUB_MAX_COMMENT_LENGTH } from \"./client.js\";\nimport type {\n GithubCapability,\n GithubAgentIdentity,\n GithubConversationBot,\n GithubEvent,\n} from \"./types.js\";\nimport type { GithubConversationRef } from \"../../office/types.js\";\n\nfunction repositoryGuide(\n capabilities: ReadonlySet<GithubCapability>,\n ref: GithubConversationRef,\n identity: GithubAgentIdentity | undefined,\n): string {\n const author = identity\n ? `Commit as the agent account: git config user.name \"${identity.login}\" and ` +\n `git config user.email \"${identity.email}\". `\n : \"\";\n const clone =\n `## Repository & pull requests\\n` +\n `Nothing is cloned for you. When you need the code, clone it into your scratch ` +\n `directory with git clone https://github.com/${ref.owner}/${ref.repo}.git; if this ` +\n `conversation is a pull request, run gh pr checkout ${ref.number} inside the clone. ` +\n `git and gh use the GitHub credentials of this sandbox, if it has any; without them ` +\n `only public repositories are reachable. ${author}\\n`;\n const shipping = capabilities.has(\"push\")\n ? `To ship code changes: push a new branch (for example pi/fix-${ref.number}), never ` +\n `the default branch, which is protected, then call github_pr with that branch to ` +\n `open a pull request (draft: true for a draft). To update this pull request, push ` +\n `to its head branch; no github_pr call is needed. Use github_checks to read CI ` +\n `results for your branch (or this PR) — pass a failing check's job id to read its ` +\n `log — and iterate until they pass. Humans review and merge every PR.\\n`\n : `Do not push branches or open pull requests here: propose code changes in your ` +\n `reply (for example as a diff or suggestion block) for a human to apply. Use ` +\n `github_checks to read this pull request's CI results.\\n`;\n const lookup =\n `github_read looks up PR/issue metadata that a clone does not show (diff stats, ` +\n `changed files, review state, other issues in this repo)` +\n (capabilities.has(\"triage\")\n ? `; github_issue manages labels, assignees, and close/reopen for triage.`\n : `.`);\n return clone + shipping + lookup;\n}\n\nexport function createGithubAdapters(\n event: GithubEvent,\n bot: GithubConversationBot,\n): ConversationContext {\n const conversationId = event.address.conversationId;\n const ref = parseGithubConversationId(conversationId);\n\n const message = createConversationMessage({\n platform: \"github\",\n conversationId,\n address: event.address,\n id: event.ts,\n sessionKey:\n event.sessionKey ??\n resolveChatSessionKey({\n conversationId,\n conversationKind: event.conversationKind,\n messageId: event.ts,\n persistentTopLevel: true,\n threadTs: event.thread_ts,\n }),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: event.userName,\n text: event.text,\n attachments: event.attachments,\n threadTs: event.thread_ts,\n });\n const baseInfo = bot.getMessagingInfo();\n const platform = {\n ...baseInfo,\n formattingGuide:\n `${baseInfo.formattingGuide}\\n\\n` +\n `## Conversation context\\n` +\n `This conversation IS GitHub issue/PR ${ref.owner}/${ref.repo}#${ref.number}: the ` +\n `first message in the history is its title and body, and the following messages are ` +\n `its comments. When the user says \"this issue\", they mean #${ref.number}. Messages ` +\n `tagged [PR review comment rc-<id> …] are inline review threads on a diff line: ` +\n `answer those with the github_review_reply tool (comment_id = that id) so the reply ` +\n `lands in-thread — your normal response posts as a plain PR comment.\\n\\n` +\n repositoryGuide(bot.capabilities, ref, bot.agentIdentity),\n diagnostics: {\n showUsageSummary: false,\n },\n };\n\n const { responder } = createProgressiveRenderer({\n label: \"GitHub\",\n maxLength: GITHUB_MAX_COMMENT_LENGTH,\n formatContinuation: formatGithubContinuation,\n errorPrefix: \"**Error:** \",\n formatToolResult: formatMarkdownToolResult,\n logIntermediateResponses: true,\n responseErrorContext: (responseId) => ({\n platform: \"github\",\n conversationId,\n messageId: message.id,\n sessionKey: message.sessionKey,\n responseMessageId: responseId === null ? null : Number(responseId),\n conversationKind: message.conversationKind,\n }),\n post: async (text) => {\n return String(await bot.postComment(ref, text));\n },\n update: (id, text) => bot.updateMessage(conversationId, id, text),\n postExtra: async (text) => bot.postComment(ref, text),\n delete: async (id) => {\n await bot.deleteComment(ref, Number(id));\n },\n logBotResponse: (text, id) => bot.logBotResponse(conversationId, text, id),\n uploadFallbackNote: (name) =>\n `*(file \\`${name}\\` was produced, but the GitHub adapter cannot attach files to comments)*`,\n react: (emoji) => bot.addReaction(conversationId, event.ts, emoji),\n });\n\n return { address: message.address, message, responder, platform };\n}\n"]}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import type { GithubConversationRef, Workspace } from "../../office/types.js";
|
|
2
1
|
import type { GithubApi, GithubCheckSummary, GithubIssueRequest, GithubPrRequest, GithubPrResult, GithubReadRequest, GithubReadResult, PlatformGithubOps } from "./types.js";
|
|
3
|
-
export declare function fetchIsPr(client: GithubApi, ref: GithubConversationRef): Promise<boolean>;
|
|
4
|
-
export declare function fetchPrHeadBranch(client: GithubApi, ref: GithubConversationRef): Promise<string | undefined>;
|
|
5
2
|
export declare class GithubOps implements PlatformGithubOps {
|
|
6
3
|
private readonly client;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
workspace: Workspace;
|
|
10
|
-
});
|
|
11
|
-
private repoDir;
|
|
12
|
-
pushAndCreatePr(conversationId: string, request: GithubPrRequest): Promise<GithubPrResult>;
|
|
4
|
+
constructor(client: GithubApi);
|
|
5
|
+
createPullRequest(conversationId: string, request: GithubPrRequest): Promise<GithubPrResult>;
|
|
13
6
|
getChecks(conversationId: string, branch?: string): Promise<GithubCheckSummary[]>;
|
|
14
|
-
syncRepo(conversationId: string, branch?: string): Promise<string>;
|
|
15
7
|
readGithub(conversationId: string, request: GithubReadRequest): Promise<GithubReadResult>;
|
|
16
8
|
manageIssue(conversationId: string, request: GithubIssueRequest): Promise<string>;
|
|
17
9
|
replyToReviewThread(conversationId: string, commentId: number, body: string): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-ops.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/github-ops.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"github-ops.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/github-ops.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAIpB,qBAAa,SAAU,YAAW,iBAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAnC,YAA6B,MAAM,EAAE,SAAS,EAAI;IAE5C,iBAAiB,CACrB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAoCzB;IAEK,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAsDtF;IAEK,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4C9F;IAEK,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoEtF;IAEK,mBAAmB,CACvB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CA4B1B;IAEK,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBtE;CACF"}
|
|
@@ -1,52 +1,15 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
1
|
import * as log from "../../log.js";
|
|
3
2
|
import { GithubApiError, GITHUB_MAX_COMMENT_LENGTH, githubRetry } from "./client.js";
|
|
4
|
-
import {
|
|
5
|
-
import { createOfficeAddress, parseGithubConversationId } from "../../office/index.js";
|
|
3
|
+
import { parseGithubConversationId } from "../../office/index.js";
|
|
6
4
|
const MAX_LOG_CHARS = 20000;
|
|
7
|
-
export async function fetchIsPr(client, ref) {
|
|
8
|
-
try {
|
|
9
|
-
const issue = await githubRetry(() => client.getIssue(ref.owner, ref.repo, ref.number));
|
|
10
|
-
return Boolean(issue.pull_request);
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
export async function fetchPrHeadBranch(client, ref) {
|
|
17
|
-
try {
|
|
18
|
-
const pr = await githubRetry(() => client.getPullRequest(ref.owner, ref.repo, ref.number));
|
|
19
|
-
const sameRepo = pr.head?.repo?.full_name?.toLowerCase() === `${ref.owner}/${ref.repo}`.toLowerCase();
|
|
20
|
-
return sameRepo ? pr.head?.ref : undefined;
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
5
|
export class GithubOps {
|
|
27
|
-
constructor(client
|
|
6
|
+
constructor(client) {
|
|
28
7
|
this.client = client;
|
|
29
|
-
this.config = config;
|
|
30
8
|
}
|
|
31
|
-
|
|
32
|
-
return conversationRepoDir(this.config.workspace.office(createOfficeAddress("github", conversationId)));
|
|
33
|
-
}
|
|
34
|
-
async pushAndCreatePr(conversationId, request) {
|
|
9
|
+
async createPullRequest(conversationId, request) {
|
|
35
10
|
const ref = parseGithubConversationId(conversationId);
|
|
36
|
-
const dir = this.repoDir(conversationId);
|
|
37
|
-
if (!existsSync(dir)) {
|
|
38
|
-
throw new Error("This conversation has no ./repo clone to push from.");
|
|
39
|
-
}
|
|
40
|
-
if (!GITHUB_PUSH_BRANCH_PATTERN.test(request.branch)) {
|
|
41
|
-
throw new Error(`Branch '${request.branch}' is not pushable: name it pi/<something> (e.g. pi/fix-${ref.number}).`);
|
|
42
|
-
}
|
|
43
11
|
const repository = await githubRetry(() => this.client.getRepository(ref.owner, ref.repo));
|
|
44
12
|
const base = request.base ?? repository.default_branch;
|
|
45
|
-
const token = await this.client.createScopedInstallationToken(ref.repo, {
|
|
46
|
-
contents: "write",
|
|
47
|
-
pull_requests: "write",
|
|
48
|
-
});
|
|
49
|
-
await pushBranch({ dir, branch: request.branch, token });
|
|
50
13
|
try {
|
|
51
14
|
const pr = await githubRetry(() => this.client.createPullRequest(ref.owner, ref.repo, {
|
|
52
15
|
title: request.title,
|
|
@@ -64,7 +27,7 @@ export class GithubOps {
|
|
|
64
27
|
/already exists/i.test(err.message)) {
|
|
65
28
|
const existing = await this.client.findOpenPullRequestByBranch(ref.owner, ref.repo, request.branch);
|
|
66
29
|
if (existing) {
|
|
67
|
-
log.logInfo(`[${conversationId}]
|
|
30
|
+
log.logInfo(`[${conversationId}] Branch already has PR #${existing.number}: ${existing.html_url}`);
|
|
68
31
|
return { number: existing.number, url: existing.html_url, updatedExisting: true };
|
|
69
32
|
}
|
|
70
33
|
}
|
|
@@ -87,56 +50,30 @@ export class GithubOps {
|
|
|
87
50
|
}
|
|
88
51
|
target = pr.head.sha;
|
|
89
52
|
}
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
53
|
+
const status = await githubRetry(() => this.client.getCombinedStatus(ref.owner, ref.repo, target));
|
|
54
|
+
const runs = await githubRetry(() => this.client.listWorkflowRuns(ref.owner, ref.repo, status.sha));
|
|
55
|
+
const jobs = await Promise.all(runs.map(async (run) => {
|
|
56
|
+
const runJobs = await githubRetry(() => this.client.listWorkflowJobs(ref.owner, ref.repo, run.id));
|
|
57
|
+
return runJobs.map((job) => ({
|
|
58
|
+
id: job.id,
|
|
59
|
+
name: run.name ? `${run.name} / ${job.name}` : job.name,
|
|
60
|
+
status: job.status,
|
|
61
|
+
conclusion: job.conclusion,
|
|
62
|
+
url: job.html_url,
|
|
63
|
+
source: "actions",
|
|
64
|
+
outputSummary: null,
|
|
65
|
+
}));
|
|
99
66
|
}));
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
let prNumber;
|
|
111
|
-
let prHeadBranch;
|
|
112
|
-
let defaultBranch;
|
|
113
|
-
if (!branch) {
|
|
114
|
-
if (await fetchIsPr(this.client, ref)) {
|
|
115
|
-
prNumber = ref.number;
|
|
116
|
-
prHeadBranch = await fetchPrHeadBranch(this.client, ref);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
const repository = await githubRetry(() => this.client.getRepository(ref.owner, ref.repo));
|
|
120
|
-
defaultBranch = repository.default_branch;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
const result = await syncRepo({ dir, token, branch, prNumber, prHeadBranch, defaultBranch });
|
|
124
|
-
if (result.updatedCheckout) {
|
|
125
|
-
return `Updated ./repo: branch ${result.target} is now at ${result.fetchedSha.slice(0, 12)}.`;
|
|
126
|
-
}
|
|
127
|
-
const reasons = [];
|
|
128
|
-
if (result.currentBranch !== result.target) {
|
|
129
|
-
reasons.push(`the checkout is on '${result.currentBranch}', not '${result.target}'`);
|
|
130
|
-
}
|
|
131
|
-
if (result.dirty) {
|
|
132
|
-
reasons.push("the working tree has uncommitted changes");
|
|
133
|
-
}
|
|
134
|
-
if (result.localCommits > 0) {
|
|
135
|
-
reasons.push(`'${result.target}' has ${result.localCommits} local commit(s) not on origin`);
|
|
136
|
-
}
|
|
137
|
-
return (`Fetched ${result.target} to FETCH_HEAD (${result.fetchedSha.slice(0, 12)}) but left the ` +
|
|
138
|
-
`checkout alone: ${reasons.join("; ")}. Merge or rebase FETCH_HEAD yourself ` +
|
|
139
|
-
`(e.g. git merge FETCH_HEAD), or commit your work to a pi/* branch first.`);
|
|
67
|
+
const statuses = status.statuses.map((entry) => ({
|
|
68
|
+
id: entry.id,
|
|
69
|
+
name: entry.context,
|
|
70
|
+
status: entry.state === "pending" ? "in_progress" : "completed",
|
|
71
|
+
conclusion: entry.state === "pending" ? null : entry.state === "success" ? "success" : "failure",
|
|
72
|
+
url: entry.target_url,
|
|
73
|
+
source: "status",
|
|
74
|
+
outputSummary: entry.description?.trim() ? entry.description.slice(0, 500) : null,
|
|
75
|
+
}));
|
|
76
|
+
return [...jobs.flat(), ...statuses];
|
|
140
77
|
}
|
|
141
78
|
async readGithub(conversationId, request) {
|
|
142
79
|
const ref = parseGithubConversationId(conversationId);
|
|
@@ -269,7 +206,7 @@ export class GithubOps {
|
|
|
269
206
|
throw new Error(`No GitHub Actions log for job ${jobId}. Logs are only available for checks reported ` +
|
|
270
207
|
`by github-actions; external CI keeps logs on its own service — ` +
|
|
271
208
|
`use that check's summary/url from github_checks, or reproduce the failure locally ` +
|
|
272
|
-
`in
|
|
209
|
+
`in your clone instead. Do not retry with other ids.`, { cause: err });
|
|
273
210
|
}
|
|
274
211
|
throw err;
|
|
275
212
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-ops.js","sourceRoot":"","sources":["../../../src/adapters/github/github-ops.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport * as log from \"../../log.js\";\nimport { GithubApiError, GITHUB_MAX_COMMENT_LENGTH, githubRetry } from \"./client.js\";\nimport { conversationRepoDir, GITHUB_PUSH_BRANCH_PATTERN, pushBranch, syncRepo } from \"./repo.js\";\nimport { createOfficeAddress, parseGithubConversationId } from \"../../office/index.js\";\n\nimport type { GithubConversationRef, Workspace } from \"../../office/types.js\";\nimport type {\n GithubApi,\n GithubCheckSummary,\n GithubIssueRequest,\n GithubPrRequest,\n GithubPrResult,\n GithubReadRequest,\n GithubReadResult,\n PlatformGithubOps,\n} from \"./types.js\";\n\nconst MAX_LOG_CHARS = 20000;\n\nexport async function fetchIsPr(client: GithubApi, ref: GithubConversationRef): Promise<boolean> {\n try {\n const issue = await githubRetry(() => client.getIssue(ref.owner, ref.repo, ref.number));\n return Boolean(issue.pull_request);\n } catch {\n return false;\n }\n}\n\nexport async function fetchPrHeadBranch(\n client: GithubApi,\n ref: GithubConversationRef,\n): Promise<string | undefined> {\n try {\n const pr = await githubRetry(() => client.getPullRequest(ref.owner, ref.repo, ref.number));\n const sameRepo =\n pr.head?.repo?.full_name?.toLowerCase() === `${ref.owner}/${ref.repo}`.toLowerCase();\n return sameRepo ? pr.head?.ref : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport class GithubOps implements PlatformGithubOps {\n constructor(\n private readonly client: GithubApi,\n private readonly config: { workspace: Workspace },\n ) {}\n\n private repoDir(conversationId: string): string {\n return conversationRepoDir(\n this.config.workspace.office(createOfficeAddress(\"github\", conversationId)),\n );\n }\n\n async pushAndCreatePr(conversationId: string, request: GithubPrRequest): Promise<GithubPrResult> {\n const ref = parseGithubConversationId(conversationId);\n const dir = this.repoDir(conversationId);\n if (!existsSync(dir)) {\n throw new Error(\"This conversation has no ./repo clone to push from.\");\n }\n if (!GITHUB_PUSH_BRANCH_PATTERN.test(request.branch)) {\n throw new Error(\n `Branch '${request.branch}' is not pushable: name it pi/<something> (e.g. pi/fix-${ref.number}).`,\n );\n }\n const repository = await githubRetry(() => this.client.getRepository(ref.owner, ref.repo));\n const base = request.base ?? repository.default_branch;\n const token = await this.client.createScopedInstallationToken(ref.repo, {\n contents: \"write\",\n pull_requests: \"write\",\n });\n await pushBranch({ dir, branch: request.branch, token });\n try {\n const pr = await githubRetry(() =>\n this.client.createPullRequest(ref.owner, ref.repo, {\n title: request.title,\n head: request.branch,\n base,\n body: request.body,\n draft: request.draft,\n }),\n );\n log.logInfo(`[${conversationId}] Opened PR #${pr.number}: ${pr.html_url}`);\n return { number: pr.number, url: pr.html_url };\n } catch (err) {\n if (\n err instanceof GithubApiError &&\n err.status === 422 &&\n /already exists/i.test(err.message)\n ) {\n const existing = await this.client.findOpenPullRequestByBranch(\n ref.owner,\n ref.repo,\n request.branch,\n );\n if (existing) {\n log.logInfo(\n `[${conversationId}] Pushed to existing PR #${existing.number}: ${existing.html_url}`,\n );\n return { number: existing.number, url: existing.html_url, updatedExisting: true };\n }\n }\n throw err;\n }\n }\n\n async getChecks(conversationId: string, branch?: string): Promise<GithubCheckSummary[]> {\n const ref = parseGithubConversationId(conversationId);\n let target = branch;\n if (!target) {\n let pr;\n try {\n pr = await githubRetry(() => this.client.getPullRequest(ref.owner, ref.repo, ref.number));\n } catch {\n pr = null;\n }\n if (!pr?.head) {\n throw new Error(\n \"This conversation is not a pull request — pass the branch whose checks you want.\",\n );\n }\n target = pr.head.sha;\n }\n const runs = await githubRetry(() => this.client.listCheckRuns(ref.owner, ref.repo, target));\n return runs.map((run) => ({\n id: run.id,\n name: run.name,\n status: run.status,\n conclusion: run.conclusion,\n url: run.html_url,\n appSlug: run.app?.slug ?? null,\n outputSummary: run.output?.summary?.trim() ? run.output.summary.slice(0, 500) : null,\n }));\n }\n\n async syncRepo(conversationId: string, branch?: string): Promise<string> {\n const ref = parseGithubConversationId(conversationId);\n const dir = this.repoDir(conversationId);\n if (!existsSync(dir)) {\n throw new Error(\"This conversation has no ./repo clone to sync.\");\n }\n const token = await this.client.createScopedInstallationToken(ref.repo, {\n contents: \"read\",\n });\n let prNumber: number | undefined;\n let prHeadBranch: string | undefined;\n let defaultBranch: string | undefined;\n if (!branch) {\n if (await fetchIsPr(this.client, ref)) {\n prNumber = ref.number;\n prHeadBranch = await fetchPrHeadBranch(this.client, ref);\n } else {\n const repository = await githubRetry(() => this.client.getRepository(ref.owner, ref.repo));\n defaultBranch = repository.default_branch;\n }\n }\n const result = await syncRepo({ dir, token, branch, prNumber, prHeadBranch, defaultBranch });\n\n if (result.updatedCheckout) {\n return `Updated ./repo: branch ${result.target} is now at ${result.fetchedSha.slice(0, 12)}.`;\n }\n const reasons: string[] = [];\n if (result.currentBranch !== result.target) {\n reasons.push(`the checkout is on '${result.currentBranch}', not '${result.target}'`);\n }\n if (result.dirty) {\n reasons.push(\"the working tree has uncommitted changes\");\n }\n if (result.localCommits > 0) {\n reasons.push(`'${result.target}' has ${result.localCommits} local commit(s) not on origin`);\n }\n return (\n `Fetched ${result.target} to FETCH_HEAD (${result.fetchedSha.slice(0, 12)}) but left the ` +\n `checkout alone: ${reasons.join(\"; \")}. Merge or rebase FETCH_HEAD yourself ` +\n `(e.g. git merge FETCH_HEAD), or commit your work to a pi/* branch first.`\n );\n }\n\n async readGithub(conversationId: string, request: GithubReadRequest): Promise<GithubReadResult> {\n const ref = parseGithubConversationId(conversationId);\n const number = request.number ?? ref.number;\n switch (request.action) {\n case \"pr\": {\n const pr = await githubRetry(() => this.client.getPullRequest(ref.owner, ref.repo, number));\n return { kind: \"pr\", pr };\n }\n case \"pr_files\": {\n const files = await githubRetry(() =>\n this.client.listPullRequestFiles(ref.owner, ref.repo, number),\n );\n return { kind: \"pr_files\", files };\n }\n case \"pr_reviews\": {\n const [reviews, threads] = await Promise.all([\n githubRetry(() => this.client.listPullRequestReviews(ref.owner, ref.repo, number)),\n githubRetry(() => this.client.listPullReviewComments(ref.owner, ref.repo, number)),\n ]);\n return { kind: \"pr_reviews\", reviews, threads };\n }\n case \"issue\": {\n const issue = await githubRetry(() => this.client.getIssue(ref.owner, ref.repo, number));\n return { kind: \"issue\", issue };\n }\n case \"comments\": {\n const comments = await githubRetry(() =>\n this.client.listIssueComments(ref.owner, ref.repo, number),\n );\n return { kind: \"comments\", comments };\n }\n case \"list\": {\n const issues = await githubRetry(() =>\n this.client.listIssues(ref.owner, ref.repo, {\n state: request.state,\n labels: request.labels,\n creator: request.creator,\n }),\n );\n return { kind: \"list\", issues };\n }\n default:\n throw new Error(`Unknown github_read action: ${String(request.action)}`);\n }\n }\n\n async manageIssue(conversationId: string, request: GithubIssueRequest): Promise<string> {\n const ref = parseGithubConversationId(conversationId);\n const number = request.number ?? ref.number;\n try {\n switch (request.action) {\n case \"add_labels\": {\n const labels = request.labels;\n if (!labels?.length) {\n throw new Error(\"add_labels requires a non-empty labels array.\");\n }\n await githubRetry(() => this.client.addIssueLabels(ref.owner, ref.repo, number, labels));\n return `Added label(s) ${labels.join(\", \")} to #${number}.`;\n }\n case \"remove_label\": {\n const label = request.label;\n if (!label) {\n throw new Error(\"remove_label requires a label name.\");\n }\n await githubRetry(() => this.client.removeIssueLabel(ref.owner, ref.repo, number, label));\n return `Removed label ${label} from #${number}.`;\n }\n case \"add_assignees\": {\n const assignees = request.assignees;\n if (!assignees?.length) {\n throw new Error(\"add_assignees requires a non-empty assignees array.\");\n }\n await githubRetry(() =>\n this.client.addIssueAssignees(ref.owner, ref.repo, number, assignees),\n );\n return `Assigned ${assignees.map((login) => `@${login}`).join(\", \")} to #${number}.`;\n }\n case \"remove_assignees\": {\n const assignees = request.assignees;\n if (!assignees?.length) {\n throw new Error(\"remove_assignees requires a non-empty assignees array.\");\n }\n await githubRetry(() =>\n this.client.removeIssueAssignees(ref.owner, ref.repo, number, assignees),\n );\n return `Unassigned ${assignees.map((login) => `@${login}`).join(\", \")} from #${number}.`;\n }\n case \"close\": {\n await githubRetry(() =>\n this.client.updateIssueState(\n ref.owner,\n ref.repo,\n number,\n \"closed\",\n request.state_reason,\n ),\n );\n return `Closed #${number}${request.state_reason ? ` as ${request.state_reason}` : \"\"}.`;\n }\n case \"reopen\": {\n await githubRetry(() =>\n this.client.updateIssueState(ref.owner, ref.repo, number, \"open\"),\n );\n return `Reopened #${number}.`;\n }\n default:\n throw new Error(`Unknown github_issue action: ${String(request.action)}`);\n }\n } catch (err) {\n if (err instanceof GithubApiError && err.status === 404) {\n throw new Error(`Issue #${number} not found in ${ref.owner}/${ref.repo}.`, { cause: err });\n }\n throw err;\n }\n }\n\n async replyToReviewThread(\n conversationId: string,\n commentId: number,\n body: string,\n ): Promise<{ url: string }> {\n if (!Number.isInteger(commentId) || commentId <= 0) {\n throw new Error(\n \"comment_id must be the numeric id from an [PR review comment rc-<id> …] message.\",\n );\n }\n const ref = parseGithubConversationId(conversationId);\n const text =\n body.length > GITHUB_MAX_COMMENT_LENGTH\n ? `${body.slice(0, GITHUB_MAX_COMMENT_LENGTH)}\\n…(truncated)`\n : body;\n try {\n const reply = await githubRetry(() =>\n this.client.replyToReviewComment(ref.owner, ref.repo, ref.number, commentId, text),\n );\n return {\n url: `https://github.com/${ref.owner}/${ref.repo}/pull/${ref.number}#discussion_r${reply.id}`,\n };\n } catch (err) {\n if (err instanceof GithubApiError && err.status === 404) {\n throw new Error(\n `Comment ${commentId} is not a review comment on this PR. Take the id from an ` +\n `[PR review comment rc-<id> …] message in this conversation; do not guess ids.`,\n { cause: err },\n );\n }\n throw err;\n }\n }\n\n async getJobLog(conversationId: string, jobId: number): Promise<string> {\n if (!Number.isInteger(jobId) || jobId <= 0) {\n throw new Error(\n \"job_id must be a positive Actions job id taken from a [job …] entry in the github_checks summary.\",\n );\n }\n const ref = parseGithubConversationId(conversationId);\n let logText: string;\n try {\n logText = await githubRetry(() => this.client.getJobLog(ref.owner, ref.repo, jobId));\n } catch (err) {\n if (err instanceof GithubApiError && err.status === 404) {\n throw new Error(\n `No GitHub Actions log for job ${jobId}. Logs are only available for checks reported ` +\n `by github-actions; external CI keeps logs on its own service — ` +\n `use that check's summary/url from github_checks, or reproduce the failure locally ` +\n `in ./repo instead. Do not retry with other ids.`,\n { cause: err },\n );\n }\n throw err;\n }\n return logText.length > MAX_LOG_CHARS\n ? `…(truncated to the last ${MAX_LOG_CHARS} chars)\\n${logText.slice(-MAX_LOG_CHARS)}`\n : logText;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"github-ops.js","sourceRoot":"","sources":["../../../src/adapters/github/github-ops.ts"],"names":[],"mappings":"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","sourcesContent":["import * as log from \"../../log.js\";\nimport { GithubApiError, GITHUB_MAX_COMMENT_LENGTH, githubRetry } from \"./client.js\";\nimport { parseGithubConversationId } from \"../../office/index.js\";\nimport type {\n GithubApi,\n GithubCheckSummary,\n GithubIssueRequest,\n GithubPrRequest,\n GithubPrResult,\n GithubReadRequest,\n GithubReadResult,\n PlatformGithubOps,\n} from \"./types.js\";\n\nconst MAX_LOG_CHARS = 20000;\n\nexport class GithubOps implements PlatformGithubOps {\n constructor(private readonly client: GithubApi) {}\n\n async createPullRequest(\n conversationId: string,\n request: GithubPrRequest,\n ): Promise<GithubPrResult> {\n const ref = parseGithubConversationId(conversationId);\n const repository = await githubRetry(() => this.client.getRepository(ref.owner, ref.repo));\n const base = request.base ?? repository.default_branch;\n try {\n const pr = await githubRetry(() =>\n this.client.createPullRequest(ref.owner, ref.repo, {\n title: request.title,\n head: request.branch,\n base,\n body: request.body,\n draft: request.draft,\n }),\n );\n log.logInfo(`[${conversationId}] Opened PR #${pr.number}: ${pr.html_url}`);\n return { number: pr.number, url: pr.html_url };\n } catch (err) {\n if (\n err instanceof GithubApiError &&\n err.status === 422 &&\n /already exists/i.test(err.message)\n ) {\n const existing = await this.client.findOpenPullRequestByBranch(\n ref.owner,\n ref.repo,\n request.branch,\n );\n if (existing) {\n log.logInfo(\n `[${conversationId}] Branch already has PR #${existing.number}: ${existing.html_url}`,\n );\n return { number: existing.number, url: existing.html_url, updatedExisting: true };\n }\n }\n throw err;\n }\n }\n\n async getChecks(conversationId: string, branch?: string): Promise<GithubCheckSummary[]> {\n const ref = parseGithubConversationId(conversationId);\n let target = branch;\n if (!target) {\n let pr;\n try {\n pr = await githubRetry(() => this.client.getPullRequest(ref.owner, ref.repo, ref.number));\n } catch {\n pr = null;\n }\n if (!pr?.head) {\n throw new Error(\n \"This conversation is not a pull request — pass the branch whose checks you want.\",\n );\n }\n target = pr.head.sha;\n }\n const status = await githubRetry(() =>\n this.client.getCombinedStatus(ref.owner, ref.repo, target),\n );\n const runs = await githubRetry(() =>\n this.client.listWorkflowRuns(ref.owner, ref.repo, status.sha),\n );\n const jobs = await Promise.all(\n runs.map(async (run) => {\n const runJobs = await githubRetry(() =>\n this.client.listWorkflowJobs(ref.owner, ref.repo, run.id),\n );\n return runJobs.map(\n (job): GithubCheckSummary => ({\n id: job.id,\n name: run.name ? `${run.name} / ${job.name}` : job.name,\n status: job.status,\n conclusion: job.conclusion,\n url: job.html_url,\n source: \"actions\",\n outputSummary: null,\n }),\n );\n }),\n );\n const statuses = status.statuses.map(\n (entry): GithubCheckSummary => ({\n id: entry.id,\n name: entry.context,\n status: entry.state === \"pending\" ? \"in_progress\" : \"completed\",\n conclusion:\n entry.state === \"pending\" ? null : entry.state === \"success\" ? \"success\" : \"failure\",\n url: entry.target_url,\n source: \"status\",\n outputSummary: entry.description?.trim() ? entry.description.slice(0, 500) : null,\n }),\n );\n return [...jobs.flat(), ...statuses];\n }\n\n async readGithub(conversationId: string, request: GithubReadRequest): Promise<GithubReadResult> {\n const ref = parseGithubConversationId(conversationId);\n const number = request.number ?? ref.number;\n switch (request.action) {\n case \"pr\": {\n const pr = await githubRetry(() => this.client.getPullRequest(ref.owner, ref.repo, number));\n return { kind: \"pr\", pr };\n }\n case \"pr_files\": {\n const files = await githubRetry(() =>\n this.client.listPullRequestFiles(ref.owner, ref.repo, number),\n );\n return { kind: \"pr_files\", files };\n }\n case \"pr_reviews\": {\n const [reviews, threads] = await Promise.all([\n githubRetry(() => this.client.listPullRequestReviews(ref.owner, ref.repo, number)),\n githubRetry(() => this.client.listPullReviewComments(ref.owner, ref.repo, number)),\n ]);\n return { kind: \"pr_reviews\", reviews, threads };\n }\n case \"issue\": {\n const issue = await githubRetry(() => this.client.getIssue(ref.owner, ref.repo, number));\n return { kind: \"issue\", issue };\n }\n case \"comments\": {\n const comments = await githubRetry(() =>\n this.client.listIssueComments(ref.owner, ref.repo, number),\n );\n return { kind: \"comments\", comments };\n }\n case \"list\": {\n const issues = await githubRetry(() =>\n this.client.listIssues(ref.owner, ref.repo, {\n state: request.state,\n labels: request.labels,\n creator: request.creator,\n }),\n );\n return { kind: \"list\", issues };\n }\n default:\n throw new Error(`Unknown github_read action: ${String(request.action)}`);\n }\n }\n\n async manageIssue(conversationId: string, request: GithubIssueRequest): Promise<string> {\n const ref = parseGithubConversationId(conversationId);\n const number = request.number ?? ref.number;\n try {\n switch (request.action) {\n case \"add_labels\": {\n const labels = request.labels;\n if (!labels?.length) {\n throw new Error(\"add_labels requires a non-empty labels array.\");\n }\n await githubRetry(() => this.client.addIssueLabels(ref.owner, ref.repo, number, labels));\n return `Added label(s) ${labels.join(\", \")} to #${number}.`;\n }\n case \"remove_label\": {\n const label = request.label;\n if (!label) {\n throw new Error(\"remove_label requires a label name.\");\n }\n await githubRetry(() => this.client.removeIssueLabel(ref.owner, ref.repo, number, label));\n return `Removed label ${label} from #${number}.`;\n }\n case \"add_assignees\": {\n const assignees = request.assignees;\n if (!assignees?.length) {\n throw new Error(\"add_assignees requires a non-empty assignees array.\");\n }\n await githubRetry(() =>\n this.client.addIssueAssignees(ref.owner, ref.repo, number, assignees),\n );\n return `Assigned ${assignees.map((login) => `@${login}`).join(\", \")} to #${number}.`;\n }\n case \"remove_assignees\": {\n const assignees = request.assignees;\n if (!assignees?.length) {\n throw new Error(\"remove_assignees requires a non-empty assignees array.\");\n }\n await githubRetry(() =>\n this.client.removeIssueAssignees(ref.owner, ref.repo, number, assignees),\n );\n return `Unassigned ${assignees.map((login) => `@${login}`).join(\", \")} from #${number}.`;\n }\n case \"close\": {\n await githubRetry(() =>\n this.client.updateIssueState(\n ref.owner,\n ref.repo,\n number,\n \"closed\",\n request.state_reason,\n ),\n );\n return `Closed #${number}${request.state_reason ? ` as ${request.state_reason}` : \"\"}.`;\n }\n case \"reopen\": {\n await githubRetry(() =>\n this.client.updateIssueState(ref.owner, ref.repo, number, \"open\"),\n );\n return `Reopened #${number}.`;\n }\n default:\n throw new Error(`Unknown github_issue action: ${String(request.action)}`);\n }\n } catch (err) {\n if (err instanceof GithubApiError && err.status === 404) {\n throw new Error(`Issue #${number} not found in ${ref.owner}/${ref.repo}.`, { cause: err });\n }\n throw err;\n }\n }\n\n async replyToReviewThread(\n conversationId: string,\n commentId: number,\n body: string,\n ): Promise<{ url: string }> {\n if (!Number.isInteger(commentId) || commentId <= 0) {\n throw new Error(\n \"comment_id must be the numeric id from an [PR review comment rc-<id> …] message.\",\n );\n }\n const ref = parseGithubConversationId(conversationId);\n const text =\n body.length > GITHUB_MAX_COMMENT_LENGTH\n ? `${body.slice(0, GITHUB_MAX_COMMENT_LENGTH)}\\n…(truncated)`\n : body;\n try {\n const reply = await githubRetry(() =>\n this.client.replyToReviewComment(ref.owner, ref.repo, ref.number, commentId, text),\n );\n return {\n url: `https://github.com/${ref.owner}/${ref.repo}/pull/${ref.number}#discussion_r${reply.id}`,\n };\n } catch (err) {\n if (err instanceof GithubApiError && err.status === 404) {\n throw new Error(\n `Comment ${commentId} is not a review comment on this PR. Take the id from an ` +\n `[PR review comment rc-<id> …] message in this conversation; do not guess ids.`,\n { cause: err },\n );\n }\n throw err;\n }\n }\n\n async getJobLog(conversationId: string, jobId: number): Promise<string> {\n if (!Number.isInteger(jobId) || jobId <= 0) {\n throw new Error(\n \"job_id must be a positive Actions job id taken from a [job …] entry in the github_checks summary.\",\n );\n }\n const ref = parseGithubConversationId(conversationId);\n let logText: string;\n try {\n logText = await githubRetry(() => this.client.getJobLog(ref.owner, ref.repo, jobId));\n } catch (err) {\n if (err instanceof GithubApiError && err.status === 404) {\n throw new Error(\n `No GitHub Actions log for job ${jobId}. Logs are only available for checks reported ` +\n `by github-actions; external CI keeps logs on its own service — ` +\n `use that check's summary/url from github_checks, or reproduce the failure locally ` +\n `in your clone instead. Do not retry with other ids.`,\n { cause: err },\n );\n }\n throw err;\n }\n return logText.length > MAX_LOG_CHARS\n ? `…(truncated to the last ${MAX_LOG_CHARS} chars)\\n${logText.slice(-MAX_LOG_CHARS)}`\n : logText;\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GithubPolicy, GithubRepoRef } from "./types.js";
|
|
2
|
+
export interface GithubPolicyEnv {
|
|
3
|
+
repos: string | undefined;
|
|
4
|
+
publicRepos: string | undefined;
|
|
5
|
+
users: string | undefined;
|
|
6
|
+
minPermission: string | undefined;
|
|
7
|
+
triggers: string | undefined;
|
|
8
|
+
capabilities: string | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseGithubPolicy(env: GithubPolicyEnv): GithubPolicy;
|
|
11
|
+
export declare function repoIsAllowed(policy: GithubPolicy, repo: GithubRepoRef & {
|
|
12
|
+
private: boolean;
|
|
13
|
+
}): boolean;
|
|
14
|
+
export declare function userIsAllowed(policy: GithubPolicy, login: string): boolean;
|
|
15
|
+
export declare function permissionMeets(policy: GithubPolicy, role: {
|
|
16
|
+
permission: string;
|
|
17
|
+
role_name?: string;
|
|
18
|
+
}): boolean;
|
|
19
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EACZ,aAAa,EAGd,MAAM,YAAY,CAAC;AAmBpB,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AA0BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,GAAG,YAAY,CA2BpE;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GACzC,OAAO,CAQT;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1E;AAMD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,OAAO,CAGT"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const GITHUB_TRIGGERS = ["mention", "assign", "review", "followup"];
|
|
2
|
+
const GITHUB_CAPABILITIES = ["triage", "push"];
|
|
3
|
+
const PERMISSION_RANK = {
|
|
4
|
+
none: 0,
|
|
5
|
+
read: 1,
|
|
6
|
+
triage: 2,
|
|
7
|
+
write: 3,
|
|
8
|
+
maintain: 4,
|
|
9
|
+
admin: 5,
|
|
10
|
+
};
|
|
11
|
+
const TRIGGER_PERMISSIONS = ["write", "maintain", "admin"];
|
|
12
|
+
const REPO_PATTERN = /^[\w.-]+\/(?:\*|[\w.-]+)$/;
|
|
13
|
+
function splitList(value) {
|
|
14
|
+
return (value ?? "")
|
|
15
|
+
.split(",")
|
|
16
|
+
.map((entry) => entry.trim().toLowerCase())
|
|
17
|
+
.filter(Boolean);
|
|
18
|
+
}
|
|
19
|
+
function pickAll(name, allowed, entries) {
|
|
20
|
+
const unknown = entries.filter((entry) => !allowed.includes(entry));
|
|
21
|
+
if (unknown.length > 0) {
|
|
22
|
+
throw new Error(`${name} has unknown value(s) ${unknown.join(", ")}; use ${allowed.join(", ")}`);
|
|
23
|
+
}
|
|
24
|
+
return new Set(entries);
|
|
25
|
+
}
|
|
26
|
+
function parseBoolean(name, value) {
|
|
27
|
+
const normalized = (value ?? "false").trim().toLowerCase();
|
|
28
|
+
if (normalized === "true")
|
|
29
|
+
return true;
|
|
30
|
+
if (normalized === "false")
|
|
31
|
+
return false;
|
|
32
|
+
throw new Error(`${name} must be true or false`);
|
|
33
|
+
}
|
|
34
|
+
export function parseGithubPolicy(env) {
|
|
35
|
+
const repos = splitList(env.repos);
|
|
36
|
+
if (repos.length === 0) {
|
|
37
|
+
throw new Error("GITHUB_REPOS must list at least one owner/repo or owner/*");
|
|
38
|
+
}
|
|
39
|
+
const invalidRepos = repos.filter((entry) => !REPO_PATTERN.test(entry));
|
|
40
|
+
if (invalidRepos.length > 0) {
|
|
41
|
+
throw new Error(`GITHUB_REPOS has invalid entries ${invalidRepos.join(", ")}; use owner/repo or owner/*`);
|
|
42
|
+
}
|
|
43
|
+
const minPermission = (env.minPermission ?? "write").trim().toLowerCase();
|
|
44
|
+
if (!TRIGGER_PERMISSIONS.includes(minPermission)) {
|
|
45
|
+
throw new Error(`GITHUB_MIN_PERMISSION must be one of ${TRIGGER_PERMISSIONS.join(", ")}`);
|
|
46
|
+
}
|
|
47
|
+
const users = splitList(env.users);
|
|
48
|
+
return {
|
|
49
|
+
repos,
|
|
50
|
+
publicRepos: parseBoolean("GITHUB_PUBLIC_REPOS", env.publicRepos),
|
|
51
|
+
users: users.length > 0 ? users : null,
|
|
52
|
+
minPermission: minPermission,
|
|
53
|
+
triggers: env.triggers === undefined
|
|
54
|
+
? new Set(GITHUB_TRIGGERS)
|
|
55
|
+
: pickAll("GITHUB_TRIGGERS", GITHUB_TRIGGERS, splitList(env.triggers)),
|
|
56
|
+
capabilities: pickAll("GITHUB_CAPABILITIES", GITHUB_CAPABILITIES, splitList(env.capabilities)),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function repoIsAllowed(policy, repo) {
|
|
60
|
+
if (!repo.private && !policy.publicRepos)
|
|
61
|
+
return false;
|
|
62
|
+
const owner = repo.owner.toLowerCase();
|
|
63
|
+
const name = repo.repo.toLowerCase();
|
|
64
|
+
return policy.repos.some((entry) => {
|
|
65
|
+
const [entryOwner, entryName] = entry.split("/");
|
|
66
|
+
return entryOwner === owner && (entryName === "*" || entryName === name);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
export function userIsAllowed(policy, login) {
|
|
70
|
+
return policy.users === null || policy.users.includes(login.toLowerCase());
|
|
71
|
+
}
|
|
72
|
+
function rankOfPermission(name) {
|
|
73
|
+
return PERMISSION_RANK[name] ?? 0;
|
|
74
|
+
}
|
|
75
|
+
export function permissionMeets(policy, role) {
|
|
76
|
+
const rank = Math.max(rankOfPermission(role.role_name ?? ""), rankOfPermission(role.permission));
|
|
77
|
+
return rank >= PERMISSION_RANK[policy.minPermission];
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/adapters/github/policy.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n GithubCapability,\n GithubPolicy,\n GithubRepoRef,\n GithubTrigger,\n GithubTriggerPermission,\n} from \"./types.js\";\n\nconst GITHUB_TRIGGERS: readonly GithubTrigger[] = [\"mention\", \"assign\", \"review\", \"followup\"];\n\nconst GITHUB_CAPABILITIES: readonly GithubCapability[] = [\"triage\", \"push\"];\n\nconst PERMISSION_RANK = {\n none: 0,\n read: 1,\n triage: 2,\n write: 3,\n maintain: 4,\n admin: 5,\n};\n\nconst TRIGGER_PERMISSIONS: readonly GithubTriggerPermission[] = [\"write\", \"maintain\", \"admin\"];\n\nconst REPO_PATTERN = /^[\\w.-]+\\/(?:\\*|[\\w.-]+)$/;\n\nexport interface GithubPolicyEnv {\n repos: string | undefined;\n publicRepos: string | undefined;\n users: string | undefined;\n minPermission: string | undefined;\n triggers: string | undefined;\n capabilities: string | undefined;\n}\n\nfunction splitList(value: string | undefined): string[] {\n return (value ?? \"\")\n .split(\",\")\n .map((entry) => entry.trim().toLowerCase())\n .filter(Boolean);\n}\n\nfunction pickAll<T extends string>(name: string, allowed: readonly T[], entries: string[]): Set<T> {\n const unknown = entries.filter((entry) => !(allowed as readonly string[]).includes(entry));\n if (unknown.length > 0) {\n throw new Error(\n `${name} has unknown value(s) ${unknown.join(\", \")}; use ${allowed.join(\", \")}`,\n );\n }\n return new Set(entries as T[]);\n}\n\nfunction parseBoolean(name: string, value: string | undefined): boolean {\n const normalized = (value ?? \"false\").trim().toLowerCase();\n if (normalized === \"true\") return true;\n if (normalized === \"false\") return false;\n throw new Error(`${name} must be true or false`);\n}\n\nexport function parseGithubPolicy(env: GithubPolicyEnv): GithubPolicy {\n const repos = splitList(env.repos);\n if (repos.length === 0) {\n throw new Error(\"GITHUB_REPOS must list at least one owner/repo or owner/*\");\n }\n const invalidRepos = repos.filter((entry) => !REPO_PATTERN.test(entry));\n if (invalidRepos.length > 0) {\n throw new Error(\n `GITHUB_REPOS has invalid entries ${invalidRepos.join(\", \")}; use owner/repo or owner/*`,\n );\n }\n const minPermission = (env.minPermission ?? \"write\").trim().toLowerCase();\n if (!(TRIGGER_PERMISSIONS as readonly string[]).includes(minPermission)) {\n throw new Error(`GITHUB_MIN_PERMISSION must be one of ${TRIGGER_PERMISSIONS.join(\", \")}`);\n }\n const users = splitList(env.users);\n return {\n repos,\n publicRepos: parseBoolean(\"GITHUB_PUBLIC_REPOS\", env.publicRepos),\n users: users.length > 0 ? users : null,\n minPermission: minPermission as GithubTriggerPermission,\n triggers:\n env.triggers === undefined\n ? new Set(GITHUB_TRIGGERS)\n : pickAll(\"GITHUB_TRIGGERS\", GITHUB_TRIGGERS, splitList(env.triggers)),\n capabilities: pickAll(\"GITHUB_CAPABILITIES\", GITHUB_CAPABILITIES, splitList(env.capabilities)),\n };\n}\n\nexport function repoIsAllowed(\n policy: GithubPolicy,\n repo: GithubRepoRef & { private: boolean },\n): boolean {\n if (!repo.private && !policy.publicRepos) return false;\n const owner = repo.owner.toLowerCase();\n const name = repo.repo.toLowerCase();\n return policy.repos.some((entry) => {\n const [entryOwner, entryName] = entry.split(\"/\");\n return entryOwner === owner && (entryName === \"*\" || entryName === name);\n });\n}\n\nexport function userIsAllowed(policy: GithubPolicy, login: string): boolean {\n return policy.users === null || policy.users.includes(login.toLowerCase());\n}\n\nfunction rankOfPermission(name: string): number {\n return PERMISSION_RANK[name as keyof typeof PERMISSION_RANK] ?? 0;\n}\n\nexport function permissionMeets(\n policy: GithubPolicy,\n role: { permission: string; role_name?: string },\n): boolean {\n const rank = Math.max(rankOfPermission(role.role_name ?? \"\"), rankOfPermission(role.permission));\n return rank >= PERMISSION_RANK[policy.minPermission];\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { PlatformToolPack } from "../../harness/tools/types.js";
|
|
2
|
-
import type { PlatformGithubOps } from "./types.js";
|
|
3
|
-
export declare function createGithubToolPack(ops: PlatformGithubOps): PlatformToolPack;
|
|
2
|
+
import type { GithubCapability, PlatformGithubOps } from "./types.js";
|
|
3
|
+
export declare function createGithubToolPack(ops: PlatformGithubOps, capabilities: ReadonlySet<GithubCapability>): PlatformToolPack;
|
|
4
4
|
//# sourceMappingURL=tool-pack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-pack.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/tool-pack.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tool-pack.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/tool-pack.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,WAAW,CAAC,gBAAgB,CAAC,GAC1C,gBAAgB,CAqClB"}
|
|
@@ -3,40 +3,35 @@ import { createGithubPrTool } from "./tools/pr.js";
|
|
|
3
3
|
import { createGithubIssueTool } from "./tools/issue.js";
|
|
4
4
|
import { createGithubReadTool } from "./tools/read.js";
|
|
5
5
|
import { createGithubReviewReplyTool } from "./tools/review-reply.js";
|
|
6
|
-
|
|
7
|
-
export function createGithubToolPack(ops) {
|
|
6
|
+
export function createGithubToolPack(ops, capabilities) {
|
|
8
7
|
const { tool: githubPrTool, setGithubPrFunction } = createGithubPrTool();
|
|
9
8
|
const { tool: githubChecksTool, setGithubChecksFunction } = createGithubChecksTool();
|
|
10
9
|
const { tool: githubReviewReplyTool, setGithubReviewReplyFunction } = createGithubReviewReplyTool();
|
|
11
|
-
const { tool: githubSyncTool, setGithubSyncFunction } = createGithubSyncTool();
|
|
12
10
|
const { tool: githubReadTool, setGithubReadFunction } = createGithubReadTool();
|
|
13
11
|
const { tool: githubIssueTool, setGithubIssueFunction } = createGithubIssueTool();
|
|
14
12
|
return {
|
|
15
13
|
tools: [
|
|
16
|
-
githubPrTool,
|
|
14
|
+
...(capabilities.has("push") ? [githubPrTool] : []),
|
|
17
15
|
githubChecksTool,
|
|
18
16
|
githubReviewReplyTool,
|
|
19
|
-
githubSyncTool,
|
|
20
17
|
githubReadTool,
|
|
21
|
-
githubIssueTool,
|
|
18
|
+
...(capabilities.has("triage") ? [githubIssueTool] : []),
|
|
22
19
|
],
|
|
23
20
|
bindRun({ conversationId, platformName }) {
|
|
24
21
|
if (platformName !== "github") {
|
|
25
22
|
setGithubPrFunction(null);
|
|
26
23
|
setGithubChecksFunction(null);
|
|
27
24
|
setGithubReviewReplyFunction(null);
|
|
28
|
-
setGithubSyncFunction(null);
|
|
29
25
|
setGithubReadFunction(null);
|
|
30
26
|
setGithubIssueFunction(null);
|
|
31
27
|
return;
|
|
32
28
|
}
|
|
33
|
-
setGithubPrFunction((request) => ops.
|
|
29
|
+
setGithubPrFunction((request) => ops.createPullRequest(conversationId, request));
|
|
34
30
|
setGithubChecksFunction({
|
|
35
31
|
getChecks: (branch) => ops.getChecks(conversationId, branch),
|
|
36
32
|
getJobLog: (jobId) => ops.getJobLog(conversationId, jobId),
|
|
37
33
|
});
|
|
38
34
|
setGithubReviewReplyFunction((commentId, body) => ops.replyToReviewThread(conversationId, commentId, body));
|
|
39
|
-
setGithubSyncFunction((branch) => ops.syncRepo(conversationId, branch));
|
|
40
35
|
setGithubReadFunction((request) => ops.readGithub(conversationId, request));
|
|
41
36
|
setGithubIssueFunction((request) => ops.manageIssue(conversationId, request));
|
|
42
37
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-pack.js","sourceRoot":"","sources":["../../../src/adapters/github/tool-pack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-pack.js","sourceRoot":"","sources":["../../../src/adapters/github/tool-pack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAItE,MAAM,UAAU,oBAAoB,CAClC,GAAsB,EACtB,YAA2C;IAE3C,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,mBAAmB,EAAE,GAAG,kBAAkB,EAAE,CAAC;IACzE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,GAAG,sBAAsB,EAAE,CAAC;IACrF,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,GACjE,2BAA2B,EAAE,CAAC;IAChC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,qBAAqB,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC/E,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,sBAAsB,EAAE,GAAG,qBAAqB,EAAE,CAAC;IAElF,OAAO;QACL,KAAK,EAAE;YACL,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,gBAAgB;YAChB,qBAAqB;YACrB,cAAc;YACd,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD;QACD,OAAO,CAAC,EAAE,cAAc,EAAE,YAAY,EAAE;YACtC,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;gBAC9B,mBAAmB,CAAC,IAAI,CAAC,CAAC;gBAC1B,uBAAuB,CAAC,IAAI,CAAC,CAAC;gBAC9B,4BAA4B,CAAC,IAAI,CAAC,CAAC;gBACnC,qBAAqB,CAAC,IAAI,CAAC,CAAC;gBAC5B,sBAAsB,CAAC,IAAI,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,mBAAmB,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;YACjF,uBAAuB,CAAC;gBACtB,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;gBAC5D,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,CAAC;aAC3D,CAAC,CAAC;YACH,4BAA4B,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAC/C,GAAG,CAAC,mBAAmB,CAAC,cAAc,EAAE,SAAS,EAAE,IAAI,CAAC,CACzD,CAAC;YACF,qBAAqB,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;YAC5E,sBAAsB,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAChF,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { createGithubChecksTool } from \"./tools/checks.js\";\nimport { createGithubPrTool } from \"./tools/pr.js\";\nimport { createGithubIssueTool } from \"./tools/issue.js\";\nimport { createGithubReadTool } from \"./tools/read.js\";\nimport { createGithubReviewReplyTool } from \"./tools/review-reply.js\";\nimport type { PlatformToolPack } from \"../../harness/tools/types.js\";\nimport type { GithubCapability, PlatformGithubOps } from \"./types.js\";\n\nexport function createGithubToolPack(\n ops: PlatformGithubOps,\n capabilities: ReadonlySet<GithubCapability>,\n): PlatformToolPack {\n const { tool: githubPrTool, setGithubPrFunction } = createGithubPrTool();\n const { tool: githubChecksTool, setGithubChecksFunction } = createGithubChecksTool();\n const { tool: githubReviewReplyTool, setGithubReviewReplyFunction } =\n createGithubReviewReplyTool();\n const { tool: githubReadTool, setGithubReadFunction } = createGithubReadTool();\n const { tool: githubIssueTool, setGithubIssueFunction } = createGithubIssueTool();\n\n return {\n tools: [\n ...(capabilities.has(\"push\") ? [githubPrTool] : []),\n githubChecksTool,\n githubReviewReplyTool,\n githubReadTool,\n ...(capabilities.has(\"triage\") ? [githubIssueTool] : []),\n ],\n bindRun({ conversationId, platformName }) {\n if (platformName !== \"github\") {\n setGithubPrFunction(null);\n setGithubChecksFunction(null);\n setGithubReviewReplyFunction(null);\n setGithubReadFunction(null);\n setGithubIssueFunction(null);\n return;\n }\n setGithubPrFunction((request) => ops.createPullRequest(conversationId, request));\n setGithubChecksFunction({\n getChecks: (branch) => ops.getChecks(conversationId, branch),\n getJobLog: (jobId) => ops.getJobLog(conversationId, jobId),\n });\n setGithubReviewReplyFunction((commentId, body) =>\n ops.replyToReviewThread(conversationId, commentId, body),\n );\n setGithubReadFunction((request) => ops.readGithub(conversationId, request));\n setGithubIssueFunction((request) => ops.manageIssue(conversationId, request));\n },\n };\n}\n"]}
|