experimental-ash 0.55.3 → 0.57.0

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.
Files changed (144) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +202 -0
  3. package/dist/docs/internals/compiler-and-artifacts.md +1 -1
  4. package/dist/docs/internals/context.md +3 -3
  5. package/dist/docs/public/advanced/typescript-api.md +19 -0
  6. package/dist/docs/public/advanced/vercel-deployment.md +2 -1
  7. package/dist/docs/public/channels/github.md +145 -0
  8. package/dist/docs/public/channels/index.md +23 -2
  9. package/dist/docs/public/meta.json +1 -0
  10. package/dist/docs/public/onboarding.md +7 -5
  11. package/dist/docs/public/sandbox.md +18 -3
  12. package/dist/docs/public/subagents.mdx +7 -2
  13. package/dist/docs/public/tools.mdx +10 -2
  14. package/dist/skills/agent/SKILL.md +169 -0
  15. package/dist/skills/agent/references/deployment.md +35 -0
  16. package/dist/skills/agent/references/getting-started.md +58 -0
  17. package/dist/skills/agent/references/project-layout.md +35 -0
  18. package/dist/skills/agent/references/runtime-model.md +24 -0
  19. package/dist/skills/agent/references/skills.md +26 -0
  20. package/dist/skills/agent/scripts/add-to-existing-project.sh +12 -0
  21. package/dist/skills/agent/scripts/bootstrap-from-npm.sh +9 -0
  22. package/dist/skills/agent/scripts/verify-local-agent.sh +16 -0
  23. package/dist/skills/ash-add-agent/SKILL.md +166 -0
  24. package/dist/skills/ash-add-next/SKILL.md +137 -0
  25. package/dist/skills/framework/SKILL.md +93 -0
  26. package/dist/skills/framework/references/architecture.md +14 -0
  27. package/dist/skills/framework/references/discovery-and-compilation.md +15 -0
  28. package/dist/skills/framework/references/quality-gates.md +13 -0
  29. package/dist/skills/framework/references/runtime-model.md +12 -0
  30. package/dist/skills/framework/references/workspace-and-sandbox.md +25 -0
  31. package/dist/skills/framework/scripts/framework-review-checklist.sh +13 -0
  32. package/dist/skills/framework/scripts/run-framework-gates.sh +8 -0
  33. package/dist/src/client/output-schema.js +1 -1
  34. package/dist/src/compiler/compile-from-memory.d.ts +2 -0
  35. package/dist/src/compiler/compile-from-memory.js +1 -1
  36. package/dist/src/compiler/manifest.d.ts +10 -2
  37. package/dist/src/compiler/manifest.js +1 -1
  38. package/dist/src/compiler/normalize-agent-config.js +1 -1
  39. package/dist/src/compiler/normalize-sandbox.js +1 -1
  40. package/dist/src/compiler/normalize-subagent.js +1 -1
  41. package/dist/src/compiler/normalize-tool.js +1 -1
  42. package/dist/src/context/build-dynamic-tools.js +1 -1
  43. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  44. package/dist/src/context/keys.d.ts +1 -0
  45. package/dist/src/execution/node-step.js +1 -1
  46. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  47. package/dist/src/execution/session.js +1 -1
  48. package/dist/src/execution/subagent-tool.js +1 -1
  49. package/dist/src/execution/workflow-entry.js +1 -1
  50. package/dist/src/harness/code-mode.js +1 -1
  51. package/dist/src/harness/execute-tool.d.ts +1 -0
  52. package/dist/src/harness/provider-tools.d.ts +7 -1
  53. package/dist/src/harness/provider-tools.js +1 -1
  54. package/dist/src/harness/tool-loop.js +1 -1
  55. package/dist/src/harness/tools.d.ts +2 -0
  56. package/dist/src/harness/tools.js +1 -1
  57. package/dist/src/internal/application/package.js +1 -1
  58. package/dist/src/internal/authored-definition/sandbox.d.ts +2 -1
  59. package/dist/src/internal/authored-definition/sandbox.js +1 -1
  60. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  61. package/dist/src/packages/ash-scaffold/src/channels.js +2 -2
  62. package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +1 -1
  63. package/dist/src/packages/ash-scaffold/src/web-template.js +2 -2
  64. package/dist/src/public/channels/github/api.d.ts +166 -0
  65. package/dist/src/public/channels/github/api.js +1 -0
  66. package/dist/src/public/channels/github/auth.d.ts +83 -0
  67. package/dist/src/public/channels/github/auth.js +2 -0
  68. package/dist/src/public/channels/github/binding.d.ts +49 -0
  69. package/dist/src/public/channels/github/binding.js +1 -0
  70. package/dist/src/public/channels/github/checkout.d.ts +48 -0
  71. package/dist/src/public/channels/github/checkout.js +1 -0
  72. package/dist/src/public/channels/github/constants.d.ts +2 -0
  73. package/dist/src/public/channels/github/constants.js +1 -0
  74. package/dist/src/public/channels/github/defaults.d.ts +21 -0
  75. package/dist/src/public/channels/github/defaults.js +3 -0
  76. package/dist/src/public/channels/github/dispatch.d.ts +34 -0
  77. package/dist/src/public/channels/github/dispatch.js +1 -0
  78. package/dist/src/public/channels/github/githubChannel.d.ts +109 -0
  79. package/dist/src/public/channels/github/githubChannel.js +1 -0
  80. package/dist/src/public/channels/github/inbound.d.ts +183 -0
  81. package/dist/src/public/channels/github/inbound.js +2 -0
  82. package/dist/src/public/channels/github/index.d.ts +9 -0
  83. package/dist/src/public/channels/github/index.js +1 -0
  84. package/dist/src/public/channels/github/limits.d.ts +4 -0
  85. package/dist/src/public/channels/github/limits.js +2 -0
  86. package/dist/src/public/channels/github/pr-context.d.ts +45 -0
  87. package/dist/src/public/channels/github/pr-context.js +5 -0
  88. package/dist/src/public/channels/github/state.d.ts +48 -0
  89. package/dist/src/public/channels/github/state.js +1 -0
  90. package/dist/src/public/channels/github/verify.d.ts +35 -0
  91. package/dist/src/public/channels/github/verify.js +1 -0
  92. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  93. package/dist/src/public/definitions/sandbox.d.ts +3 -3
  94. package/dist/src/public/definitions/tool.d.ts +21 -1
  95. package/dist/src/public/sandbox/index.d.ts +1 -1
  96. package/dist/src/public/tools/define-bash-tool.js +1 -1
  97. package/dist/src/public/tools/define-glob-tool.js +1 -1
  98. package/dist/src/public/tools/define-grep-tool.js +1 -1
  99. package/dist/src/public/tools/define-read-file-tool.js +1 -1
  100. package/dist/src/public/tools/define-write-file-tool.js +1 -1
  101. package/dist/src/public/tools/internal.js +1 -1
  102. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  103. package/dist/src/runtime/connections/authorization-tokens.d.ts +8 -0
  104. package/dist/src/runtime/connections/authorization-tokens.js +1 -1
  105. package/dist/src/runtime/connections/mcp-client.d.ts +14 -0
  106. package/dist/src/runtime/connections/mcp-client.js +1 -1
  107. package/dist/src/runtime/connections/types.d.ts +1 -0
  108. package/dist/src/runtime/framework-tools/ask-question.d.ts +4 -0
  109. package/dist/src/runtime/framework-tools/ask-question.js +1 -1
  110. package/dist/src/runtime/framework-tools/bash.d.ts +5 -0
  111. package/dist/src/runtime/framework-tools/bash.js +1 -1
  112. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +1 -0
  113. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  114. package/dist/src/runtime/framework-tools/final-output.js +1 -1
  115. package/dist/src/runtime/framework-tools/glob.d.ts +5 -0
  116. package/dist/src/runtime/framework-tools/glob.js +2 -2
  117. package/dist/src/runtime/framework-tools/grep.d.ts +5 -0
  118. package/dist/src/runtime/framework-tools/grep.js +2 -2
  119. package/dist/src/runtime/framework-tools/read-file.d.ts +5 -0
  120. package/dist/src/runtime/framework-tools/read-file.js +2 -2
  121. package/dist/src/runtime/framework-tools/skill.d.ts +2 -0
  122. package/dist/src/runtime/framework-tools/skill.js +1 -1
  123. package/dist/src/runtime/framework-tools/todo.d.ts +2 -0
  124. package/dist/src/runtime/framework-tools/todo.js +2 -2
  125. package/dist/src/runtime/framework-tools/web-fetch.d.ts +3 -0
  126. package/dist/src/runtime/framework-tools/web-fetch.js +2 -2
  127. package/dist/src/runtime/framework-tools/web-search.d.ts +17 -0
  128. package/dist/src/runtime/framework-tools/web-search.js +1 -1
  129. package/dist/src/runtime/framework-tools/write-file.d.ts +5 -0
  130. package/dist/src/runtime/framework-tools/write-file.js +2 -2
  131. package/dist/src/runtime/resolve-sandbox.js +1 -1
  132. package/dist/src/runtime/resolve-tool.js +1 -1
  133. package/dist/src/runtime/sandbox/keys.js +1 -1
  134. package/dist/src/runtime/sandbox/template-plan.d.ts +5 -0
  135. package/dist/src/runtime/sandbox/template-plan.js +1 -1
  136. package/dist/src/runtime/subagents/registry.js +1 -1
  137. package/dist/src/runtime/tools/registry.js +1 -1
  138. package/dist/src/runtime/types.d.ts +11 -2
  139. package/dist/src/shared/dynamic-tool-definition.d.ts +2 -1
  140. package/dist/src/shared/json-schema.d.ts +3 -1
  141. package/dist/src/shared/json-schema.js +1 -1
  142. package/dist/src/shared/sandbox-definition.d.ts +22 -2
  143. package/dist/src/shared/tool-definition.d.ts +10 -2
  144. package/package.json +25 -1
@@ -0,0 +1,83 @@
1
+ import type { GitHubWebhookVerifier } from "#public/channels/github/verify.js";
2
+ /** GitHub App id, supplied directly or resolved lazily from a secret manager. */
3
+ export type GitHubAppId = number | string | (() => number | string | Promise<number | string>);
4
+ /** GitHub App private key, supplied directly or resolved lazily from a secret manager. */
5
+ export type GitHubPrivateKey = string | (() => string | Promise<string>);
6
+ /** GitHub webhook secret, supplied directly or resolved lazily from a secret manager. */
7
+ export type GitHubWebhookSecret = string | (() => string | Promise<string>);
8
+ /**
9
+ * Pre-resolved GitHub installation access token, supplied directly or
10
+ * resolved lazily from a secret manager. When present, ash skips the
11
+ * native `appId`/`privateKey`/`installationId` JWT-minting path entirely.
12
+ * Typically populated by integrations (e.g. Connect) that derive the
13
+ * installation token out-of-band.
14
+ */
15
+ export type GitHubInstallationToken = string | (() => string | Promise<string>);
16
+ /** Credentials used by the native GitHub channel. */
17
+ export interface GitHubChannelCredentials {
18
+ readonly appId?: GitHubAppId;
19
+ readonly privateKey?: GitHubPrivateKey;
20
+ readonly webhookSecret?: GitHubWebhookSecret;
21
+ /**
22
+ * Pre-resolved GitHub installation access token. When supplied, ash uses
23
+ * it directly for authenticated GitHub API calls and skips the native
24
+ * `appId`/`privateKey` JWT exchange — `installationId` is not required.
25
+ * Typically populated by integrations (e.g. Connect) that derive the
26
+ * token out-of-band.
27
+ */
28
+ readonly installationToken?: GitHubInstallationToken;
29
+ /**
30
+ * Custom inbound webhook verifier. When supplied, ash skips the
31
+ * `GITHUB_WEBHOOK_SECRET` fallback and delegates verification to this
32
+ * function. Typically populated by integrations (e.g. Connect) that
33
+ * authenticate webhooks out-of-band.
34
+ */
35
+ readonly webhookVerifier?: GitHubWebhookVerifier;
36
+ }
37
+ /** Options needed by GitHub App auth helpers. */
38
+ export interface GitHubAuthApiOptions {
39
+ readonly apiBaseUrl?: string;
40
+ readonly fetch?: typeof fetch;
41
+ }
42
+ /** Resolves a GitHub App id, falling back to `GITHUB_APP_ID`. */
43
+ export declare function resolveGitHubAppId(appId?: GitHubAppId): Promise<string>;
44
+ /** Resolves and normalizes a GitHub App private key. */
45
+ export declare function resolveGitHubPrivateKey(privateKey?: GitHubPrivateKey): Promise<string>;
46
+ /** Resolves a GitHub webhook secret, falling back to `GITHUB_WEBHOOK_SECRET`. */
47
+ export declare function resolveGitHubWebhookSecret(webhookSecret?: GitHubWebhookSecret): Promise<string>;
48
+ /** Converts hosted-platform escaped newlines back into PEM newlines. */
49
+ export declare function normalizeGitHubPrivateKey(privateKey: string): string;
50
+ /** Creates a short-lived RS256 GitHub App JWT. */
51
+ export declare function createGitHubAppJwt(input: {
52
+ readonly appId?: GitHubAppId;
53
+ readonly now?: Date;
54
+ readonly privateKey?: GitHubPrivateKey;
55
+ }): Promise<string>;
56
+ /**
57
+ * Resolves an installation access token by minting and caching a GitHub App
58
+ * installation token in process memory.
59
+ */
60
+ export declare function resolveGitHubInstallationToken(input: {
61
+ readonly api?: GitHubAuthApiOptions;
62
+ readonly credentials?: GitHubChannelCredentials;
63
+ readonly installationId: number | undefined;
64
+ }): Promise<string>;
65
+ /**
66
+ * Exchanges a GitHub App JWT for an installation access token, cached until
67
+ * shortly before GitHub's reported expiry.
68
+ */
69
+ export declare function createGitHubInstallationToken(input: {
70
+ readonly api?: GitHubAuthApiOptions;
71
+ readonly appId?: GitHubAppId;
72
+ readonly installationId: number;
73
+ readonly privateKey?: GitHubPrivateKey;
74
+ }): Promise<string>;
75
+ /** Clears the in-memory GitHub installation token cache. Intended for tests. */
76
+ export declare function clearGitHubInstallationTokenCache(): void;
77
+ /** Seeds the in-memory installation token cache. Intended for tests. */
78
+ export declare function seedGitHubInstallationTokenForTests(input: {
79
+ readonly apiBaseUrl?: string;
80
+ readonly appId?: string;
81
+ readonly installationId: number;
82
+ readonly token: string;
83
+ }): void;
@@ -0,0 +1,2 @@
1
+ import{isObject}from"#shared/guards.js";import{createSign}from"node:crypto";const installationTokenCache=new Map;async function resolveGitHubAppId(e){let t=e??process.env.GITHUB_APP_ID;if(t===void 0||t===``)throw Error(`githubChannel: GITHUB_APP_ID is required.`);let n=typeof t==`function`?await t():t;return String(n)}async function resolveGitHubPrivateKey(e){let t=e??process.env.GITHUB_APP_PRIVATE_KEY;if(!t)throw Error(`githubChannel: GITHUB_APP_PRIVATE_KEY is required.`);return normalizeGitHubPrivateKey(typeof t==`function`?await t():t)}async function resolveGitHubWebhookSecret(e){let t=e??process.env.GITHUB_WEBHOOK_SECRET;if(!t)throw Error(`githubChannel: GITHUB_WEBHOOK_SECRET is required.`);return typeof t==`function`?await t():t}function normalizeGitHubPrivateKey(e){return e.replace(/\\n/gu,`
2
+ `)}async function createGitHubAppJwt(e){let n=await resolveGitHubAppId(e.appId),r=await resolveGitHubPrivateKey(e.privateKey),i=Math.floor((e.now?.getTime()??Date.now())/1e3),a={alg:`RS256`,typ:`JWT`},o={exp:i+600,iat:i-60,iss:n},s=`${base64UrlJson(a)}.${base64UrlJson(o)}`;return`${s}.${createSign(`RSA-SHA256`).update(s).sign(r,`base64url`)}`}async function resolveGitHubInstallationToken(e){let t=e.credentials?.installationToken;if(t!==void 0)return typeof t==`function`?await t():t;if(e.installationId===void 0)throw Error(`githubChannel: installationId is required for authenticated GitHub API calls.`);return createGitHubInstallationToken({api:e.api,appId:e.credentials?.appId,installationId:e.installationId,privateKey:e.credentials?.privateKey})}async function createGitHubInstallationToken(t){let r=await resolveGitHubAppId(t.appId),i=t.api?.apiBaseUrl??`https://api.github.com`,a=`${i}:${r}:${t.installationId}`,o=installationTokenCache.get(a);if(o!==void 0&&Date.now()<o.expiresAtMs-6e4)return o.token;let s=await createGitHubAppJwt({appId:r,privateKey:t.privateKey}),c=await(t.api?.fetch??fetch)(`${i}/app/installations/${t.installationId}/access_tokens`,{headers:{accept:`application/vnd.github+json`,authorization:`Bearer ${s}`,"x-github-api-version":`2022-11-28`},method:`POST`}),l=await parseJsonBody(c);if(!c.ok)throw Error(`githubChannel: create installation token failed with HTTP ${c.status}.`);if(!isObject(l)||typeof l.token!=`string`)throw Error(`githubChannel: installation token response did not include a token.`);let u=parseExpiryMs(l.expires_at);return installationTokenCache.set(a,{expiresAtMs:u,token:l.token}),l.token}function clearGitHubInstallationTokenCache(){installationTokenCache.clear()}function seedGitHubInstallationTokenForTests(e){let t=e.apiBaseUrl??`https://api.github.com`,r=e.appId??`test-app`;installationTokenCache.set(`${t}:${r}:${e.installationId}`,{expiresAtMs:Date.now()+3600*1e3,token:e.token})}function base64UrlJson(e){return Buffer.from(JSON.stringify(e)).toString(`base64url`)}async function parseJsonBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}function parseExpiryMs(e){if(typeof e==`string`){let t=Date.parse(e);if(Number.isFinite(t))return t}return Date.now()+3600*1e3}export{clearGitHubInstallationTokenCache,createGitHubAppJwt,createGitHubInstallationToken,normalizeGitHubPrivateKey,resolveGitHubAppId,resolveGitHubInstallationToken,resolveGitHubPrivateKey,resolveGitHubWebhookSecret,seedGitHubInstallationTokenForTests};
@@ -0,0 +1,49 @@
1
+ import { type GitHubApiMethod, type GitHubApiOptions, type GitHubApiResponse, type GitHubJsonObject, type GitHubPostedComment, type GitHubReactionContent } from "#public/channels/github/api.js";
2
+ import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
3
+ import type { GitHubConversationKind, GitHubRepositoryRef } from "#public/channels/github/inbound.js";
4
+ /** Minimal config needed to rebuild GitHub API handles. */
5
+ export interface GitHubBindingConfig {
6
+ readonly api?: GitHubApiOptions;
7
+ readonly credentials?: GitHubChannelCredentials;
8
+ }
9
+ /** Serializable state fields needed to rebuild GitHub API handles. */
10
+ export interface GitHubBindingState {
11
+ readonly conversationKind: GitHubConversationKind;
12
+ readonly installationId: number | null;
13
+ readonly issueNumber: number | null;
14
+ readonly owner: string;
15
+ readonly pullRequestNumber: number | null;
16
+ readonly repo: string;
17
+ readonly repositoryId: number;
18
+ readonly reviewCommentId: number | null;
19
+ readonly reviewThreadRootCommentId: number | null;
20
+ readonly triggeringCommentId: number | null;
21
+ }
22
+ /** GitHub operations exposed to hooks and events. */
23
+ export interface GitHubHandle {
24
+ readonly installationId: number | undefined;
25
+ readonly repository: GitHubRepositoryRef;
26
+ /**
27
+ * Calls an arbitrary GitHub REST path with installation-token auth. Use this
28
+ * for any GitHub operation the channel does not wrap natively.
29
+ */
30
+ request<T = unknown>(input: {
31
+ readonly body?: GitHubJsonObject;
32
+ readonly method: GitHubApiMethod;
33
+ readonly path: string;
34
+ }): Promise<GitHubApiResponse<T>>;
35
+ }
36
+ /** Thread-scoped operations for the current GitHub conversation. */
37
+ export interface GitHubThread {
38
+ readonly kind: GitHubConversationKind;
39
+ post(message: string): Promise<GitHubPostedComment>;
40
+ react(content: GitHubReactionContent): Promise<void>;
41
+ }
42
+ /** Rebuilds GitHub API and thread handles from durable channel state. */
43
+ export declare function buildGitHubBinding(input: {
44
+ readonly config: GitHubBindingConfig;
45
+ readonly state: GitHubBindingState;
46
+ }): {
47
+ readonly github: GitHubHandle;
48
+ readonly thread: GitHubThread;
49
+ };
@@ -0,0 +1 @@
1
+ import{callGitHubApi,createGitHubIssueComment,createGitHubReaction,createGitHubReviewCommentReply}from"#public/channels/github/api.js";function buildGitHubBinding(n){let{config:r,state:i}=n,a={fullName:`${i.owner}/${i.repo}`,id:i.repositoryId,name:i.repo,owner:i.owner,private:!1},o=i.installationId??void 0;return{github:{installationId:o,repository:a,request(t){return callGitHubApi({api:r.api,body:t.body,credentials:r.credentials,installationId:o,method:t.method,path:t.path})}},thread:{kind:i.conversationKind,post(e){return i.conversationKind===`review_thread`?createGitHubReviewCommentReply({api:r.api,body:e,commentId:requiredStateNumber(i.reviewThreadRootCommentId??i.reviewCommentId,`reviewThreadRootCommentId`),credentials:r.credentials,installationId:o,owner:i.owner,pullRequestNumber:requiredStateNumber(i.pullRequestNumber,`pullRequestNumber`),repo:i.repo}):createGitHubIssueComment({api:r.api,body:e,credentials:r.credentials,installationId:o,issueNumber:requiredStateNumber(i.issueNumber??i.pullRequestNumber,`issueNumber`),owner:i.owner,repo:i.repo})},async react(e){let t=i.conversationKind===`review_thread`?i.reviewCommentId:i.triggeringCommentId;t!==null&&await createGitHubReaction({api:r.api,commentId:t,content:e,credentials:r.credentials,installationId:o,owner:i.owner,repo:i.repo,subject:i.conversationKind===`review_thread`?`pull_request_review_comment`:`issue_comment`})}}}}function requiredStateNumber(e,t){if(typeof e==`number`&&Number.isFinite(e))return e;throw Error(`githubChannel: missing ${t}.`)}export{buildGitHubBinding};
@@ -0,0 +1,48 @@
1
+ import { type GitHubApiOptions } from "#public/channels/github/api.js";
2
+ import { type GitHubChannelCredentials } from "#public/channels/github/auth.js";
3
+ import type { SandboxSession } from "#shared/sandbox-session.js";
4
+ /** Options for cloning a GitHub repository ref into the active sandbox. */
5
+ export interface GitHubCheckoutOptions {
6
+ readonly depth?: number;
7
+ readonly includeBase?: boolean;
8
+ readonly mode?: "full" | "shallow";
9
+ readonly path?: string;
10
+ readonly ref?: string;
11
+ }
12
+ /** Result returned after a GitHub checkout completes. */
13
+ export interface GitHubCheckout {
14
+ readonly baseRef: string | null;
15
+ readonly path: string;
16
+ readonly ref: string;
17
+ readonly sha: string;
18
+ }
19
+ /** Internal descriptor used by channel-owned checkout paths. */
20
+ export interface GitHubCheckoutInput extends GitHubCheckoutOptions {
21
+ readonly api?: GitHubApiOptions;
22
+ readonly baseRef?: string | null;
23
+ readonly baseSha?: string | null;
24
+ readonly credentials?: GitHubChannelCredentials;
25
+ readonly defaultBranch?: string | null;
26
+ readonly headRef?: string | null;
27
+ readonly headSha?: string | null;
28
+ readonly installationId?: number | null;
29
+ readonly owner?: string;
30
+ readonly pullRequestNumber?: number | null;
31
+ readonly repo?: string;
32
+ }
33
+ /**
34
+ * Clones a described GitHub repository ref into the given sandbox.
35
+ *
36
+ * Runs on every turn via the channel's `turn.started` handler, which resolves
37
+ * the session sandbox from its `ctx` and passes it in. The sandbox persists for
38
+ * the session, so when the workspace is already at the target commit this is a
39
+ * no-op probe — no token is minted and nothing is fetched.
40
+ *
41
+ * The installation token is brokered at the sandbox firewall
42
+ * (`sandbox.setNetworkPolicy`) rather than embedded in the remote URL, so it
43
+ * never enters the sandbox process. Requires a firewall-capable backend; the
44
+ * local backend rejects `setNetworkPolicy`.
45
+ *
46
+ * Channel-internal; not part of the public GitHub channel API.
47
+ */
48
+ export declare function checkoutGitHubRepository(sandbox: SandboxSession, input: GitHubCheckoutInput): Promise<GitHubCheckout>;
@@ -0,0 +1 @@
1
+ import{resolveGitHubInstallationToken}from"#public/channels/github/auth.js";import{getGitHubPullRequest,getGitHubRepository}from"#public/channels/github/api.js";async function checkoutGitHubRepository(t,n){let r=await resolveCheckoutDescriptor(n),i=t.resolvePath(n.path??`/workspace`),a=resolveCheckoutRef(n.ref,r);if(isFullSha(a)){let e=await readCheckoutHead(t,i);if(e===a)return{baseRef:r.baseRef,path:i,ref:a,sha:e}}let o=normalizeCheckoutDepth(n.depth),s=n.mode===`full`?``:` --depth ${o}`,c=await resolveGitHubInstallationToken({api:n.api,credentials:n.credentials,installationId:r.installationId}),l=publicRemoteUrl({owner:r.owner,repo:r.repo}),u=isFullSha(a)?a:`FETCH_HEAD`;await t.setNetworkPolicy(buildBrokerNetworkPolicy(c)),await runCheckoutCommand({command:`mkdir -p ${shellQuote(i)}`,label:`create checkout directory`,sandbox:t}),await runCheckoutCommand({command:`cd ${shellQuote(i)} && git init`,label:`initialize git repository`,sandbox:t}),await runCheckoutCommand({command:`cd ${shellQuote(i)} && git remote remove origin >/dev/null 2>&1 || true`,label:`reset git remote`,sandbox:t}),await runCheckoutCommand({command:`cd ${shellQuote(i)} && git remote add origin ${shellQuote(l)}`,label:`configure git remote`,sandbox:t}),await runCheckoutCommand({command:`cd ${shellQuote(i)} && GIT_TERMINAL_PROMPT=0 git fetch${s} origin ${shellQuote(a)}`,label:`fetch GitHub ref`,sandbox:t}),await runCheckoutCommand({command:`cd ${shellQuote(i)} && git checkout --detach ${shellQuote(u)}`,label:`checkout GitHub ref`,sandbox:t}),n.includeBase===!0&&r.baseSha!==null&&await runCheckoutCommand({command:`cd ${shellQuote(i)} && GIT_TERMINAL_PROMPT=0 git fetch${s} origin ${shellQuote(r.baseSha)}`,label:`fetch GitHub base ref`,sandbox:t});let d=(await runCheckoutCommand({command:`cd ${shellQuote(i)} && git rev-parse HEAD`,label:`resolve checked out commit`,sandbox:t})).stdout.trim()||r.headSha||a;return{baseRef:r.baseRef,path:i,ref:a,sha:d}}async function resolveCheckoutDescriptor(e){let n=readNonEmptyString(e.owner),r=readNonEmptyString(e.repo);if(n===void 0||r===void 0)throw Error(`GitHub checkout requires a repository owner and name.`);if(e.installationId===void 0||e.installationId===null)throw Error(`GitHub checkout requires a GitHub App installation id.`);let i=e.pullRequestNumber??null,a=readNonEmptyString(e.ref),o=null;i!==null&&(a===void 0&&((e.headSha===void 0||e.headSha===null)&&(e.headRef===void 0||e.headRef===null)||e.defaultBranch===void 0||e.defaultBranch===null)||e.includeBase===!0&&(e.baseSha===void 0||e.baseSha===null)||e.includeBase===!0&&(e.baseRef===void 0||e.baseRef===null))&&(o=await getGitHubPullRequest({api:e.api,credentials:e.credentials,installationId:e.installationId,owner:n,pullRequestNumber:i,repo:r}));let s=readNonEmptyString(e.defaultBranch)??o?.defaultBranch??await resolveRepositoryDefaultBranch(e,{owner:n,pullRequestNumber:i,repo:r});return{baseRef:e.baseRef??o?.base.ref??null,baseSha:e.baseSha??o?.base.sha??null,defaultBranch:s,headRef:e.headRef??o?.head.ref??null,headSha:e.headSha??o?.head.sha??null,installationId:e.installationId,owner:n,pullRequestNumber:i,repo:r}}async function resolveRepositoryDefaultBranch(e,t){return t.pullRequestNumber!==null||readNonEmptyString(e.ref)!==void 0||readNonEmptyString(e.headSha)!==void 0||readNonEmptyString(e.headRef)!==void 0?null:(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:e.installationId??void 0,owner:t.owner,repo:t.repo})).defaultBranch??null}function resolveCheckoutRef(e,t){if(e!==void 0&&e.trim().length>0)return e.trim();if(t.headSha!==null)return t.headSha;if(t.pullRequestNumber!==null)return`refs/pull/${t.pullRequestNumber}/head`;if(t.headRef!==null)return t.headRef;if(t.defaultBranch!==null)return t.defaultBranch;throw Error(`GitHub checkout could not resolve a ref to fetch.`)}async function readCheckoutHead(e,t){let n=await e.run({command:`cd ${shellQuote(t)} && git rev-parse HEAD 2>/dev/null`});if(n.exitCode!==0)return null;let r=String(n.stdout??``).trim();return isFullSha(r)?r:null}async function runCheckoutCommand(e){let t=await e.sandbox.run({command:e.command}),n=String(t.stderr??``),r=String(t.stdout??``);if(t.exitCode===0)return{stderr:n,stdout:r};throw Error([`GitHub checkout failed during ${e.label} (exit ${t.exitCode}).`,n?`stderr: ${n}`:void 0,r?`stdout: ${r}`:void 0,`Verify the GitHub App installation has access to this repository.`].filter(e=>e!==void 0).join(` `))}function normalizeCheckoutDepth(e){if(e===void 0)return 1;if(!Number.isFinite(e)||e<1)throw Error(`GitHub checkout depth must be a positive number.`);return Math.floor(e)}function publicRemoteUrl(e){return`https://github.com/${e.owner}/${e.repo}.git`}function buildBrokerNetworkPolicy(e){let t=[{transform:[{headers:{Authorization:`Basic ${Buffer.from(`x-access-token:${e}`).toString(`base64`)}`}}]}];return{allow:{"github.com":t,"codeload.github.com":t,"*":[]}}}function readNonEmptyString(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}function isFullSha(e){return/^[a-f0-9]{40}$/iu.test(e)}function shellQuote(e){return`'${e.replace(/'/gu,`'\\''`)}'`}export{checkoutGitHubRepository};
@@ -0,0 +1,2 @@
1
+ /** Default route mounted by {@link githubChannel}. */
2
+ export declare const GITHUB_CHANNEL_DEFAULT_ROUTE = "/ash/v1/github";
@@ -0,0 +1 @@
1
+ const GITHUB_CHANNEL_DEFAULT_ROUTE=`/ash/v1/github`;export{GITHUB_CHANNEL_DEFAULT_ROUTE};
@@ -0,0 +1,21 @@
1
+ import type { SessionAuthContext } from "#channel/types.js";
2
+ import type { GitHubApiOptions } from "#public/channels/github/api.js";
3
+ import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
4
+ import { type GitHubComment } from "#public/channels/github/inbound.js";
5
+ import type { GitHubChannelEvents, GitHubInboundContext, GitHubInboundResult, GitHubProgressConfig } from "#public/channels/github/githubChannel.js";
6
+ /** Projects a GitHub webhook actor into Ash session auth. */
7
+ export declare function defaultGitHubAuth(ctx: GitHubInboundContext): SessionAuthContext;
8
+ /** Options used by the built-in GitHub comment dispatch hook. */
9
+ export interface GitHubDefaultDispatchOptions {
10
+ readonly botName?: string;
11
+ }
12
+ /** Default comment hook: dispatch only when the comment `@mention`s the bot. */
13
+ export declare function defaultOnComment(ctx: GitHubInboundContext, comment: GitHubComment, options: GitHubDefaultDispatchOptions): GitHubInboundResult;
14
+ /** Options used by built-in GitHub event handlers. */
15
+ export interface GitHubDefaultEventOptions {
16
+ readonly api?: GitHubApiOptions;
17
+ readonly credentials?: GitHubChannelCredentials;
18
+ readonly progress?: GitHubProgressConfig;
19
+ }
20
+ /** Builds GitHub's built-in event handlers for acknowledgement and terminal output. */
21
+ export declare function createDefaultEvents(options?: GitHubDefaultEventOptions): GitHubChannelEvents;
@@ -0,0 +1,3 @@
1
+ import{createLogger,extractErrorId,formatErrorHint,logError}from"#internal/logging.js";import{checkoutGitHubRepository}from"#public/channels/github/checkout.js";import{shouldDispatchGitHubComment}from"#public/channels/github/inbound.js";import{splitGitHubCommentBody}from"#public/channels/github/limits.js";const log=createLogger(`github.defaults`);function defaultGitHubAuth(e){let{sender:t}=e;return{attributes:{conversation_kind:e.conversation.kind,delivery_id:e.delivery.id,installation_id:String(e.github.installationId??``),issue_number:String(e.conversation.issueNumber??``),pull_request_number:String(e.conversation.pullRequestNumber??``),repository:e.repository.fullName,repository_id:String(e.repository.id),user_login:t.login,user_type:t.type},authenticator:`github-webhook`,issuer:`github:${e.repository.owner}`,principalId:`github:${t.id}`,principalType:t.type===`Bot`?`service`:`user`,subject:t.login}}function defaultOnComment(e,t,n){return shouldDispatchGitHubComment({author:t.author,body:t.body,botName:n.botName})?{auth:defaultGitHubAuth(e)}:null}function createDefaultEvents(e={}){return{async"turn.started"(t,n,i){if(e.progress?.reactions!==!1)try{await n.thread.react(`eyes`)}catch(e){logError(log,`GitHub reaction failed — swallowed`,e)}await checkoutRepositoryForTurn(n,i,e)},async"message.completed"(e,t,n){e.finishReason===`tool-calls`||!e.message||await postCommentChunks(t,e.message)},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await postFailure(r,[`This session could not recover from an error${i}.`,``,`Start a new comment to continue.`,...a?[``,`Error id: ${a}`]:[]].join(`
2
+ `))},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await postFailure(r,[`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`Error id: ${o}`]:[]].join(`
3
+ `))}}}async function checkoutRepositoryForTurn(e,t,n){let{state:a}=e;try{let e=await checkoutGitHubRepository(await t.getSandbox(),{api:n.api,baseRef:a.baseRef,baseSha:a.baseSha,credentials:n.credentials,defaultBranch:a.defaultBranch,headRef:a.headRef,headSha:a.headSha,includeBase:a.pullRequestNumber!==null,installationId:a.installationId,owner:a.owner,pullRequestNumber:a.pullRequestNumber,repo:a.repo});a.checkoutPath=e.path,a.headSha=e.sha,a.baseRef=e.baseRef}catch(e){logError(log,`GitHub checkout failed — swallowed`,e)}}async function postCommentChunks(e,t){for(let n of splitGitHubCommentBody(t))await e.thread.post(n)}async function postFailure(e,t){await postCommentChunks(e,t)}export{createDefaultEvents,defaultGitHubAuth,defaultOnComment};
@@ -0,0 +1,34 @@
1
+ import { type GitHubIssueCommentEvent, type GitHubIssueWebhookEvent, type GitHubPullRequestReviewCommentEvent, type GitHubPullRequestWebhookEvent } from "#public/channels/github/inbound.js";
2
+ import { type GitHubChannelState } from "#public/channels/github/state.js";
3
+ import type { GitHubChannelConfig } from "#public/channels/github/githubChannel.js";
4
+ import type { SendFn } from "#public/definitions/defineChannel.js";
5
+ /** Dispatches a bot-directed issue or PR timeline comment into the runtime. */
6
+ export declare function dispatchIssueComment(input: {
7
+ readonly botName: string | undefined;
8
+ readonly config: GitHubChannelConfig;
9
+ readonly event: GitHubIssueCommentEvent;
10
+ readonly handler: NonNullable<GitHubChannelConfig["onComment"]>;
11
+ readonly send: SendFn<GitHubChannelState>;
12
+ }): Promise<void>;
13
+ /** Dispatches a bot-directed inline pull-request review comment. */
14
+ export declare function dispatchPullRequestReviewComment(input: {
15
+ readonly botName: string | undefined;
16
+ readonly config: GitHubChannelConfig;
17
+ readonly event: GitHubPullRequestReviewCommentEvent;
18
+ readonly handler: NonNullable<GitHubChannelConfig["onComment"]>;
19
+ readonly send: SendFn<GitHubChannelState>;
20
+ }): Promise<void>;
21
+ /** Dispatches an opt-in issue webhook event into the runtime. */
22
+ export declare function dispatchIssue(input: {
23
+ readonly config: GitHubChannelConfig;
24
+ readonly event: GitHubIssueWebhookEvent;
25
+ readonly handler: NonNullable<GitHubChannelConfig["onIssue"]>;
26
+ readonly send: SendFn<GitHubChannelState>;
27
+ }): Promise<void>;
28
+ /** Dispatches an opt-in pull-request webhook event into the runtime. */
29
+ export declare function dispatchPullRequest(input: {
30
+ readonly config: GitHubChannelConfig;
31
+ readonly event: GitHubPullRequestWebhookEvent;
32
+ readonly handler: NonNullable<GitHubChannelConfig["onPullRequest"]>;
33
+ readonly send: SendFn<GitHubChannelState>;
34
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ import{createLogger,logError}from"#internal/logging.js";import{extractGitHubCommentTrigger,formatGitHubContextBlock,prependGitHubContext}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{buildGitHubPullRequestContext,mergeGitHubContext}from"#public/channels/github/pr-context.js";import{continuationTokenFromState,stateFromIssueCommentEvent,stateFromIssueEvent,stateFromPullRequestEvent,stateFromPullRequestReviewCommentEvent}from"#public/channels/github/state.js";const log=createLogger(`github.dispatch`);async function dispatchIssueComment(e){if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,e.botName))return;let t=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:e.botName,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(t,toGitHubComment(e.event.comment)),config:e.config,send:e.send,state:stateFromIssueCommentEvent(e.event)})}async function dispatchPullRequestReviewComment(e){if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,e.botName))return;let t=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:e.botName,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(t,toGitHubComment(e.event.comment)),config:e.config,send:e.send,state:stateFromPullRequestReviewCommentEvent(e.event)})}async function dispatchIssue(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.issue),message:formatIssueEventMessage(e.event),send:e.send,state:stateFromIssueEvent(e.event)})}async function dispatchPullRequest(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.pullRequest),message:formatPullRequestEventMessage(e.event),send:e.send,state:stateFromPullRequestEvent(e.event)})}async function dispatchWebhookEventTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});t!=null&&await sendGitHubTurn({auth:t.auth,event:e.event,message:e.message,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),send:e.send,state:e.state})}async function dispatchCommentTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let r=extractGitHubCommentTrigger({body:e.body,botName:e.botName})?.message??e.body.trim();await sendGitHubTurn({auth:t.auth,commentUrl:e.commentUrl,event:e.event,message:r,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),send:e.send,state:e.state})}async function runInboundHandler(e){try{return await e.handlerResult()}catch(n){logError(log,`GitHub inbound handler failed`,n,{deliveryId:e.event.delivery.id});return}}async function sendGitHubTurn(e){let n=formatGitHubContextBlock({deliveryId:e.event.delivery.id,commentUrl:e.commentUrl,headSha:e.state.headSha,issueNumber:e.state.issueNumber,pullRequestNumber:e.state.pullRequestNumber,repository:e.event.repository,sender:e.event.sender}),i=prependGitHubContext(e.message,n);try{await e.send({message:i,context:e.context},{auth:e.auth,continuationToken:continuationTokenFromState(e.state),state:e.state})}catch(n){logError(log,e.logMessage??`GitHub delivery failed`,n,{deliveryId:e.event.delivery.id})}}async function buildPullRequestContext(e,n,r){try{return await buildGitHubPullRequestContext({api:e.api,config:e.pullRequestContext,credentials:e.credentials,installationId:n.installationId??void 0,owner:n.owner,pullRequestNumber:n.pullRequestNumber,repo:n.repo})}catch(e){logError(log,`GitHub pull-request context failed — swallowed`,e,{deliveryId:r});return}}function buildInboundContext(e,t){let n=buildGitHubBinding({config:e,state:t.kind===`issue_comment`?stateFromIssueCommentEvent(t):t.kind===`issues`?stateFromIssueEvent(t):t.kind===`pull_request`?stateFromPullRequestEvent(t):stateFromPullRequestReviewCommentEvent(t)});return{conversation:t.conversation,delivery:t.delivery,github:n.github,repository:t.repository,sender:t.sender,thread:n.thread}}function toGitHubComment(e){return{author:e.author,body:e.body,htmlUrl:e.htmlUrl,id:e.id,raw:e.raw,url:e.url}}function formatIssueEventMessage(e){let t=readString(e.issue.raw.title);return`Issue ${e.issue.action}: #${e.issue.issueNumber}${t?` ${t}`:``}`}function formatPullRequestEventMessage(e){let t=readString(e.pullRequest.raw.title);return`Pull request ${e.pullRequest.action}: #${e.pullRequest.pullRequestNumber}${t?` ${t}`:``}`}function isIgnoredInboundComment(e,t,n){if(e.includes(`<!-- ash:github:`)||t?.type===`Bot`)return!0;let r=n?`${n}[bot]`.toLowerCase():``;return r.length>0&&t?.login.toLowerCase()===r}function readString(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment};
@@ -0,0 +1,109 @@
1
+ import type { SessionAuthContext } from "#channel/types.js";
2
+ import type { SessionContext } from "#public/definitions/callback-context.js";
3
+ import type { ChannelSessionOps } from "#public/definitions/defineChannel.js";
4
+ import type { HandleMessageStreamEvent } from "#protocol/message.js";
5
+ import { type GitHubHandle, type GitHubThread } from "#public/channels/github/binding.js";
6
+ import { type GitHubApiOptions } from "#public/channels/github/api.js";
7
+ import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
8
+ import { type GitHubComment, type GitHubConversationRef, type GitHubDelivery, type GitHubIssueEvent, type GitHubPullRequestEvent, type GitHubRepositoryRef, type GitHubUser } from "#public/channels/github/inbound.js";
9
+ import { type GitHubChannelState } from "#public/channels/github/state.js";
10
+ import type { GitHubPullRequestContextConfig } from "#public/channels/github/pr-context.js";
11
+ import { type Channel } from "#public/definitions/defineChannel.js";
12
+ type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
13
+ type: T;
14
+ }> extends {
15
+ data: infer D;
16
+ } ? D : undefined;
17
+ /** Target accepted by `receive(github, { target })` for proactive sessions. */
18
+ export interface GitHubReceiveTarget {
19
+ readonly initialMessage?: string;
20
+ readonly installationId?: number;
21
+ readonly issueNumber?: number;
22
+ readonly owner: string;
23
+ readonly pullRequestNumber?: number;
24
+ /** Optional shortcut that avoids a repository metadata API call. */
25
+ readonly repositoryId?: number;
26
+ readonly repo: string;
27
+ }
28
+ /** Optional acknowledgement progress surfaces for GitHub conversations. */
29
+ export interface GitHubProgressConfig {
30
+ readonly reactions?: boolean;
31
+ }
32
+ /** Pre-dispatch GitHub context passed to inbound hooks. */
33
+ export interface GitHubInboundContext {
34
+ readonly conversation: GitHubConversationRef;
35
+ readonly delivery: GitHubDelivery;
36
+ readonly github: GitHubHandle;
37
+ readonly repository: GitHubRepositoryRef;
38
+ readonly sender: GitHubUser;
39
+ readonly thread: GitHubThread;
40
+ }
41
+ /** Channel-owned GitHub context rebuilt from persisted channel state. */
42
+ export interface GitHubChannelContext {
43
+ readonly conversation: GitHubConversationRef;
44
+ readonly github: GitHubHandle;
45
+ readonly repository: GitHubRepositoryRef;
46
+ readonly thread: GitHubThread;
47
+ state: GitHubChannelState;
48
+ }
49
+ /** Event-handler GitHub context, including session operations. */
50
+ export interface GitHubEventContext extends GitHubChannelContext, ChannelSessionOps {
51
+ }
52
+ /** Result of a GitHub inbound hook. Return `null` to acknowledge without dispatching. */
53
+ export type GitHubInboundResult = {
54
+ readonly auth: SessionAuthContext | null;
55
+ readonly context?: readonly string[];
56
+ } | null;
57
+ /** Sync or async {@link GitHubInboundResult}. */
58
+ export type GitHubInboundResultOrPromise = GitHubInboundResult | Promise<GitHubInboundResult>;
59
+ type GitHubEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: GitHubEventContext, ctx: SessionContext) => void | Promise<void>;
60
+ type GitHubSessionFailedHandler = (data: EventData<"session.failed">, channel: GitHubEventContext) => void | Promise<void>;
61
+ /** Event handlers supported by `githubChannel({ events })`. */
62
+ export interface GitHubChannelEvents {
63
+ readonly "action.result"?: GitHubEventHandler<"action.result">;
64
+ readonly "actions.requested"?: GitHubEventHandler<"actions.requested">;
65
+ readonly "authorization.completed"?: GitHubEventHandler<"authorization.completed">;
66
+ readonly "authorization.required"?: GitHubEventHandler<"authorization.required">;
67
+ readonly "input.requested"?: GitHubEventHandler<"input.requested">;
68
+ readonly "message.appended"?: GitHubEventHandler<"message.appended">;
69
+ readonly "message.completed"?: GitHubEventHandler<"message.completed">;
70
+ readonly "session.completed"?: GitHubEventHandler<"session.completed">;
71
+ readonly "session.failed"?: GitHubSessionFailedHandler;
72
+ readonly "session.waiting"?: GitHubEventHandler<"session.waiting">;
73
+ readonly "turn.completed"?: GitHubEventHandler<"turn.completed">;
74
+ readonly "turn.failed"?: GitHubEventHandler<"turn.failed">;
75
+ readonly "turn.started"?: GitHubEventHandler<"turn.started">;
76
+ }
77
+ /** Configuration for {@link githubChannel}. */
78
+ export interface GitHubChannelConfig {
79
+ readonly api?: GitHubApiOptions;
80
+ readonly botName?: string;
81
+ readonly credentials?: GitHubChannelCredentials;
82
+ readonly events?: GitHubChannelEvents;
83
+ readonly progress?: GitHubProgressConfig;
84
+ readonly pullRequestContext?: GitHubPullRequestContextConfig;
85
+ readonly route?: string;
86
+ /**
87
+ * Invoked for every `@mention` of the bot in an issue/PR timeline comment or
88
+ * an inline review comment. `ctx.conversation.kind` distinguishes the surface.
89
+ * Return `{ auth }` to dispatch or `null` to ignore. Replacing this fully
90
+ * replaces the default mention gate.
91
+ */
92
+ onComment?(ctx: GitHubInboundContext, comment: GitHubComment): GitHubInboundResultOrPromise;
93
+ /**
94
+ * Opt-in handler for `issues` webhook events. There is no default dispatch —
95
+ * define this to act on issues (e.g. `issue.action === "opened"`).
96
+ */
97
+ onIssue?(ctx: GitHubInboundContext, issue: GitHubIssueEvent): GitHubInboundResultOrPromise;
98
+ /**
99
+ * Opt-in handler for `pull_request` webhook events. There is no default
100
+ * dispatch — define this to act on PRs (e.g. `pullRequest.action === "opened"`).
101
+ */
102
+ onPullRequest?(ctx: GitHubInboundContext, pullRequest: GitHubPullRequestEvent): GitHubInboundResultOrPromise;
103
+ }
104
+ /** Concrete return type of {@link githubChannel}. */
105
+ export interface GitHubChannel extends Channel<GitHubChannelState, GitHubReceiveTarget> {
106
+ }
107
+ /** GitHub channel factory for GitHub App webhooks and proactive comments. */
108
+ export declare function githubChannel(config?: GitHubChannelConfig): GitHubChannel;
109
+ export {};
@@ -0,0 +1 @@
1
+ import{createLogger}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{getGitHubRepository}from"#public/channels/github/api.js";import{parseGitHubWebhookEvent}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromReceiveTarget}from"#public/channels/github/state.js";import{GITHUB_CHANNEL_DEFAULT_ROUTE}from"#public/channels/github/constants.js";import{createDefaultEvents,defaultOnComment}from"#public/channels/github/defaults.js";import{dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment}from"#public/channels/github/dispatch.js";import{verifyGitHubRequest}from"#public/channels/github/verify.js";const log=createLogger(`github.channel`);function githubChannel(e={}){let s=e.botName??process.env.GITHUB_APP_SLUG,u={botName:s},d={...createDefaultEvents({api:e.api,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({kindHint:`github`,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(t,{send:n,waitUntil:r})=>{let a=await verifyInbound(t,e.credentials);if(a===null)return new Response(`unauthorized`,{status:401});let o;try{o=parseGitHubWebhookEvent({body:a,contentType:t.headers.get(`content-type`)??void 0,headers:t.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return o===null?jsonOk({ignored:!0,ok:!0}):o.kind===`ping`?jsonOk({ok:!0}):o.kind===`issue_comment`&&o.action===`created`?(r(dispatchIssueComment({botName:s,config:e,event:o,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),send:n})),jsonOk({ok:!0})):o.kind===`pull_request_review_comment`&&o.action===`created`?(r(dispatchPullRequestReviewComment({botName:s,config:e,event:o,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),send:n})),jsonOk({ok:!0})):o.kind===`issues`&&e.onIssue!==void 0?(r(dispatchIssue({config:e,event:o,handler:e.onIssue,send:n})),jsonOk({ok:!0})):o.kind===`pull_request`&&e.onPullRequest!==void 0?(r(dispatchPullRequest({config:e,event:o,handler:e.onPullRequest,send:n})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0})})],async receive(t,{send:n}){let i=t.target,s=readNonEmptyString(i.owner),c=readNonEmptyString(i.repo);if(s===void 0||c===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([i.issueNumber!==void 0,i.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let l=stateFromReceiveTarget({target:i,owner:s,repo:c,repositoryId:i.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:i.installationId,owner:s,repo:c})).id});if(i.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:l});await t.post(i.initialMessage)}return n(t.message,{auth:t.auth,continuationToken:continuationTokenFromState(l),state:l})},events:d})}function rebuildGitHubContext(e,t,n){let r=buildGitHubBinding({config:n,state:e});return{conversation:conversationFromState(e),github:r.github,repository:r.github.repository,state:e,thread:r.thread}}async function verifyInbound(e,t){try{return await verifyGitHubRequest(e,{webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`github inbound verification failed`,{error:e}),null}}function readNonEmptyString(e){return typeof e==`string`&&e.length>0?e:void 0}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{githubChannel};
@@ -0,0 +1,183 @@
1
+ import type { UserContent } from "ai";
2
+ import { type JsonObject } from "#shared/json.js";
3
+ /** GitHub conversation kinds represented by the channel state. */
4
+ export type GitHubConversationKind = "issue" | "pull_request" | "review_thread";
5
+ /** Stable repository identity normalized from webhook payloads. */
6
+ export interface GitHubRepositoryRef {
7
+ readonly fullName: string;
8
+ readonly id: number;
9
+ readonly name: string;
10
+ readonly owner: string;
11
+ readonly private: boolean;
12
+ }
13
+ /** GitHub actor metadata normalized from webhook payloads. */
14
+ export interface GitHubUser {
15
+ readonly htmlUrl: string | undefined;
16
+ readonly id: number;
17
+ readonly login: string;
18
+ readonly type: string;
19
+ readonly url: string | undefined;
20
+ }
21
+ /** Verified GitHub webhook delivery headers. */
22
+ export interface GitHubDelivery {
23
+ readonly event: string;
24
+ readonly hookId: string | undefined;
25
+ readonly id: string;
26
+ }
27
+ /** Channel-local conversation reference. */
28
+ export interface GitHubConversationRef {
29
+ readonly issueNumber: number | null;
30
+ readonly kind: GitHubConversationKind;
31
+ readonly pullRequestNumber: number | null;
32
+ }
33
+ /**
34
+ * Normalized GitHub comment handed to the `onComment` hook. Covers issue and PR
35
+ * timeline comments and inline review comments alike; `ctx.conversation.kind`
36
+ * distinguishes them.
37
+ */
38
+ export interface GitHubComment {
39
+ readonly author: GitHubUser | undefined;
40
+ readonly body: string;
41
+ readonly htmlUrl: string | undefined;
42
+ readonly id: number;
43
+ readonly raw: JsonObject;
44
+ readonly url: string | undefined;
45
+ }
46
+ /** Normalized issue/PR timeline comment. */
47
+ export interface GitHubIssueComment {
48
+ readonly author: GitHubUser | undefined;
49
+ readonly body: string;
50
+ readonly htmlUrl: string | undefined;
51
+ readonly id: number;
52
+ readonly issueNumber: number;
53
+ readonly pullRequestNumber: number | null;
54
+ readonly raw: JsonObject;
55
+ readonly url: string | undefined;
56
+ }
57
+ /** Normalized inline pull-request review comment. */
58
+ export interface GitHubPullRequestReviewComment {
59
+ readonly author: GitHubUser | undefined;
60
+ readonly body: string;
61
+ readonly htmlUrl: string | undefined;
62
+ readonly id: number;
63
+ readonly inReplyToId: number | null;
64
+ readonly pullRequestNumber: number;
65
+ readonly raw: JsonObject;
66
+ readonly reviewThreadRootCommentId: number;
67
+ readonly url: string | undefined;
68
+ }
69
+ /**
70
+ * Common `issues` webhook actions, kept open to any action GitHub sends so
71
+ * authors get autocomplete without losing forward compatibility.
72
+ */
73
+ export type GitHubIssueAction = "assigned" | "closed" | "edited" | "labeled" | "opened" | "reopened" | "unassigned" | "unlabeled" | (string & {});
74
+ /** Common `pull_request` webhook actions, kept open to any action GitHub sends. */
75
+ export type GitHubPullRequestAction = "closed" | "edited" | "labeled" | "opened" | "ready_for_review" | "reopened" | "synchronize" | "unlabeled" | (string & {});
76
+ /** Normalized issue event payload. */
77
+ export interface GitHubIssueEvent {
78
+ readonly action: GitHubIssueAction;
79
+ readonly issueNumber: number;
80
+ readonly raw: JsonObject;
81
+ }
82
+ /** Normalized pull-request event payload. */
83
+ export interface GitHubPullRequestEvent {
84
+ readonly action: GitHubPullRequestAction;
85
+ readonly headSha: string | null;
86
+ readonly pullRequestNumber: number;
87
+ readonly raw: JsonObject;
88
+ }
89
+ export interface GitHubPingEvent extends GitHubInboundEventBase {
90
+ readonly kind: "ping";
91
+ }
92
+ export interface GitHubIssueCommentEvent extends GitHubInboundEventBase {
93
+ readonly action: string;
94
+ readonly baseRef: string | null;
95
+ readonly baseSha: string | null;
96
+ readonly comment: GitHubIssueComment;
97
+ readonly conversation: GitHubConversationRef;
98
+ readonly defaultBranch: string | null;
99
+ readonly headRef: string | null;
100
+ readonly headSha: string | null;
101
+ readonly kind: "issue_comment";
102
+ }
103
+ export interface GitHubPullRequestReviewCommentEvent extends GitHubInboundEventBase {
104
+ readonly action: string;
105
+ readonly baseRef: string | null;
106
+ readonly baseSha: string | null;
107
+ readonly comment: GitHubPullRequestReviewComment;
108
+ readonly conversation: GitHubConversationRef;
109
+ readonly defaultBranch: string | null;
110
+ readonly headRef: string | null;
111
+ readonly headSha: string | null;
112
+ readonly kind: "pull_request_review_comment";
113
+ }
114
+ export interface GitHubIssueWebhookEvent extends GitHubInboundEventBase {
115
+ readonly action: string;
116
+ readonly conversation: GitHubConversationRef;
117
+ readonly issue: GitHubIssueEvent;
118
+ readonly kind: "issues";
119
+ }
120
+ export interface GitHubPullRequestWebhookEvent extends GitHubInboundEventBase {
121
+ readonly action: string;
122
+ readonly baseRef: string | null;
123
+ readonly baseSha: string | null;
124
+ readonly conversation: GitHubConversationRef;
125
+ readonly defaultBranch: string | null;
126
+ readonly headRef: string | null;
127
+ readonly headSha: string | null;
128
+ readonly kind: "pull_request";
129
+ readonly pullRequest: GitHubPullRequestEvent;
130
+ }
131
+ interface GitHubInboundEventBase {
132
+ readonly delivery: GitHubDelivery;
133
+ readonly installationId: number | undefined;
134
+ readonly raw: JsonObject;
135
+ readonly repository: GitHubRepositoryRef;
136
+ readonly sender: GitHubUser;
137
+ }
138
+ /** Parsed GitHub webhook event shape consumed by the channel. */
139
+ export type GitHubInboundEvent = GitHubIssueCommentEvent | GitHubIssueWebhookEvent | GitHubPingEvent | GitHubPullRequestReviewCommentEvent | GitHubPullRequestWebhookEvent;
140
+ /** Parsed mention trigger for a bot-directed GitHub comment. */
141
+ export interface GitHubCommentTrigger {
142
+ readonly kind: "mention";
143
+ readonly message: string;
144
+ readonly token: string;
145
+ }
146
+ /** Builds the channel-local continuation token for a GitHub conversation. */
147
+ export declare function githubContinuationToken(input: {
148
+ readonly conversationKind: GitHubConversationKind;
149
+ readonly issueNumber?: number | null;
150
+ readonly pullRequestNumber?: number | null;
151
+ readonly repositoryId: number;
152
+ readonly reviewThreadRootCommentId?: number | null;
153
+ }): string;
154
+ /** Returns true when a comment @mentions the bot and should wake the channel. */
155
+ export declare function shouldDispatchGitHubComment(input: {
156
+ readonly author?: GitHubUser;
157
+ readonly body: string;
158
+ readonly botName?: string;
159
+ }): boolean;
160
+ /** Extracts and strips the bot `@mention` from a comment body. */
161
+ export declare function extractGitHubCommentTrigger(input: {
162
+ readonly body: string;
163
+ readonly botName?: string;
164
+ }): GitHubCommentTrigger | null;
165
+ /** Parses GitHub webhook headers and body into an Ash-owned event shape. */
166
+ export declare function parseGitHubWebhookEvent(input: {
167
+ readonly body: string;
168
+ readonly contentType?: string;
169
+ readonly headers: Headers;
170
+ }): GitHubInboundEvent | null;
171
+ /** Renders deterministic GitHub metadata for the model-visible turn. */
172
+ export declare function formatGitHubContextBlock(input: {
173
+ readonly commentUrl?: string;
174
+ readonly deliveryId: string;
175
+ readonly headSha?: string | null;
176
+ readonly issueNumber?: number | null;
177
+ readonly pullRequestNumber?: number | null;
178
+ readonly repository: GitHubRepositoryRef;
179
+ readonly sender: GitHubUser;
180
+ }): string;
181
+ /** Prepends a `<github_context>` block to the inbound turn message. */
182
+ export declare function prependGitHubContext(message: string | UserContent, block: string): string | UserContent;
183
+ export {};
@@ -0,0 +1,2 @@
1
+ import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";function githubContinuationToken(e){return e.conversationKind===`issue`?`repo:${e.repositoryId}:issue:${requiredNumber(e.issueNumber,`issueNumber`)}`:e.conversationKind===`pull_request`?`repo:${e.repositoryId}:pull:${requiredNumber(e.pullRequestNumber,`pullRequestNumber`)}`:`repo:${e.repositoryId}:pull:${requiredNumber(e.pullRequestNumber,`pullRequestNumber`)}:review-comment:${requiredNumber(e.reviewThreadRootCommentId,`reviewThreadRootCommentId`)}`}function shouldDispatchGitHubComment(e){return isIgnoredGitHubComment(e.body,e.author,e.botName)?!1:extractGitHubCommentTrigger(e)!==null}function extractGitHubCommentTrigger(e){let t=e.botName?.trim();if(!t)return null;let n=RegExp(`@${escapeRegExp(t)}(?=$|[^A-Za-z0-9_-])`,`iu`).exec(e.body);if(n===null)return null;let r=n.index,i=r+n[0].length;return{kind:`mention`,message:`${e.body.slice(0,r)}${e.body.slice(i)}`.trim(),token:n[0]}}function parseGitHubWebhookEvent(e){let t=e.headers.get(`x-github-event`)??``,n=e.headers.get(`x-github-delivery`)??``;if(!t||!n)return null;let r=decodePayload(e.body,e.contentType),i=normalizeRepository(r.repository),a=normalizeUser(r.sender);if(i===null||a===void 0)return null;let o={delivery:{event:t,hookId:e.headers.get(`x-github-hook-id`)??void 0,id:n},installationId:readInstallationId(r.installation),raw:r,repository:i,sender:a};return t===`ping`?{...o,kind:`ping`}:t===`issue_comment`?parseIssueCommentEvent(o):t===`pull_request_review_comment`?parsePullRequestReviewCommentEvent(o):t===`issues`?parseIssueEvent(o):t===`pull_request`?parsePullRequestEvent(o):null}function formatGitHubContextBlock(e){return[`<github_context>`,`repository: ${e.repository.fullName}`,`repository_id: ${e.repository.id}`,...e.issueNumber!==void 0&&e.issueNumber!==null?[`issue_number: ${e.issueNumber}`]:[],...e.pullRequestNumber!==void 0&&e.pullRequestNumber!==null?[`pull_request_number: ${e.pullRequestNumber}`]:[],`sender: ${e.sender.login}`,`sender_type: ${e.sender.type}`,...e.commentUrl?[`comment_url: ${e.commentUrl}`]:[],...e.headSha?[`head_sha: ${e.headSha}`]:[],`delivery_id: ${e.deliveryId}`,`</github_context>`].join(`
2
+ `)}function prependGitHubContext(e,t){return typeof e==`string`?e.length>0?`${t}\n\n${e}`:t:[{text:t,type:`text`},...e]}function parseIssueCommentEvent(n){let r=isObject(n.raw.issue)?n.raw.issue:null,i=isObject(n.raw.comment)?parseJsonObject(n.raw.comment):null,a=typeof r?.number==`number`?r.number:void 0;if(i===null||r===null||a===void 0)return null;let o=isObject(r.pull_request)?a:null,s=readAction(n.raw),c={author:normalizeUser(i.user),body:typeof i.body==`string`?i.body:``,htmlUrl:typeof i.html_url==`string`?i.html_url:void 0,id:typeof i.id==`number`?i.id:0,issueNumber:a,pullRequestNumber:o,raw:i,url:typeof i.url==`string`?i.url:void 0};return{...n,action:s,baseRef:null,baseSha:null,comment:c,conversation:{issueNumber:a,kind:o===null?`issue`:`pull_request`,pullRequestNumber:o},defaultBranch:null,headRef:null,headSha:null,kind:`issue_comment`}}function parsePullRequestReviewCommentEvent(n){let r=isObject(n.raw.comment)?parseJsonObject(n.raw.comment):null,i=isObject(n.raw.pull_request)?n.raw.pull_request:null,a=typeof i?.number==`number`?i.number:void 0;if(r===null||a===void 0)return null;let o=typeof r.id==`number`?r.id:0,s=typeof r.in_reply_to_id==`number`?r.in_reply_to_id:null,c={author:normalizeUser(r.user),body:typeof r.body==`string`?r.body:``,htmlUrl:typeof r.html_url==`string`?r.html_url:void 0,id:o,inReplyToId:s,pullRequestNumber:a,raw:r,reviewThreadRootCommentId:s??o,url:typeof r.url==`string`?r.url:void 0};return{...n,action:readAction(n.raw),baseRef:readPullRequestBaseRef(i),baseSha:readPullRequestBaseSha(i),comment:c,conversation:{issueNumber:null,kind:`review_thread`,pullRequestNumber:a},defaultBranch:readPullRequestDefaultBranch(i),headRef:readPullRequestHeadRef(i),headSha:readPullRequestHeadSha(i),kind:`pull_request_review_comment`}}function parseIssueEvent(n){let r=isObject(n.raw.issue)?n.raw.issue:null,i=typeof r?.number==`number`?r.number:void 0;return i===void 0?null:{...n,action:readAction(n.raw),conversation:{issueNumber:i,kind:`issue`,pullRequestNumber:null},issue:{action:readAction(n.raw),issueNumber:i,raw:parseJsonObject(r)},kind:`issues`}}function parsePullRequestEvent(n){let r=isObject(n.raw.pull_request)?n.raw.pull_request:null,i=typeof r?.number==`number`?r.number:void 0;return i===void 0?null:{...n,action:readAction(n.raw),baseRef:readPullRequestBaseRef(r),baseSha:readPullRequestBaseSha(r),conversation:{issueNumber:null,kind:`pull_request`,pullRequestNumber:i},defaultBranch:readPullRequestDefaultBranch(r),headRef:readPullRequestHeadRef(r),headSha:readPullRequestHeadSha(r),kind:`pull_request`,pullRequest:{action:readAction(n.raw),headSha:readPullRequestHeadSha(r),pullRequestNumber:i,raw:parseJsonObject(r)}}}function decodePayload(e,n){if(n?.includes(`application/x-www-form-urlencoded`)===!0){let n=new URLSearchParams(e).get(`payload`)??``;return parseJsonObject(JSON.parse(n))}return parseJsonObject(JSON.parse(e))}function normalizeRepository(t){if(!isObject(t))return null;let n=typeof t.full_name==`string`?t.full_name:``,[r=``,i=``]=n.split(`/`),a=isObject(t.owner)?t.owner:{},o=typeof a.login==`string`?a.login:r,s=typeof t.name==`string`?t.name:i,c=typeof t.id==`number`?t.id:0;return!o||!s?null:{fullName:n||`${o}/${s}`,id:c,name:s,owner:o,private:t.private===!0}}function normalizeUser(t){if(!isObject(t))return;let n=typeof t.login==`string`?t.login:``;if(n)return{htmlUrl:typeof t.html_url==`string`?t.html_url:void 0,id:typeof t.id==`number`?t.id:0,login:n,type:typeof t.type==`string`?t.type:`User`,url:typeof t.url==`string`?t.url:void 0}}function readInstallationId(t){if(isObject(t))return typeof t.id==`number`?t.id:void 0}function readAction(e){return typeof e.action==`string`?e.action:``}function readPullRequestHeadSha(t){let n=isObject(t?.head)?t.head:null;return typeof n?.sha==`string`?n.sha:null}function readPullRequestHeadRef(t){let n=isObject(t?.head)?t.head:null;return typeof n?.ref==`string`?n.ref:null}function readPullRequestBaseRef(t){let n=isObject(t?.base)?t.base:null;return typeof n?.ref==`string`?n.ref:null}function readPullRequestBaseSha(t){let n=isObject(t?.base)?t.base:null;return typeof n?.sha==`string`?n.sha:null}function readPullRequestDefaultBranch(t){let n=isObject(t?.base)?t.base:null,r=isObject(n?.repo)?n.repo:null;return typeof r?.default_branch==`string`?r.default_branch:null}function isIgnoredGitHubComment(e,t,n){if(e.includes(`<!-- ash:github:`))return!0;if(t===void 0)return!1;if(t.type===`Bot`)return!0;let r=n?`${n}[bot]`.toLowerCase():``;return r.length>0&&t.login.toLowerCase()===r}function requiredNumber(e,t){if(typeof e==`number`&&Number.isFinite(e))return e;throw Error(`githubContinuationToken requires ${t}.`)}function escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,`\\$&`)}export{extractGitHubCommentTrigger,formatGitHubContextBlock,githubContinuationToken,parseGitHubWebhookEvent,prependGitHubContext,shouldDispatchGitHubComment};
@@ -0,0 +1,9 @@
1
+ export { GitHubApiError, type GitHubApiMethod, type GitHubApiOptions, type GitHubApiResponse, type GitHubJsonObject, type GitHubPostedComment, type GitHubReactionContent, } from "#public/channels/github/api.js";
2
+ export { type GitHubHandle, type GitHubThread } from "#public/channels/github/binding.js";
3
+ export { type GitHubAppId, type GitHubChannelCredentials, type GitHubInstallationToken, type GitHubPrivateKey, type GitHubWebhookSecret, } from "#public/channels/github/auth.js";
4
+ export { defaultGitHubAuth } from "#public/channels/github/defaults.js";
5
+ export { type GitHubComment, type GitHubConversationKind, type GitHubConversationRef, type GitHubDelivery, type GitHubIssueAction, type GitHubIssueEvent, type GitHubPullRequestAction, type GitHubPullRequestEvent, type GitHubRepositoryRef, type GitHubUser, } from "#public/channels/github/inbound.js";
6
+ export { githubChannel, type GitHubChannel, type GitHubChannelConfig, type GitHubChannelEvents, type GitHubEventContext, type GitHubInboundContext, type GitHubInboundResult, type GitHubInboundResultOrPromise, type GitHubProgressConfig, type GitHubReceiveTarget, } from "#public/channels/github/githubChannel.js";
7
+ export { GITHUB_DEFAULT_EXCLUDED_DIFF_FILES, type GitHubPullRequestContextConfig, } from "#public/channels/github/pr-context.js";
8
+ export { type GitHubChannelState } from "#public/channels/github/state.js";
9
+ export { type GitHubWebhookVerifier } from "#public/channels/github/verify.js";
@@ -0,0 +1 @@
1
+ import{GitHubApiError}from"#public/channels/github/api.js";import{GITHUB_DEFAULT_EXCLUDED_DIFF_FILES}from"#public/channels/github/pr-context.js";import{defaultGitHubAuth}from"#public/channels/github/defaults.js";import{githubChannel}from"#public/channels/github/githubChannel.js";export{GITHUB_DEFAULT_EXCLUDED_DIFF_FILES,GitHubApiError,defaultGitHubAuth,githubChannel};