agent-relay 6.0.11 → 6.0.12

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/dist/index.cjs CHANGED
@@ -5411,8 +5411,8 @@ var require_ignore = __commonJS({
5411
5411
  (prev, [matcher, replacer]) => prev.replace(matcher, replacer.bind(pattern)),
5412
5412
  pattern
5413
5413
  );
5414
- var isString = (subject) => typeof subject === "string";
5415
- var checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
5414
+ var isString2 = (subject) => typeof subject === "string";
5415
+ var checkPattern = (pattern) => pattern && isString2(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
5416
5416
  var splitPattern = (pattern) => pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
5417
5417
  var IgnoreRule = class {
5418
5418
  constructor(pattern, mark, body, ignoreCase, negative, prefix) {
@@ -5479,7 +5479,7 @@ var require_ignore = __commonJS({
5479
5479
  this._added = true;
5480
5480
  return;
5481
5481
  }
5482
- if (isString(pattern)) {
5482
+ if (isString2(pattern)) {
5483
5483
  pattern = {
5484
5484
  pattern
5485
5485
  };
@@ -5494,7 +5494,7 @@ var require_ignore = __commonJS({
5494
5494
  add(pattern) {
5495
5495
  this._added = false;
5496
5496
  makeArray(
5497
- isString(pattern) ? splitPattern(pattern) : pattern
5497
+ isString2(pattern) ? splitPattern(pattern) : pattern
5498
5498
  ).forEach(this._add, this);
5499
5499
  return this._added;
5500
5500
  }
@@ -5536,7 +5536,7 @@ var require_ignore = __commonJS({
5536
5536
  throw new Ctor(message);
5537
5537
  };
5538
5538
  var checkPath = (path25, originalPath, doThrow) => {
5539
- if (!isString(path25)) {
5539
+ if (!isString2(path25)) {
5540
5540
  return doThrow(
5541
5541
  `path must be a string, but got \`${originalPath}\``,
5542
5542
  TypeError
@@ -18730,6 +18730,1794 @@ var init_listr_renderer = __esm({
18730
18730
  }
18731
18731
  });
18732
18732
 
18733
+ // packages/github-primitive/src/constants.ts
18734
+ var DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_GH_PATH, DEFAULT_NANGO_BASE_URL, DEFAULT_NANGO_PROVIDER_CONFIG_KEY, DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT, DEFAULT_USER_AGENT;
18735
+ var init_constants = __esm({
18736
+ "packages/github-primitive/src/constants.ts"() {
18737
+ "use strict";
18738
+ DEFAULT_TIMEOUT = 3e4;
18739
+ DEFAULT_MAX_RETRIES = 3;
18740
+ DEFAULT_GH_PATH = "gh";
18741
+ DEFAULT_NANGO_BASE_URL = "https://api.nango.dev";
18742
+ DEFAULT_NANGO_PROVIDER_CONFIG_KEY = "github";
18743
+ DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT = "/api/integrations/github/proxy";
18744
+ DEFAULT_USER_AGENT = "agent-relay-github-primitive";
18745
+ }
18746
+ });
18747
+
18748
+ // packages/github-primitive/src/types.ts
18749
+ var GitHubAction, GITHUB_ACTIONS, GitHubApiError, GitHubClientInterface;
18750
+ var init_types = __esm({
18751
+ "packages/github-primitive/src/types.ts"() {
18752
+ "use strict";
18753
+ GitHubAction = /* @__PURE__ */ ((GitHubAction2) => {
18754
+ GitHubAction2["ListRepos"] = "listRepos";
18755
+ GitHubAction2["GetRepo"] = "getRepo";
18756
+ GitHubAction2["ListIssues"] = "listIssues";
18757
+ GitHubAction2["CreateIssue"] = "createIssue";
18758
+ GitHubAction2["UpdateIssue"] = "updateIssue";
18759
+ GitHubAction2["CloseIssue"] = "closeIssue";
18760
+ GitHubAction2["ListPRs"] = "listPRs";
18761
+ GitHubAction2["GetPR"] = "getPR";
18762
+ GitHubAction2["CreatePR"] = "createPR";
18763
+ GitHubAction2["UpdatePR"] = "updatePR";
18764
+ GitHubAction2["MergePR"] = "mergePR";
18765
+ GitHubAction2["ListFiles"] = "listFiles";
18766
+ GitHubAction2["ReadFile"] = "readFile";
18767
+ GitHubAction2["CreateFile"] = "createFile";
18768
+ GitHubAction2["UpdateFile"] = "updateFile";
18769
+ GitHubAction2["DeleteFile"] = "deleteFile";
18770
+ GitHubAction2["CreateBranch"] = "createBranch";
18771
+ GitHubAction2["ListBranches"] = "listBranches";
18772
+ GitHubAction2["ListCommits"] = "listCommits";
18773
+ GitHubAction2["CreateCommit"] = "createCommit";
18774
+ GitHubAction2["GetUser"] = "getUser";
18775
+ GitHubAction2["ListOrganizations"] = "listOrganizations";
18776
+ return GitHubAction2;
18777
+ })(GitHubAction || {});
18778
+ GITHUB_ACTIONS = Object.values(GitHubAction);
18779
+ GitHubApiError = class extends Error {
18780
+ status;
18781
+ responseBody;
18782
+ responseHeaders;
18783
+ cause;
18784
+ constructor(message, options = {}) {
18785
+ super(message);
18786
+ this.name = "GitHubApiError";
18787
+ this.status = options.status;
18788
+ this.responseBody = options.responseBody;
18789
+ this.responseHeaders = options.responseHeaders;
18790
+ this.cause = options.cause;
18791
+ }
18792
+ };
18793
+ GitHubClientInterface = class {
18794
+ config;
18795
+ constructor(config2) {
18796
+ this.config = config2;
18797
+ }
18798
+ getRuntimeConfig() {
18799
+ return this.config;
18800
+ }
18801
+ };
18802
+ }
18803
+ });
18804
+
18805
+ // packages/github-primitive/src/actions/utils.ts
18806
+ async function withActionError(description, operation) {
18807
+ try {
18808
+ return await operation();
18809
+ } catch (error51) {
18810
+ if (error51 instanceof GitHubApiError) {
18811
+ throw new GitHubApiError(`Failed to ${description}: ${error51.message}`, {
18812
+ status: error51.status,
18813
+ responseBody: error51.responseBody,
18814
+ responseHeaders: error51.responseHeaders,
18815
+ cause: error51
18816
+ });
18817
+ }
18818
+ throw new GitHubApiError(`Failed to ${description}: ${errorMessage(error51)}`, { cause: error51 });
18819
+ }
18820
+ }
18821
+ function assertOwnerRepo(owner, repo) {
18822
+ assertNonEmptyString(owner, "owner");
18823
+ assertNonEmptyString(repo, "repo");
18824
+ }
18825
+ function assertNonEmptyString(value, name) {
18826
+ if (typeof value !== "string" || !value.trim()) {
18827
+ throw new GitHubApiError(`GitHub ${name} must be a non-empty string.`);
18828
+ }
18829
+ return value.trim();
18830
+ }
18831
+ function assertPositiveInteger(value, name) {
18832
+ if (!Number.isInteger(value) || value < 1) {
18833
+ throw new GitHubApiError(`GitHub ${name} must be a positive integer.`);
18834
+ }
18835
+ return value;
18836
+ }
18837
+ function repoEndpoint(owner, repo, suffix = "") {
18838
+ assertOwnerRepo(owner, repo);
18839
+ return `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}${suffix}`;
18840
+ }
18841
+ function contentsEndpoint(owner, repo, path25 = "") {
18842
+ const normalizedPath = normalizeRepoPath(path25);
18843
+ const suffix = normalizedPath ? `/contents/${encodeRepoPath(normalizedPath)}` : "/contents";
18844
+ return repoEndpoint(owner, repo, suffix);
18845
+ }
18846
+ function branchEndpoint(owner, repo, branch) {
18847
+ const normalizedBranch = assertNonEmptyString(branch, "branch");
18848
+ return repoEndpoint(owner, repo, `/branches/${encodeURIComponent(normalizedBranch)}`);
18849
+ }
18850
+ function normalizeRepoPath(path25) {
18851
+ return path25?.trim().replace(/^\/+/, "").replace(/\/+$/, "") ?? "";
18852
+ }
18853
+ function normalizePerPage(perPage) {
18854
+ if (typeof perPage === "undefined") {
18855
+ return void 0;
18856
+ }
18857
+ if (!Number.isInteger(perPage) || perPage < 1) {
18858
+ throw new GitHubApiError("GitHub perPage must be a positive integer.");
18859
+ }
18860
+ return Math.min(perPage, 100);
18861
+ }
18862
+ function removeUndefinedValues(values) {
18863
+ const result = {};
18864
+ for (const [key, value] of Object.entries(values)) {
18865
+ if (typeof value !== "undefined") {
18866
+ result[key] = value;
18867
+ }
18868
+ }
18869
+ return result;
18870
+ }
18871
+ function hasDefinedValue(values) {
18872
+ return Object.values(values).some((value) => typeof value !== "undefined");
18873
+ }
18874
+ function optionalRecord(value) {
18875
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
18876
+ }
18877
+ function appendQuery(path25, query) {
18878
+ if (!query) {
18879
+ return path25;
18880
+ }
18881
+ const params = new URLSearchParams();
18882
+ for (const [name, rawValue] of Object.entries(query)) {
18883
+ const values = Array.isArray(rawValue) ? rawValue : [rawValue];
18884
+ for (const value of values) {
18885
+ if (value !== null && typeof value !== "undefined") {
18886
+ params.append(name, String(value));
18887
+ }
18888
+ }
18889
+ }
18890
+ const serialized = params.toString();
18891
+ if (!serialized) {
18892
+ return path25;
18893
+ }
18894
+ return `${path25}${path25.includes("?") ? "&" : "?"}${serialized}`;
18895
+ }
18896
+ function nonEmpty(value) {
18897
+ const trimmed = value?.trim();
18898
+ return trimmed ? trimmed : void 0;
18899
+ }
18900
+ function trimTrailingSlash(value) {
18901
+ const trimmed = nonEmpty(value);
18902
+ return trimmed?.replace(/\/+$/, "");
18903
+ }
18904
+ function queryWithPerPage(query, perPage) {
18905
+ const normalizedPerPage = normalizePerPage(perPage);
18906
+ return typeof normalizedPerPage === "undefined" ? query : {
18907
+ ...query,
18908
+ per_page: normalizedPerPage
18909
+ };
18910
+ }
18911
+ function asRecord(value, name) {
18912
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
18913
+ throw new GitHubApiError(`GitHub API response for ${name} was not an object.`);
18914
+ }
18915
+ return value;
18916
+ }
18917
+ function asArray(value, name) {
18918
+ if (!Array.isArray(value)) {
18919
+ throw new GitHubApiError(`GitHub API response for ${name} was not an array.`);
18920
+ }
18921
+ return value;
18922
+ }
18923
+ function mapGitHubOwner(value) {
18924
+ const owner = asRecord(value, "owner");
18925
+ return {
18926
+ login: stringValue(owner.login),
18927
+ type: stringValue(owner.type, "User"),
18928
+ id: numberValue(owner.id),
18929
+ avatarUrl: optionalString(owner.avatar_url),
18930
+ htmlUrl: optionalString(owner.html_url)
18931
+ };
18932
+ }
18933
+ function mapLogin(value) {
18934
+ const record2 = asRecord(value, "user");
18935
+ return {
18936
+ login: stringValue(record2.login)
18937
+ };
18938
+ }
18939
+ function mapLogins(value) {
18940
+ if (!Array.isArray(value)) {
18941
+ return [];
18942
+ }
18943
+ return value.map(mapLogin);
18944
+ }
18945
+ function stringValue(value, fallback = "") {
18946
+ return typeof value === "string" ? value : fallback;
18947
+ }
18948
+ function optionalString(value) {
18949
+ return typeof value === "string" && value.length > 0 ? value : void 0;
18950
+ }
18951
+ function numberValue(value, fallback = 0) {
18952
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
18953
+ }
18954
+ function booleanValue(value, fallback = false) {
18955
+ return typeof value === "boolean" ? value : fallback;
18956
+ }
18957
+ function stateValue(value) {
18958
+ return value === "closed" ? "closed" : "open";
18959
+ }
18960
+ function visibilityValue(value, isPrivate) {
18961
+ if (value === "public" || value === "private" || value === "internal") {
18962
+ return value;
18963
+ }
18964
+ return isPrivate ? "private" : "public";
18965
+ }
18966
+ function errorMessage(error51) {
18967
+ return error51 instanceof Error ? error51.message : String(error51);
18968
+ }
18969
+ function encodeRepoPath(path25) {
18970
+ return path25.split("/").map(encodeURIComponent).join("/");
18971
+ }
18972
+ var init_utils = __esm({
18973
+ "packages/github-primitive/src/actions/utils.ts"() {
18974
+ "use strict";
18975
+ init_types();
18976
+ }
18977
+ });
18978
+
18979
+ // packages/github-primitive/src/actions/branches.ts
18980
+ async function listBranches(adapter, owner, repo) {
18981
+ return withActionError(`list GitHub branches for ${owner}/${repo}`, async () => {
18982
+ assertOwnerRepo(owner, repo);
18983
+ const response = await adapter.request("GET", repoEndpoint(owner, repo, "/branches"));
18984
+ return asArray(response, "branches").map(mapBranch);
18985
+ });
18986
+ }
18987
+ async function createBranch(adapter, params) {
18988
+ const { owner, repo } = params;
18989
+ return withActionError(`create GitHub branch ${params.branch} in ${owner}/${repo}`, async () => {
18990
+ assertOwnerRepo(owner, repo);
18991
+ const branch = assertNonEmptyString(params.branch, "branch");
18992
+ const sourceBranch = params.fromBranch ?? await getDefaultBranch(adapter, params);
18993
+ const source = await getBranch(adapter, owner, repo, sourceBranch);
18994
+ const sha = assertNonEmptyString(source.commit.sha, "source branch sha");
18995
+ await adapter.request("POST", repoEndpoint(owner, repo, "/git/refs"), {
18996
+ body: {
18997
+ ref: `refs/heads/${branch}`,
18998
+ sha
18999
+ }
19000
+ });
19001
+ });
19002
+ }
19003
+ async function getBranch(adapter, owner, repo, branch) {
19004
+ const response = await adapter.request("GET", branchEndpoint(owner, repo, branch));
19005
+ return mapBranch(response);
19006
+ }
19007
+ function mapBranch(value) {
19008
+ const branch = asRecord(value, "branch");
19009
+ const commit = asRecord(branch.commit, "branch commit");
19010
+ return {
19011
+ name: stringValue(branch.name),
19012
+ commit: {
19013
+ sha: stringValue(commit.sha),
19014
+ url: stringValue(commit.url)
19015
+ },
19016
+ protected: booleanValue(branch.protected)
19017
+ };
19018
+ }
19019
+ async function getDefaultBranch(adapter, params) {
19020
+ const response = await adapter.request("GET", repoEndpoint(params.owner, params.repo));
19021
+ const repository = asRecord(response, "repository");
19022
+ const branch = stringValue(repository.default_branch);
19023
+ if (!branch) {
19024
+ const id = numberValue(repository.id);
19025
+ throw new Error(
19026
+ id ? `Repository ${params.owner}/${params.repo} did not include a default branch.` : `Repository ${params.owner}/${params.repo} was not a valid repository response.`
19027
+ );
19028
+ }
19029
+ return branch;
19030
+ }
19031
+ var init_branches = __esm({
19032
+ "packages/github-primitive/src/actions/branches.ts"() {
19033
+ "use strict";
19034
+ init_utils();
19035
+ }
19036
+ });
19037
+
19038
+ // packages/github-primitive/src/actions/commits.ts
19039
+ async function listCommits(adapter, params) {
19040
+ const { owner, repo } = params;
19041
+ return withActionError(`list GitHub commits for ${owner}/${repo}`, async () => {
19042
+ assertOwnerRepo(owner, repo);
19043
+ const query = {
19044
+ sha: params.sha,
19045
+ path: params.path,
19046
+ author: params.author,
19047
+ since: params.since,
19048
+ until: params.until,
19049
+ per_page: normalizePerPage(params.perPage)
19050
+ };
19051
+ const response = await adapter.request("GET", repoEndpoint(owner, repo, "/commits"), {
19052
+ query
19053
+ });
19054
+ return asArray(response, "commits").map(mapCommit);
19055
+ });
19056
+ }
19057
+ async function createCommit(adapter, params) {
19058
+ const { owner, repo } = params;
19059
+ return withActionError(`create GitHub commit in ${owner}/${repo}`, async () => {
19060
+ assertOwnerRepo(owner, repo);
19061
+ const message = assertNonEmptyString(params.message, "commit message");
19062
+ const tree = assertNonEmptyString(params.tree, "commit tree");
19063
+ if (!Array.isArray(params.parents)) {
19064
+ throw new Error("GitHub commit parents must be an array of parent SHAs.");
19065
+ }
19066
+ const response = await adapter.request("POST", repoEndpoint(owner, repo, "/git/commits"), {
19067
+ body: removeUndefinedValues({
19068
+ message,
19069
+ tree,
19070
+ parents: params.parents.map((parent) => assertNonEmptyString(parent, "parent sha")),
19071
+ author: params.author,
19072
+ committer: params.committer
19073
+ })
19074
+ });
19075
+ return mapCommit(response);
19076
+ });
19077
+ }
19078
+ function mapCommit(value) {
19079
+ const topLevel = asRecord(value, "commit");
19080
+ const nestedCommit = optionalRecord(topLevel.commit);
19081
+ const author = optionalRecord(nestedCommit?.author ?? topLevel.author);
19082
+ const committer = optionalRecord(nestedCommit?.committer ?? topLevel.committer);
19083
+ return {
19084
+ sha: stringValue(topLevel.sha),
19085
+ url: optionalString(topLevel.url),
19086
+ htmlUrl: optionalString(topLevel.html_url),
19087
+ message: optionalString(nestedCommit?.message ?? topLevel.message),
19088
+ author: author ? mapCommitAuthor(author) : void 0,
19089
+ committer: committer ? mapCommitAuthor(committer) : void 0
19090
+ };
19091
+ }
19092
+ function mapCommitAuthor(value) {
19093
+ return {
19094
+ name: stringValue(value.name),
19095
+ email: stringValue(value.email),
19096
+ date: optionalString(value.date)
19097
+ };
19098
+ }
19099
+ var init_commits = __esm({
19100
+ "packages/github-primitive/src/actions/commits.ts"() {
19101
+ "use strict";
19102
+ init_utils();
19103
+ }
19104
+ });
19105
+
19106
+ // packages/github-primitive/src/actions/files.ts
19107
+ async function listFiles(adapter, owner, repo, path25 = "", options = {}) {
19108
+ return withActionError(`list GitHub files at ${owner}/${repo}/${path25}`, async () => {
19109
+ assertOwnerRepo(owner, repo);
19110
+ const response = await adapter.request("GET", contentsEndpoint(owner, repo, path25), {
19111
+ query: {
19112
+ ref: options.ref
19113
+ }
19114
+ });
19115
+ return Array.isArray(response) ? asArray(response, "repository contents").map(mapFile) : [mapFile(response)];
19116
+ });
19117
+ }
19118
+ async function readFile3(adapter, owner, repo, path25, ref) {
19119
+ return withActionError(`read GitHub file ${owner}/${repo}/${path25}`, async () => {
19120
+ assertOwnerRepo(owner, repo);
19121
+ assertNonEmptyString(normalizeRepoPath(path25), "file path");
19122
+ const response = await adapter.request("GET", contentsEndpoint(owner, repo, path25), {
19123
+ query: {
19124
+ ref
19125
+ }
19126
+ });
19127
+ const file2 = mapFile(response);
19128
+ if (file2.type !== "file") {
19129
+ throw new Error(`GitHub path "${path25}" is not a file.`);
19130
+ }
19131
+ if (!file2.content) {
19132
+ throw new Error(`GitHub file "${path25}" did not include content in the API response.`);
19133
+ }
19134
+ if (file2.encoding && file2.encoding !== "base64") {
19135
+ throw new Error(`GitHub file "${path25}" used unsupported encoding "${file2.encoding}".`);
19136
+ }
19137
+ return import_node_buffer.Buffer.from(file2.content.replace(/\s/g, ""), "base64").toString("utf8");
19138
+ });
19139
+ }
19140
+ async function createFile(adapter, owner, repo, path25, content, message, options = {}) {
19141
+ return withActionError(`create GitHub file ${owner}/${repo}/${path25}`, async () => {
19142
+ assertOwnerRepo(owner, repo);
19143
+ const normalizedPath = assertNonEmptyString(normalizeRepoPath(path25), "file path");
19144
+ const commitMessage = assertNonEmptyString(message, "commit message");
19145
+ await adapter.request("PUT", contentsEndpoint(owner, repo, normalizedPath), {
19146
+ body: removeUndefinedValues({
19147
+ message: commitMessage,
19148
+ content: import_node_buffer.Buffer.from(content, "utf8").toString("base64"),
19149
+ branch: options.branch,
19150
+ author: options.author
19151
+ })
19152
+ });
19153
+ });
19154
+ }
19155
+ async function updateFile(adapter, owner, repo, path25, content, message, sha, options = {}) {
19156
+ return withActionError(`update GitHub file ${owner}/${repo}/${path25}`, async () => {
19157
+ assertOwnerRepo(owner, repo);
19158
+ const normalizedPath = assertNonEmptyString(normalizeRepoPath(path25), "file path");
19159
+ const commitMessage = assertNonEmptyString(message, "commit message");
19160
+ const fileSha = assertNonEmptyString(sha, "file sha");
19161
+ const response = await adapter.request("PUT", contentsEndpoint(owner, repo, normalizedPath), {
19162
+ body: removeUndefinedValues({
19163
+ message: commitMessage,
19164
+ content: import_node_buffer.Buffer.from(content, "utf8").toString("base64"),
19165
+ sha: fileSha,
19166
+ branch: options.branch,
19167
+ author: options.author
19168
+ })
19169
+ });
19170
+ const contentRecord = asRecord(response, "update file response").content;
19171
+ return mapFile(contentRecord);
19172
+ });
19173
+ }
19174
+ async function deleteFile(adapter, owner, repo, path25, sha, message, options = {}) {
19175
+ return withActionError(`delete GitHub file ${owner}/${repo}/${path25}`, async () => {
19176
+ assertOwnerRepo(owner, repo);
19177
+ const normalizedPath = assertNonEmptyString(normalizeRepoPath(path25), "file path");
19178
+ const fileSha = assertNonEmptyString(sha, "file sha");
19179
+ const commitMessage = assertNonEmptyString(message, "commit message");
19180
+ await adapter.request("DELETE", contentsEndpoint(owner, repo, normalizedPath), {
19181
+ body: removeUndefinedValues({
19182
+ message: commitMessage,
19183
+ sha: fileSha,
19184
+ branch: options.branch,
19185
+ author: options.author
19186
+ })
19187
+ });
19188
+ });
19189
+ }
19190
+ function mapFile(value) {
19191
+ const file2 = asRecord(value, "repository content");
19192
+ const type = stringValue(file2.type) === "dir" ? "dir" : "file";
19193
+ return {
19194
+ name: stringValue(file2.name),
19195
+ path: stringValue(file2.path),
19196
+ sha: stringValue(file2.sha),
19197
+ size: numberValue(file2.size),
19198
+ url: stringValue(file2.url),
19199
+ htmlUrl: stringValue(file2.html_url),
19200
+ gitUrl: stringValue(file2.git_url),
19201
+ downloadUrl: optionalString(file2.download_url),
19202
+ type,
19203
+ content: optionalString(file2.content),
19204
+ encoding: optionalString(file2.encoding),
19205
+ target: optionalString(file2.target)
19206
+ };
19207
+ }
19208
+ var import_node_buffer;
19209
+ var init_files = __esm({
19210
+ "packages/github-primitive/src/actions/files.ts"() {
19211
+ "use strict";
19212
+ import_node_buffer = require("node:buffer");
19213
+ init_utils();
19214
+ }
19215
+ });
19216
+
19217
+ // packages/github-primitive/src/actions/issues.ts
19218
+ async function listIssues(adapter, owner, repo, options = {}) {
19219
+ return withActionError(`list GitHub issues for ${owner}/${repo}`, async () => {
19220
+ assertOwnerRepo(owner, repo);
19221
+ const query = queryWithPerPage(
19222
+ {
19223
+ state: options.state,
19224
+ assignee: options.assignee,
19225
+ labels: options.labels,
19226
+ sort: options.sort,
19227
+ direction: options.direction
19228
+ },
19229
+ options.perPage
19230
+ );
19231
+ const response = await adapter.request("GET", repoEndpoint(owner, repo, "/issues"), {
19232
+ query
19233
+ });
19234
+ return asArray(response, "issues").filter(isIssueResponse).map(mapIssue);
19235
+ });
19236
+ }
19237
+ async function createIssue(adapter, owner, repo, title, body, options = {}) {
19238
+ return withActionError(`create GitHub issue in ${owner}/${repo}`, async () => {
19239
+ assertOwnerRepo(owner, repo);
19240
+ const issueTitle = assertNonEmptyString(title, "issue title");
19241
+ const response = await adapter.request("POST", repoEndpoint(owner, repo, "/issues"), {
19242
+ body: removeUndefinedValues({
19243
+ title: issueTitle,
19244
+ body,
19245
+ assignees: options.assignee ? [options.assignee] : void 0,
19246
+ labels: options.labels,
19247
+ milestone: options.milestone
19248
+ })
19249
+ });
19250
+ return mapIssue(response);
19251
+ });
19252
+ }
19253
+ async function updateIssue(adapter, owner, repo, number4, updates) {
19254
+ return withActionError(`update GitHub issue #${number4} in ${owner}/${repo}`, async () => {
19255
+ assertOwnerRepo(owner, repo);
19256
+ assertPositiveInteger(number4, "issue number");
19257
+ if (!hasDefinedValue(updates)) {
19258
+ throw new Error("At least one issue update field must be provided.");
19259
+ }
19260
+ const response = await adapter.request("PATCH", repoEndpoint(owner, repo, `/issues/${number4}`), {
19261
+ body: removeUndefinedValues({
19262
+ title: updates.title,
19263
+ body: updates.body,
19264
+ state: updates.state,
19265
+ assignees: updates.assignee ? [updates.assignee] : void 0,
19266
+ labels: updates.labels
19267
+ })
19268
+ });
19269
+ return mapIssue(response);
19270
+ });
19271
+ }
19272
+ function mapIssue(value) {
19273
+ const issue2 = asRecord(value, "issue");
19274
+ const milestone = optionalRecord(issue2.milestone);
19275
+ const reactions = optionalRecord(issue2.reactions);
19276
+ return {
19277
+ number: numberValue(issue2.number),
19278
+ id: numberValue(issue2.id),
19279
+ title: stringValue(issue2.title),
19280
+ body: optionalString(issue2.body),
19281
+ user: mapGitHubOwner(issue2.user),
19282
+ labels: Array.isArray(issue2.labels) ? issue2.labels.map(mapIssueLabel) : [],
19283
+ state: stateValue(issue2.state),
19284
+ locked: booleanValue(issue2.locked),
19285
+ assignee: issue2.assignee ? mapLogin(issue2.assignee) : void 0,
19286
+ assignees: mapLogins(issue2.assignees),
19287
+ milestone: milestone ? {
19288
+ number: numberValue(milestone.number),
19289
+ title: stringValue(milestone.title)
19290
+ } : void 0,
19291
+ commentsCount: numberValue(issue2.comments),
19292
+ createdAt: stringValue(issue2.created_at),
19293
+ updatedAt: stringValue(issue2.updated_at),
19294
+ closedAt: optionalString(issue2.closed_at),
19295
+ authorAssociation: stringValue(issue2.author_association),
19296
+ reactions: {
19297
+ totalCount: numberValue(reactions?.total_count)
19298
+ }
19299
+ };
19300
+ }
19301
+ function mapIssueLabel(value) {
19302
+ if (typeof value === "string") {
19303
+ return {
19304
+ name: value,
19305
+ color: ""
19306
+ };
19307
+ }
19308
+ const label = asRecord(value, "issue label");
19309
+ return {
19310
+ name: stringValue(label.name),
19311
+ color: stringValue(label.color),
19312
+ description: optionalString(label.description)
19313
+ };
19314
+ }
19315
+ function isIssueResponse(value) {
19316
+ return !("pull_request" in asRecord(value, "issue"));
19317
+ }
19318
+ var init_issues = __esm({
19319
+ "packages/github-primitive/src/actions/issues.ts"() {
19320
+ "use strict";
19321
+ init_utils();
19322
+ }
19323
+ });
19324
+
19325
+ // packages/github-primitive/src/actions/pulls.ts
19326
+ async function listPRs(adapter, owner, repo, options = {}) {
19327
+ return withActionError(`list GitHub pull requests for ${owner}/${repo}`, async () => {
19328
+ assertOwnerRepo(owner, repo);
19329
+ const query = queryWithPerPage(
19330
+ {
19331
+ state: options.state,
19332
+ base: options.base,
19333
+ head: options.head,
19334
+ sort: options.sort,
19335
+ direction: options.direction
19336
+ },
19337
+ options.perPage
19338
+ );
19339
+ const response = await adapter.request("GET", repoEndpoint(owner, repo, "/pulls"), {
19340
+ query
19341
+ });
19342
+ return asArray(response, "pull requests").map(mapPR);
19343
+ });
19344
+ }
19345
+ async function getPR(adapter, owner, repo, number4) {
19346
+ return withActionError(`get GitHub pull request #${number4} in ${owner}/${repo}`, async () => {
19347
+ assertOwnerRepo(owner, repo);
19348
+ assertPositiveInteger(number4, "pull request number");
19349
+ const response = await adapter.request("GET", repoEndpoint(owner, repo, `/pulls/${number4}`));
19350
+ return mapPR(response);
19351
+ });
19352
+ }
19353
+ async function createPR(adapter, owner, repo, title, body, base, head, options = {}) {
19354
+ return withActionError(`create GitHub pull request in ${owner}/${repo}`, async () => {
19355
+ assertOwnerRepo(owner, repo);
19356
+ const prTitle = assertNonEmptyString(title, "pull request title");
19357
+ const baseRef = assertNonEmptyString(base, "pull request base");
19358
+ const headRef = assertNonEmptyString(head, "pull request head");
19359
+ const response = await adapter.request("POST", repoEndpoint(owner, repo, "/pulls"), {
19360
+ body: removeUndefinedValues({
19361
+ title: prTitle,
19362
+ body,
19363
+ base: baseRef,
19364
+ head: headRef,
19365
+ draft: options.draft,
19366
+ maintainer_can_modify: options.maintainerCanModify
19367
+ })
19368
+ });
19369
+ return mapPR(response);
19370
+ });
19371
+ }
19372
+ async function updatePR(adapter, owner, repo, number4, updates) {
19373
+ return withActionError(`update GitHub pull request #${number4} in ${owner}/${repo}`, async () => {
19374
+ assertOwnerRepo(owner, repo);
19375
+ assertPositiveInteger(number4, "pull request number");
19376
+ if (!hasDefinedValue(updates)) {
19377
+ throw new Error("At least one pull request update field must be provided.");
19378
+ }
19379
+ const response = await adapter.request("PATCH", repoEndpoint(owner, repo, `/pulls/${number4}`), {
19380
+ body: removeUndefinedValues({
19381
+ title: updates.title,
19382
+ body: updates.body,
19383
+ state: updates.state,
19384
+ base: updates.base,
19385
+ maintainer_can_modify: updates.maintainerCanModify
19386
+ })
19387
+ });
19388
+ return mapPR(response);
19389
+ });
19390
+ }
19391
+ async function mergePR(adapter, owner, repo, number4, options = {}) {
19392
+ return withActionError(`merge GitHub pull request #${number4} in ${owner}/${repo}`, async () => {
19393
+ assertOwnerRepo(owner, repo);
19394
+ assertPositiveInteger(number4, "pull request number");
19395
+ await adapter.request("PUT", repoEndpoint(owner, repo, `/pulls/${number4}/merge`), {
19396
+ body: removeUndefinedValues({
19397
+ commit_title: options.commitTitle,
19398
+ commit_message: options.commitMessage,
19399
+ merge_method: options.mergeMethod
19400
+ })
19401
+ });
19402
+ return getPR(adapter, owner, repo, number4);
19403
+ });
19404
+ }
19405
+ function mapPR(value) {
19406
+ const pull = asRecord(value, "pull request");
19407
+ const base = asRecord(pull.base, "pull request base");
19408
+ const head = asRecord(pull.head, "pull request head");
19409
+ const baseRepo = optionalRecord(base.repo);
19410
+ const headRepo = optionalRecord(head.repo);
19411
+ return {
19412
+ number: numberValue(pull.number),
19413
+ id: numberValue(pull.id),
19414
+ title: stringValue(pull.title),
19415
+ body: optionalString(pull.body),
19416
+ user: mapGitHubOwner(pull.user),
19417
+ state: stateValue(pull.state),
19418
+ draft: booleanValue(pull.draft),
19419
+ locked: booleanValue(pull.locked),
19420
+ mergeable: typeof pull.mergeable === "boolean" ? pull.mergeable : void 0,
19421
+ mergeableState: stringValue(pull.mergeable_state),
19422
+ merged: booleanValue(pull.merged),
19423
+ mergedAt: optionalString(pull.merged_at),
19424
+ mergedBy: pull.merged_by ? mapLogin(pull.merged_by) : void 0,
19425
+ base: {
19426
+ ref: stringValue(base.ref),
19427
+ sha: stringValue(base.sha),
19428
+ repo: {
19429
+ name: stringValue(baseRepo?.name),
19430
+ fullName: stringValue(baseRepo?.full_name)
19431
+ }
19432
+ },
19433
+ head: {
19434
+ ref: stringValue(head.ref),
19435
+ sha: stringValue(head.sha),
19436
+ repo: headRepo ? {
19437
+ name: stringValue(headRepo.name),
19438
+ fullName: stringValue(headRepo.full_name)
19439
+ } : void 0
19440
+ },
19441
+ requestedReviewers: mapLogins(pull.requested_reviewers),
19442
+ labels: Array.isArray(pull.labels) ? pull.labels.map(mapPullLabel) : [],
19443
+ commentsCount: numberValue(pull.comments),
19444
+ reviewCommentsCount: numberValue(pull.review_comments),
19445
+ commitsCount: numberValue(pull.commits),
19446
+ additionsCount: numberValue(pull.additions),
19447
+ deletionsCount: numberValue(pull.deletions),
19448
+ changedFilesCount: numberValue(pull.changed_files),
19449
+ createdAt: stringValue(pull.created_at),
19450
+ updatedAt: stringValue(pull.updated_at)
19451
+ };
19452
+ }
19453
+ function mapPullLabel(value) {
19454
+ if (typeof value === "string") {
19455
+ return {
19456
+ name: value,
19457
+ color: ""
19458
+ };
19459
+ }
19460
+ const label = asRecord(value, "pull request label");
19461
+ return {
19462
+ name: stringValue(label.name),
19463
+ color: stringValue(label.color)
19464
+ };
19465
+ }
19466
+ var init_pulls = __esm({
19467
+ "packages/github-primitive/src/actions/pulls.ts"() {
19468
+ "use strict";
19469
+ init_utils();
19470
+ }
19471
+ });
19472
+
19473
+ // packages/github-primitive/src/actions/repos.ts
19474
+ async function listRepos(adapter, options = {}) {
19475
+ return withActionError("list GitHub repositories", async () => {
19476
+ const query = queryWithPerPage(
19477
+ {
19478
+ visibility: options.visibility,
19479
+ affiliation: options.affiliation,
19480
+ sort: options.sort,
19481
+ direction: options.direction
19482
+ },
19483
+ options.perPage
19484
+ );
19485
+ const response = await adapter.request("GET", "/user/repos", { query });
19486
+ return asArray(response, "repositories").map(mapRepo);
19487
+ });
19488
+ }
19489
+ async function getRepo(adapter, owner, repo) {
19490
+ return withActionError(`get GitHub repository ${owner}/${repo}`, async () => {
19491
+ const response = await adapter.request("GET", repoEndpoint(owner, repo));
19492
+ return mapRepo(response);
19493
+ });
19494
+ }
19495
+ function mapRepo(value) {
19496
+ const repo = asRecord(value, "repository");
19497
+ const isPrivate = booleanValue(repo.private);
19498
+ const permissions = optionalRecord(repo.permissions);
19499
+ return {
19500
+ id: numberValue(repo.id),
19501
+ name: stringValue(repo.name),
19502
+ fullName: stringValue(repo.full_name, stringValue(repo.name)),
19503
+ owner: mapGitHubOwner(repo.owner),
19504
+ description: optionalString(repo.description),
19505
+ private: isPrivate,
19506
+ fork: booleanValue(repo.fork),
19507
+ createdAt: stringValue(repo.created_at),
19508
+ updatedAt: stringValue(repo.updated_at),
19509
+ pushedAt: stringValue(repo.pushed_at),
19510
+ size: numberValue(repo.size),
19511
+ stargazersCount: numberValue(repo.stargazers_count),
19512
+ watchersCount: numberValue(repo.watchers_count),
19513
+ language: optionalString(repo.language),
19514
+ forksCount: numberValue(repo.forks_count),
19515
+ openIssuesCount: numberValue(repo.open_issues_count),
19516
+ defaultBranch: stringValue(repo.default_branch),
19517
+ topics: Array.isArray(repo.topics) ? repo.topics.filter(isString) : [],
19518
+ visibility: visibilityValue(repo.visibility, isPrivate),
19519
+ permissions: permissions ? {
19520
+ admin: booleanValue(permissions.admin),
19521
+ maintain: booleanValue(permissions.maintain),
19522
+ push: booleanValue(permissions.push),
19523
+ triage: booleanValue(permissions.triage),
19524
+ pull: booleanValue(permissions.pull)
19525
+ } : void 0
19526
+ };
19527
+ }
19528
+ function isString(value) {
19529
+ return typeof value === "string";
19530
+ }
19531
+ var init_repos = __esm({
19532
+ "packages/github-primitive/src/actions/repos.ts"() {
19533
+ "use strict";
19534
+ init_utils();
19535
+ }
19536
+ });
19537
+
19538
+ // packages/github-primitive/src/actions/users.ts
19539
+ async function getUser(adapter, params = {}) {
19540
+ return withActionError("get GitHub user", async () => {
19541
+ const path25 = params.username ? `/users/${encodeURIComponent(assertNonEmptyString(params.username, "username"))}` : "/user";
19542
+ const response = await adapter.request("GET", path25);
19543
+ return mapUser(response);
19544
+ });
19545
+ }
19546
+ async function listOrganizations(adapter, params = {}) {
19547
+ return withActionError("list GitHub organizations", async () => {
19548
+ const path25 = params.username ? `/users/${encodeURIComponent(assertNonEmptyString(params.username, "username"))}/orgs` : "/user/orgs";
19549
+ const response = await adapter.request("GET", path25, {
19550
+ query: queryWithPerPage({}, params.perPage)
19551
+ });
19552
+ return asArray(response, "organizations").map(mapOrganization);
19553
+ });
19554
+ }
19555
+ function mapUser(value) {
19556
+ const user = asRecord(value, "user");
19557
+ const login = stringValue(user.login);
19558
+ if (!login) {
19559
+ throw new Error("GitHub user response did not include a login.");
19560
+ }
19561
+ return {
19562
+ login,
19563
+ name: optionalString(user.name),
19564
+ id: numberValue(user.id),
19565
+ type: optionalString(user.type)
19566
+ };
19567
+ }
19568
+ function mapOrganization(value) {
19569
+ const organization = asRecord(value, "organization");
19570
+ return {
19571
+ login: stringValue(organization.login),
19572
+ id: numberValue(organization.id),
19573
+ description: optionalString(organization.description),
19574
+ url: optionalString(organization.url),
19575
+ avatarUrl: optionalString(organization.avatar_url)
19576
+ };
19577
+ }
19578
+ var init_users = __esm({
19579
+ "packages/github-primitive/src/actions/users.ts"() {
19580
+ "use strict";
19581
+ init_utils();
19582
+ }
19583
+ });
19584
+
19585
+ // packages/github-primitive/src/local-runtime.ts
19586
+ var local_runtime_exports = {};
19587
+ __export(local_runtime_exports, {
19588
+ GhCliClient: () => GhCliClient,
19589
+ GhCliError: () => GhCliError
19590
+ });
19591
+ var import_node_child_process10, GhCliError, GhCliClient;
19592
+ var init_local_runtime = __esm({
19593
+ "packages/github-primitive/src/local-runtime.ts"() {
19594
+ "use strict";
19595
+ import_node_child_process10 = require("node:child_process");
19596
+ init_adapter();
19597
+ init_utils();
19598
+ init_types();
19599
+ GhCliError = class extends Error {
19600
+ command;
19601
+ args;
19602
+ exitCode;
19603
+ stdout;
19604
+ stderr;
19605
+ cause;
19606
+ constructor(message, options) {
19607
+ super(message);
19608
+ this.name = "GhCliError";
19609
+ this.command = options.command;
19610
+ this.args = options.args;
19611
+ this.exitCode = options.exitCode;
19612
+ this.stdout = options.stdout ?? "";
19613
+ this.stderr = options.stderr ?? "";
19614
+ this.cause = options.cause;
19615
+ }
19616
+ };
19617
+ GhCliClient = class extends BaseGitHubAdapter {
19618
+ constructor(config2 = {}) {
19619
+ super({
19620
+ ...config2,
19621
+ runtime: "local"
19622
+ });
19623
+ }
19624
+ getRuntime() {
19625
+ return "local";
19626
+ }
19627
+ async isAuthenticated() {
19628
+ try {
19629
+ await this.runGhCommand(["auth", "status"], {
19630
+ parseJson: false,
19631
+ timeout: Math.min(this.config.timeout, 1e4)
19632
+ });
19633
+ return true;
19634
+ } catch {
19635
+ return false;
19636
+ }
19637
+ }
19638
+ async getCurrentUser() {
19639
+ const user = await this.request("GET", "/user");
19640
+ if (!user.login) {
19641
+ throw new GitHubApiError("GitHub user response did not include a login.");
19642
+ }
19643
+ return {
19644
+ login: user.login,
19645
+ name: user.name ?? void 0,
19646
+ id: user.id,
19647
+ type: user.type
19648
+ };
19649
+ }
19650
+ async request(method, path25, options = {}) {
19651
+ return this.executeWithRetries(async () => {
19652
+ const request = this.buildApiCommand(method, path25, options);
19653
+ const result = await this.runGhCommand(request.args, {
19654
+ input: request.input,
19655
+ parseJson: true,
19656
+ allowEmpty: true,
19657
+ timeout: options.timeout ?? this.config.timeout,
19658
+ signal: options.signal
19659
+ });
19660
+ return result.data;
19661
+ });
19662
+ }
19663
+ runGhCommand(args, options = {}) {
19664
+ const command = this.config.ghPath;
19665
+ const timeout = options.timeout ?? this.config.timeout;
19666
+ const env = {
19667
+ ...process.env,
19668
+ ...this.config.env,
19669
+ ...options.env
19670
+ };
19671
+ return new Promise((resolve4, reject) => {
19672
+ const child = (0, import_node_child_process10.spawn)(command, args, {
19673
+ cwd: options.cwd ?? this.config.cwd,
19674
+ env,
19675
+ stdio: ["pipe", "pipe", "pipe"]
19676
+ });
19677
+ let stdout = "";
19678
+ let stderr = "";
19679
+ let finished = false;
19680
+ const finish = (callback) => {
19681
+ if (finished) {
19682
+ return;
19683
+ }
19684
+ finished = true;
19685
+ clearTimeout(timer);
19686
+ options.signal?.removeEventListener("abort", abort);
19687
+ callback();
19688
+ };
19689
+ const rejectWith = (error51) => {
19690
+ finish(() => reject(error51));
19691
+ };
19692
+ const abort = () => {
19693
+ child.kill("SIGTERM");
19694
+ rejectWith(
19695
+ new GhCliError(`gh command aborted: ${command} ${args.join(" ")}`, {
19696
+ command,
19697
+ args,
19698
+ stdout,
19699
+ stderr
19700
+ })
19701
+ );
19702
+ };
19703
+ const timer = setTimeout(() => {
19704
+ child.kill("SIGTERM");
19705
+ rejectWith(
19706
+ new GhCliError(`gh command timed out after ${timeout}ms: ${command} ${args.join(" ")}`, {
19707
+ command,
19708
+ args,
19709
+ stdout,
19710
+ stderr
19711
+ })
19712
+ );
19713
+ }, timeout);
19714
+ if (options.signal?.aborted) {
19715
+ abort();
19716
+ return;
19717
+ }
19718
+ options.signal?.addEventListener("abort", abort, { once: true });
19719
+ child.stdout.setEncoding("utf8");
19720
+ child.stderr.setEncoding("utf8");
19721
+ child.stdout.on("data", (chunk) => {
19722
+ stdout += chunk;
19723
+ });
19724
+ child.stderr.on("data", (chunk) => {
19725
+ stderr += chunk;
19726
+ });
19727
+ child.on("error", (error51) => {
19728
+ rejectWith(
19729
+ new GhCliError(`Failed to start gh command: ${error51.message}`, {
19730
+ command,
19731
+ args,
19732
+ stdout,
19733
+ stderr,
19734
+ cause: error51
19735
+ })
19736
+ );
19737
+ });
19738
+ child.on("close", (exitCode) => {
19739
+ if (finished) {
19740
+ return;
19741
+ }
19742
+ if (exitCode !== 0) {
19743
+ rejectWith(
19744
+ new GhCliError(stderr.trim() || `gh command failed with exit code ${exitCode}`, {
19745
+ command,
19746
+ args,
19747
+ exitCode: exitCode ?? void 0,
19748
+ stdout,
19749
+ stderr
19750
+ })
19751
+ );
19752
+ return;
19753
+ }
19754
+ try {
19755
+ const data = this.parseCommandOutput(stdout, options);
19756
+ finish(
19757
+ () => resolve4({
19758
+ args,
19759
+ command,
19760
+ exitCode: exitCode ?? 0,
19761
+ stdout,
19762
+ stderr,
19763
+ data
19764
+ })
19765
+ );
19766
+ } catch (error51) {
19767
+ rejectWith(
19768
+ new GhCliError(error51 instanceof Error ? error51.message : String(error51), {
19769
+ command,
19770
+ args,
19771
+ exitCode: exitCode ?? void 0,
19772
+ stdout,
19773
+ stderr,
19774
+ cause: error51
19775
+ })
19776
+ );
19777
+ }
19778
+ });
19779
+ if (typeof options.input === "string") {
19780
+ child.stdin.end(options.input);
19781
+ } else {
19782
+ child.stdin.end();
19783
+ }
19784
+ });
19785
+ }
19786
+ buildApiCommand(method, path25, options) {
19787
+ const args = [
19788
+ "api",
19789
+ appendQuery(path25, options.query),
19790
+ "--method",
19791
+ method,
19792
+ "--header",
19793
+ "Accept: application/vnd.github+json",
19794
+ "--header",
19795
+ "X-GitHub-Api-Version: 2022-11-28"
19796
+ ];
19797
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
19798
+ args.push("--header", `${name}: ${value}`);
19799
+ }
19800
+ if (typeof options.body !== "undefined") {
19801
+ args.push("--input", "-");
19802
+ return {
19803
+ args,
19804
+ input: JSON.stringify(options.body)
19805
+ };
19806
+ }
19807
+ return { args };
19808
+ }
19809
+ parseCommandOutput(stdout, options) {
19810
+ if (options.parseJson === false) {
19811
+ return stdout;
19812
+ }
19813
+ const trimmed = stdout.trim();
19814
+ if (!trimmed) {
19815
+ if (options.allowEmpty) {
19816
+ return void 0;
19817
+ }
19818
+ throw new Error("gh command returned empty output where JSON was expected.");
19819
+ }
19820
+ try {
19821
+ return JSON.parse(trimmed);
19822
+ } catch (error51) {
19823
+ throw new Error(
19824
+ `Failed to parse gh JSON output: ${error51 instanceof Error ? error51.message : String(error51)}`
19825
+ );
19826
+ }
19827
+ }
19828
+ };
19829
+ }
19830
+ });
19831
+
19832
+ // packages/github-primitive/src/cloud-runtime.ts
19833
+ var cloud_runtime_exports = {};
19834
+ __export(cloud_runtime_exports, {
19835
+ NangoClient: () => NangoClient
19836
+ });
19837
+ async function parseJsonResponse(response) {
19838
+ const text = await response.text();
19839
+ if (!response.ok) {
19840
+ throw new GitHubApiError(
19841
+ text || `GitHub API request failed with ${response.status} ${response.statusText}`,
19842
+ {
19843
+ status: response.status,
19844
+ responseBody: text,
19845
+ responseHeaders: headersToRecord(response.headers)
19846
+ }
19847
+ );
19848
+ }
19849
+ if (!text.trim()) {
19850
+ return void 0;
19851
+ }
19852
+ try {
19853
+ return JSON.parse(text);
19854
+ } catch (error51) {
19855
+ throw new GitHubApiError(
19856
+ `Failed to parse GitHub API JSON response: ${error51 instanceof Error ? error51.message : String(error51)}`,
19857
+ {
19858
+ status: response.status,
19859
+ responseBody: text,
19860
+ responseHeaders: headersToRecord(response.headers),
19861
+ cause: error51
19862
+ }
19863
+ );
19864
+ }
19865
+ }
19866
+ function buildNangoProxyUrl(baseUrl, path25, query) {
19867
+ const base = trimTrailingSlash(baseUrl) ?? DEFAULT_NANGO_BASE_URL;
19868
+ const endpoint = stripLeadingSlash(path25);
19869
+ return appendQuery(`${base}/proxy/${endpoint}`, query);
19870
+ }
19871
+ function joinUrl(baseUrl, path25) {
19872
+ return `${trimTrailingSlash(baseUrl) ?? baseUrl}/${stripLeadingSlash(path25)}`;
19873
+ }
19874
+ function stripLeadingSlash(value) {
19875
+ return value.replace(/^\/+/, "");
19876
+ }
19877
+ function headersToRecord(headers) {
19878
+ const record2 = {};
19879
+ headers.forEach((value, key) => {
19880
+ record2[key] = value;
19881
+ });
19882
+ return record2;
19883
+ }
19884
+ function errorMessage2(error51) {
19885
+ return error51 instanceof Error ? error51.message : String(error51);
19886
+ }
19887
+ var NangoClient;
19888
+ var init_cloud_runtime = __esm({
19889
+ "packages/github-primitive/src/cloud-runtime.ts"() {
19890
+ "use strict";
19891
+ init_adapter();
19892
+ init_utils();
19893
+ init_constants();
19894
+ init_types();
19895
+ NangoClient = class extends BaseGitHubAdapter {
19896
+ lastNangoFallbackError;
19897
+ constructor(config2 = {}) {
19898
+ super({
19899
+ ...config2,
19900
+ runtime: "cloud"
19901
+ });
19902
+ }
19903
+ getRuntime() {
19904
+ return "cloud";
19905
+ }
19906
+ async isAuthenticated() {
19907
+ try {
19908
+ await this.getCurrentUser();
19909
+ return true;
19910
+ } catch {
19911
+ return false;
19912
+ }
19913
+ }
19914
+ async getCurrentUser() {
19915
+ const user = await this.request("GET", "/user");
19916
+ if (!user.login) {
19917
+ throw new GitHubApiError("GitHub user response did not include a login.");
19918
+ }
19919
+ return {
19920
+ login: user.login,
19921
+ name: user.name ?? void 0,
19922
+ id: user.id,
19923
+ type: user.type
19924
+ };
19925
+ }
19926
+ async request(method, path25, options = {}) {
19927
+ return this.executeWithRetries(async () => {
19928
+ if (this.hasNangoCredentials()) {
19929
+ try {
19930
+ return await this.requestViaNango(method, path25, options);
19931
+ } catch (error51) {
19932
+ if (!this.hasRelayCloudCredentials()) {
19933
+ throw error51;
19934
+ }
19935
+ this.lastNangoFallbackError = error51;
19936
+ try {
19937
+ return await this.requestViaRelayCloud(method, path25, options);
19938
+ } catch (relayError) {
19939
+ throw new GitHubApiError(
19940
+ `Nango GitHub proxy failed, then relay-cloud fallback failed: ${errorMessage2(relayError)}`,
19941
+ {
19942
+ cause: {
19943
+ nango: error51,
19944
+ relayCloud: relayError
19945
+ }
19946
+ }
19947
+ );
19948
+ }
19949
+ }
19950
+ }
19951
+ if (this.hasRelayCloudCredentials()) {
19952
+ return this.requestViaRelayCloud(method, path25, options);
19953
+ }
19954
+ throw new GitHubApiError(
19955
+ "Cloud GitHub runtime requires Nango credentials or relay-cloud proxy configuration."
19956
+ );
19957
+ });
19958
+ }
19959
+ /**
19960
+ * Returns the most recent Nango failure that triggered a relay-cloud fallback.
19961
+ */
19962
+ getLastNangoFallbackError() {
19963
+ return this.lastNangoFallbackError;
19964
+ }
19965
+ async requestViaNango(method, path25, options) {
19966
+ const secretKey = this.config.nango.secretKey;
19967
+ const connectionId = this.config.nango.connectionId;
19968
+ const providerConfigKey = this.config.nango.providerConfigKey;
19969
+ if (!secretKey || !connectionId || !providerConfigKey) {
19970
+ throw new GitHubApiError("Nango GitHub proxy requires secretKey, connectionId, and providerConfigKey.");
19971
+ }
19972
+ const url2 = buildNangoProxyUrl(this.config.nango.baseUrl, path25, options.query);
19973
+ const response = await this.fetchWithTimeout(url2, {
19974
+ method,
19975
+ headers: {
19976
+ Authorization: `Bearer ${secretKey}`,
19977
+ "Connection-Id": connectionId,
19978
+ "Provider-Config-Key": providerConfigKey,
19979
+ Accept: "application/json",
19980
+ "Content-Type": "application/json",
19981
+ "User-Agent": this.config.userAgent,
19982
+ ...options.headers
19983
+ },
19984
+ body: typeof options.body === "undefined" ? void 0 : JSON.stringify(options.body),
19985
+ signal: options.signal,
19986
+ timeout: options.timeout
19987
+ });
19988
+ return parseJsonResponse(response);
19989
+ }
19990
+ async requestViaRelayCloud(method, path25, options) {
19991
+ const apiUrl = this.config.relayCloud.apiUrl;
19992
+ const accessToken = this.config.relayCloud.accessToken;
19993
+ const endpoint = this.config.relayCloud.endpoint ?? DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT;
19994
+ if (!apiUrl || !accessToken) {
19995
+ throw new GitHubApiError("Relay cloud GitHub proxy requires apiUrl and accessToken configuration.");
19996
+ }
19997
+ const payload = {
19998
+ method,
19999
+ path: path25,
20000
+ query: options.query,
20001
+ body: options.body,
20002
+ headers: options.headers,
20003
+ nango: {
20004
+ connectionId: this.config.nango.connectionId,
20005
+ providerConfigKey: this.config.nango.providerConfigKey
20006
+ }
20007
+ };
20008
+ const response = await this.fetchWithTimeout(joinUrl(apiUrl, endpoint), {
20009
+ method: "POST",
20010
+ headers: {
20011
+ Authorization: `Bearer ${accessToken}`,
20012
+ Accept: "application/json",
20013
+ "Content-Type": "application/json",
20014
+ "User-Agent": this.config.userAgent,
20015
+ ...this.config.relayCloud.workspaceId ? { "X-Relay-Workspace-Id": this.config.relayCloud.workspaceId } : {}
20016
+ },
20017
+ body: JSON.stringify(payload),
20018
+ signal: options.signal,
20019
+ timeout: options.timeout
20020
+ });
20021
+ const result = await parseJsonResponse(response);
20022
+ if (typeof result === "object" && result !== null && "data" in result && Object.keys(result).some((key) => key === "data")) {
20023
+ return result.data;
20024
+ }
20025
+ return result;
20026
+ }
20027
+ async fetchWithTimeout(input, init) {
20028
+ const fetchImpl = this.config.fetch ?? fetch;
20029
+ const timeout = init.timeout ?? this.config.timeout;
20030
+ const signal = init.signal ?? AbortSignal.timeout(timeout);
20031
+ const { timeout: _timeout, ...requestInit } = init;
20032
+ return fetchImpl(input, {
20033
+ ...requestInit,
20034
+ signal
20035
+ });
20036
+ }
20037
+ hasNangoCredentials() {
20038
+ return Boolean(
20039
+ this.config.nango.secretKey && this.config.nango.connectionId && this.config.nango.providerConfigKey
20040
+ );
20041
+ }
20042
+ hasRelayCloudCredentials() {
20043
+ return Boolean(this.config.relayCloud.apiUrl && this.config.relayCloud.accessToken);
20044
+ }
20045
+ };
20046
+ }
20047
+ });
20048
+
20049
+ // packages/github-primitive/src/adapter.ts
20050
+ function normalizeGitHubRuntimeConfig(config2 = {}) {
20051
+ const env = config2.env ?? process.env;
20052
+ const nango = config2.nango ?? {};
20053
+ const relayCloud = config2.relayCloud ?? {};
20054
+ return {
20055
+ ...config2,
20056
+ runtime: config2.runtime ?? "auto",
20057
+ ghPath: nonEmpty(config2.ghPath) ?? nonEmpty(env.GH_PATH) ?? DEFAULT_GH_PATH,
20058
+ cwd: config2.cwd,
20059
+ env,
20060
+ timeout: config2.timeout ?? DEFAULT_TIMEOUT,
20061
+ retryOnRateLimit: config2.retryOnRateLimit ?? true,
20062
+ maxRetries: config2.maxRetries ?? DEFAULT_MAX_RETRIES,
20063
+ userAgent: config2.userAgent ?? DEFAULT_USER_AGENT,
20064
+ fetch: config2.fetch,
20065
+ nango: {
20066
+ connectionId: nonEmpty(nango.connectionId) ?? nonEmpty(env.NANGO_GITHUB_CONNECTION_ID) ?? nonEmpty(env.GITHUB_NANGO_CONNECTION_ID) ?? nonEmpty(env.NANGO_CONNECTION_ID),
20067
+ providerConfigKey: nonEmpty(nango.providerConfigKey) ?? nonEmpty(env.NANGO_GITHUB_PROVIDER_CONFIG_KEY) ?? nonEmpty(env.GITHUB_NANGO_PROVIDER_CONFIG_KEY) ?? nonEmpty(env.NANGO_PROVIDER_CONFIG_KEY) ?? DEFAULT_NANGO_PROVIDER_CONFIG_KEY,
20068
+ secretKey: nonEmpty(nango.secretKey) ?? nonEmpty(env.NANGO_SECRET_KEY),
20069
+ baseUrl: trimTrailingSlash(nonEmpty(nango.baseUrl) ?? nonEmpty(env.NANGO_HOST)) ?? DEFAULT_NANGO_BASE_URL
20070
+ },
20071
+ relayCloud: {
20072
+ apiUrl: trimTrailingSlash(
20073
+ nonEmpty(relayCloud.apiUrl) ?? nonEmpty(env.RELAY_CLOUD_API_URL) ?? nonEmpty(env.CLOUD_API_URL)
20074
+ ) ?? void 0,
20075
+ accessToken: nonEmpty(relayCloud.accessToken) ?? nonEmpty(env.RELAY_CLOUD_API_TOKEN) ?? nonEmpty(env.CLOUD_API_ACCESS_TOKEN) ?? nonEmpty(env.WORKSPACE_TOKEN),
20076
+ workspaceId: nonEmpty(relayCloud.workspaceId) ?? nonEmpty(env.WORKSPACE_ID),
20077
+ workspaceToken: nonEmpty(relayCloud.workspaceToken) ?? nonEmpty(env.WORKSPACE_TOKEN),
20078
+ endpoint: nonEmpty(relayCloud.endpoint) ?? nonEmpty(env.RELAY_CLOUD_GITHUB_PROXY_ENDPOINT) ?? DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT
20079
+ }
20080
+ };
20081
+ }
20082
+ function detectGitHubRuntime(config2 = {}) {
20083
+ return GitHubRuntimeDetector.detect(config2);
20084
+ }
20085
+ function createGitHubAdapter(config2 = {}) {
20086
+ return GitHubAdapterFactory.create(config2);
20087
+ }
20088
+ async function testLocalRuntime(config2) {
20089
+ try {
20090
+ const { stdout } = await execFileAsync2(config2.ghPath, ["--version"], {
20091
+ cwd: config2.cwd,
20092
+ env: config2.env,
20093
+ timeout: Math.min(config2.timeout, 5e3),
20094
+ maxBuffer: 1024 * 1024
20095
+ });
20096
+ const version2 = String(stdout).split("\n")[0]?.trim();
20097
+ return {
20098
+ runtime: "local",
20099
+ available: true,
20100
+ reason: version2 ? `gh CLI available: ${version2}` : "gh CLI available.",
20101
+ details: version2 ? { version: version2 } : void 0
20102
+ };
20103
+ } catch (error51) {
20104
+ return {
20105
+ runtime: "local",
20106
+ available: false,
20107
+ reason: `gh CLI was not available at "${config2.ghPath}".`,
20108
+ error: errorMessage3(error51)
20109
+ };
20110
+ }
20111
+ }
20112
+ async function testCloudRuntime(config2) {
20113
+ if (hasNangoConfig(config2)) {
20114
+ return {
20115
+ runtime: "cloud",
20116
+ available: true,
20117
+ reason: "Nango configuration is available.",
20118
+ details: {
20119
+ providerConfigKey: config2.nango.providerConfigKey ?? DEFAULT_NANGO_PROVIDER_CONFIG_KEY,
20120
+ hasConnectionId: Boolean(config2.nango.connectionId)
20121
+ }
20122
+ };
20123
+ }
20124
+ if (hasRelayCloudConfig(config2)) {
20125
+ return {
20126
+ runtime: "cloud",
20127
+ available: true,
20128
+ reason: "Relay cloud API configuration is available.",
20129
+ details: {
20130
+ endpoint: config2.relayCloud.endpoint ?? DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT,
20131
+ hasWorkspaceId: Boolean(config2.relayCloud.workspaceId)
20132
+ }
20133
+ };
20134
+ }
20135
+ return {
20136
+ runtime: "cloud",
20137
+ available: false,
20138
+ reason: "No Nango or relay-cloud GitHub proxy configuration was found."
20139
+ };
20140
+ }
20141
+ function detectionResult(input) {
20142
+ return {
20143
+ runtime: input.runtime,
20144
+ requestedRuntime: input.requestedRuntime,
20145
+ source: input.source,
20146
+ available: input.selected.available,
20147
+ reason: input.reason,
20148
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
20149
+ local: input.local,
20150
+ cloud: input.cloud
20151
+ };
20152
+ }
20153
+ function hasNangoConfig(config2) {
20154
+ return Boolean(config2.nango.secretKey);
20155
+ }
20156
+ function hasRelayCloudConfig(config2) {
20157
+ return Boolean(config2.relayCloud.apiUrl && config2.relayCloud.accessToken);
20158
+ }
20159
+ function hasCloudEnvironment(env) {
20160
+ return Boolean(
20161
+ env.WORKSPACE_ID || env.CLOUD_API_URL || env.VERCEL || env.RAILWAY_ENVIRONMENT || env.FLY_APP_NAME || env.AWS_REGION || env.GOOGLE_CLOUD_PROJECT || env.NODE_ENV === "production"
20162
+ );
20163
+ }
20164
+ function statusFromError(error51) {
20165
+ if (error51 instanceof GitHubApiError) {
20166
+ return error51.status;
20167
+ }
20168
+ if (typeof error51 === "object" && error51 !== null && "status" in error51) {
20169
+ const status = error51.status;
20170
+ return typeof status === "number" ? status : void 0;
20171
+ }
20172
+ return void 0;
20173
+ }
20174
+ function resetHeaderFromError(error51) {
20175
+ const headers = error51 instanceof GitHubApiError ? error51.responseHeaders : typeof error51 === "object" && error51 !== null && "responseHeaders" in error51 ? error51.responseHeaders : void 0;
20176
+ return headers?.["x-ratelimit-reset"] ?? headers?.["X-RateLimit-Reset"];
20177
+ }
20178
+ function stringifyOutput(value) {
20179
+ if (typeof value === "string") {
20180
+ return value;
20181
+ }
20182
+ if (typeof value === "undefined") {
20183
+ return "";
20184
+ }
20185
+ return JSON.stringify(value);
20186
+ }
20187
+ function errorMessage3(error51) {
20188
+ return error51 instanceof Error ? error51.message : String(error51);
20189
+ }
20190
+ function delay3(ms2) {
20191
+ return new Promise((resolve4) => {
20192
+ setTimeout(resolve4, ms2);
20193
+ });
20194
+ }
20195
+ var import_node_child_process11, import_node_util4, execFileAsync2, GitHubRuntimeDetector, BaseGitHubAdapter, GitHubAdapterFactory, GitHubClientFactory;
20196
+ var init_adapter = __esm({
20197
+ "packages/github-primitive/src/adapter.ts"() {
20198
+ "use strict";
20199
+ import_node_child_process11 = require("node:child_process");
20200
+ import_node_util4 = require("node:util");
20201
+ init_branches();
20202
+ init_commits();
20203
+ init_files();
20204
+ init_issues();
20205
+ init_pulls();
20206
+ init_repos();
20207
+ init_users();
20208
+ init_utils();
20209
+ init_constants();
20210
+ init_types();
20211
+ execFileAsync2 = (0, import_node_util4.promisify)(import_node_child_process11.execFile);
20212
+ GitHubRuntimeDetector = class {
20213
+ static async detect(config2 = {}) {
20214
+ const normalized = normalizeGitHubRuntimeConfig(config2);
20215
+ const [local, cloud] = await Promise.all([
20216
+ this.testRuntime("local", normalized),
20217
+ this.testRuntime("cloud", normalized)
20218
+ ]);
20219
+ const requestedRuntime = normalized.runtime;
20220
+ if (requestedRuntime === "local" || requestedRuntime === "cloud") {
20221
+ const selected = requestedRuntime === "local" ? local : cloud;
20222
+ return detectionResult({
20223
+ runtime: requestedRuntime,
20224
+ requestedRuntime,
20225
+ source: "config",
20226
+ selected,
20227
+ local,
20228
+ cloud,
20229
+ reason: selected.available ? `Runtime explicitly configured as ${requestedRuntime}.` : `Runtime explicitly configured as ${requestedRuntime}, but availability check failed: ${selected.reason}`
20230
+ });
20231
+ }
20232
+ if (hasNangoConfig(normalized)) {
20233
+ return detectionResult({
20234
+ runtime: "cloud",
20235
+ requestedRuntime,
20236
+ source: "nango",
20237
+ selected: cloud,
20238
+ local,
20239
+ cloud,
20240
+ reason: cloud.available ? "Using cloud runtime because Nango configuration is available." : `Cloud runtime selected from Nango configuration, but availability check failed: ${cloud.reason}`
20241
+ });
20242
+ }
20243
+ if (hasCloudEnvironment(normalized.env)) {
20244
+ if (cloud.available) {
20245
+ return detectionResult({
20246
+ runtime: "cloud",
20247
+ requestedRuntime,
20248
+ source: "environment",
20249
+ selected: cloud,
20250
+ local,
20251
+ cloud,
20252
+ reason: "Using cloud runtime because a cloud workspace or deployment environment was detected."
20253
+ });
20254
+ }
20255
+ if (local.available) {
20256
+ return detectionResult({
20257
+ runtime: "local",
20258
+ requestedRuntime,
20259
+ source: "gh-cli",
20260
+ selected: local,
20261
+ local,
20262
+ cloud,
20263
+ reason: "Cloud environment was detected, but cloud credentials were unavailable; using local gh CLI."
20264
+ });
20265
+ }
20266
+ }
20267
+ if (local.available) {
20268
+ return detectionResult({
20269
+ runtime: "local",
20270
+ requestedRuntime,
20271
+ source: "gh-cli",
20272
+ selected: local,
20273
+ local,
20274
+ cloud,
20275
+ reason: "Using local runtime because gh CLI is available."
20276
+ });
20277
+ }
20278
+ return detectionResult({
20279
+ runtime: "cloud",
20280
+ requestedRuntime,
20281
+ source: "fallback",
20282
+ selected: cloud,
20283
+ local,
20284
+ cloud,
20285
+ reason: cloud.available ? "Using cloud runtime because local gh CLI was unavailable." : "Falling back to cloud runtime because local gh CLI was unavailable; cloud credentials may still be required."
20286
+ });
20287
+ }
20288
+ static async testRuntime(runtime, config2 = {}) {
20289
+ const normalized = normalizeGitHubRuntimeConfig(config2);
20290
+ if (runtime === "local") {
20291
+ return testLocalRuntime(normalized);
20292
+ }
20293
+ return testCloudRuntime(normalized);
20294
+ }
20295
+ static async detectRuntime(config2 = {}) {
20296
+ const result = await this.detect(config2);
20297
+ return result.runtime;
20298
+ }
20299
+ };
20300
+ BaseGitHubAdapter = class extends GitHubClientInterface {
20301
+ retryUsed = false;
20302
+ constructor(config2 = {}) {
20303
+ super(normalizeGitHubRuntimeConfig(config2));
20304
+ }
20305
+ async executeAction(action, params) {
20306
+ const startedAt = Date.now();
20307
+ this.retryUsed = false;
20308
+ try {
20309
+ const data = await this.dispatchAction(action, params);
20310
+ return {
20311
+ success: true,
20312
+ output: stringifyOutput(data),
20313
+ data,
20314
+ metadata: {
20315
+ runtime: this.getRuntime(),
20316
+ executionTime: Date.now() - startedAt,
20317
+ retried: this.retryUsed
20318
+ }
20319
+ };
20320
+ } catch (error51) {
20321
+ return {
20322
+ success: false,
20323
+ output: "",
20324
+ error: errorMessage3(error51),
20325
+ metadata: {
20326
+ runtime: this.getRuntime(),
20327
+ executionTime: Date.now() - startedAt,
20328
+ retried: this.retryUsed
20329
+ }
20330
+ };
20331
+ }
20332
+ }
20333
+ async listRepositories(params = {}) {
20334
+ return listRepos(this, params);
20335
+ }
20336
+ async getRepository(params) {
20337
+ return getRepo(this, params.owner, params.repo);
20338
+ }
20339
+ async listIssues(params) {
20340
+ const { owner, repo, ...options } = params;
20341
+ return listIssues(this, owner, repo, options);
20342
+ }
20343
+ async createIssue(params) {
20344
+ const { owner, repo, title, body, ...options } = params;
20345
+ return createIssue(this, owner, repo, title, body, options);
20346
+ }
20347
+ async updateIssue(params) {
20348
+ const { owner, repo, issueNumber, ...updates } = params;
20349
+ return updateIssue(this, owner, repo, issueNumber, updates);
20350
+ }
20351
+ async closeIssue(params) {
20352
+ return updateIssue(this, params.owner, params.repo, params.issueNumber, {
20353
+ state: "closed"
20354
+ });
20355
+ }
20356
+ async listPullRequests(params) {
20357
+ const { owner, repo, ...options } = params;
20358
+ return listPRs(this, owner, repo, options);
20359
+ }
20360
+ async getPullRequest(params) {
20361
+ return getPR(this, params.owner, params.repo, params.pullNumber);
20362
+ }
20363
+ async createPullRequest(params) {
20364
+ const { owner, repo, title, body, base, head, ...options } = params;
20365
+ return createPR(this, owner, repo, title, body, base, head, options);
20366
+ }
20367
+ async updatePullRequest(params) {
20368
+ const { owner, repo, pullNumber, ...updates } = params;
20369
+ return updatePR(this, owner, repo, pullNumber, updates);
20370
+ }
20371
+ async mergePullRequest(params) {
20372
+ const { owner, repo, pullNumber, ...options } = params;
20373
+ return mergePR(this, owner, repo, pullNumber, options);
20374
+ }
20375
+ async listFiles(params) {
20376
+ const { owner, repo, path: path25, ...options } = params;
20377
+ return listFiles(this, owner, repo, path25, options);
20378
+ }
20379
+ async readFile(params) {
20380
+ return readFile3(this, params.owner, params.repo, params.path, params.ref);
20381
+ }
20382
+ async createFile(params) {
20383
+ const { owner, repo, path: path25, content, message, ...options } = params;
20384
+ return createFile(this, owner, repo, path25, content, message, options);
20385
+ }
20386
+ async updateFile(params) {
20387
+ const { owner, repo, path: path25, content, message, sha, ...options } = params;
20388
+ return updateFile(this, owner, repo, path25, content, message, sha, options);
20389
+ }
20390
+ async deleteFile(params) {
20391
+ const { owner, repo, path: path25, sha, message, ...options } = params;
20392
+ return deleteFile(this, owner, repo, path25, sha, message, options);
20393
+ }
20394
+ async listBranches(params) {
20395
+ return listBranches(this, params.owner, params.repo);
20396
+ }
20397
+ async createBranch(params) {
20398
+ return createBranch(this, params);
20399
+ }
20400
+ async listCommits(params) {
20401
+ return listCommits(this, params);
20402
+ }
20403
+ async createCommit(params) {
20404
+ return createCommit(this, params);
20405
+ }
20406
+ async getUser(params) {
20407
+ return getUser(this, params);
20408
+ }
20409
+ async listOrganizations(params) {
20410
+ return listOrganizations(this, params);
20411
+ }
20412
+ async executeWithRetries(operation) {
20413
+ const maxRetries = this.config.retryOnRateLimit ? this.config.maxRetries : 0;
20414
+ let attempt = 0;
20415
+ while (true) {
20416
+ try {
20417
+ return await operation();
20418
+ } catch (error51) {
20419
+ if (attempt >= maxRetries || !this.isRetryableError(error51)) {
20420
+ throw error51;
20421
+ }
20422
+ attempt += 1;
20423
+ this.retryUsed = true;
20424
+ await delay3(this.retryDelayMs(attempt, error51));
20425
+ }
20426
+ }
20427
+ }
20428
+ isRetryableError(error51) {
20429
+ const status = statusFromError(error51);
20430
+ return status === 403 || status === 429 || typeof status === "number" && status >= 500;
20431
+ }
20432
+ retryDelayMs(attempt, error51) {
20433
+ const reset = resetHeaderFromError(error51);
20434
+ if (reset) {
20435
+ const resetMs = Number(reset) * 1e3;
20436
+ if (Number.isFinite(resetMs) && resetMs > Date.now()) {
20437
+ return Math.min(resetMs - Date.now(), 6e4);
20438
+ }
20439
+ }
20440
+ return Math.min(500 * 2 ** (attempt - 1), 1e4);
20441
+ }
20442
+ async dispatchAction(action, params) {
20443
+ switch (action) {
20444
+ case "listRepos" /* ListRepos */:
20445
+ return this.listRepositories(params);
20446
+ case "getRepo" /* GetRepo */:
20447
+ return this.getRepository(params);
20448
+ case "listIssues" /* ListIssues */:
20449
+ return this.listIssues(params);
20450
+ case "createIssue" /* CreateIssue */:
20451
+ return this.createIssue(params);
20452
+ case "updateIssue" /* UpdateIssue */:
20453
+ return this.updateIssue(params);
20454
+ case "closeIssue" /* CloseIssue */:
20455
+ return this.closeIssue(params);
20456
+ case "listPRs" /* ListPRs */:
20457
+ return this.listPullRequests(params);
20458
+ case "getPR" /* GetPR */:
20459
+ return this.getPullRequest(params);
20460
+ case "createPR" /* CreatePR */:
20461
+ return this.createPullRequest(params);
20462
+ case "updatePR" /* UpdatePR */:
20463
+ return this.updatePullRequest(params);
20464
+ case "mergePR" /* MergePR */:
20465
+ return this.mergePullRequest(params);
20466
+ case "listFiles" /* ListFiles */:
20467
+ return this.listFiles(params);
20468
+ case "readFile" /* ReadFile */:
20469
+ return this.readFile(params);
20470
+ case "createFile" /* CreateFile */:
20471
+ return this.createFile(params);
20472
+ case "updateFile" /* UpdateFile */:
20473
+ return this.updateFile(params);
20474
+ case "deleteFile" /* DeleteFile */:
20475
+ return this.deleteFile(params);
20476
+ case "createBranch" /* CreateBranch */:
20477
+ return this.createBranch(params);
20478
+ case "listBranches" /* ListBranches */:
20479
+ return this.listBranches(params);
20480
+ case "listCommits" /* ListCommits */:
20481
+ return this.listCommits(params);
20482
+ case "createCommit" /* CreateCommit */:
20483
+ return this.createCommit(params);
20484
+ case "getUser" /* GetUser */:
20485
+ return this.getUser(params);
20486
+ case "listOrganizations" /* ListOrganizations */:
20487
+ return this.listOrganizations(params);
20488
+ default:
20489
+ throw new Error(`Unsupported GitHub action: ${String(action)}`);
20490
+ }
20491
+ }
20492
+ };
20493
+ GitHubAdapterFactory = class {
20494
+ static async create(config2 = {}) {
20495
+ const detection = await GitHubRuntimeDetector.detect(config2);
20496
+ const runtimeConfig = {
20497
+ ...config2,
20498
+ runtime: detection.runtime
20499
+ };
20500
+ if (detection.runtime === "local") {
20501
+ const { GhCliClient: GhCliClient2 } = await Promise.resolve().then(() => (init_local_runtime(), local_runtime_exports));
20502
+ return new GhCliClient2(runtimeConfig);
20503
+ }
20504
+ const { NangoClient: NangoClient2 } = await Promise.resolve().then(() => (init_cloud_runtime(), cloud_runtime_exports));
20505
+ return new NangoClient2(runtimeConfig);
20506
+ }
20507
+ static detect(config2 = {}) {
20508
+ return GitHubRuntimeDetector.detect(config2);
20509
+ }
20510
+ static detectRuntime(config2 = {}) {
20511
+ return GitHubRuntimeDetector.detectRuntime(config2);
20512
+ }
20513
+ static testRuntime(runtime, config2 = {}) {
20514
+ return GitHubRuntimeDetector.testRuntime(runtime, config2);
20515
+ }
20516
+ };
20517
+ GitHubClientFactory = GitHubAdapterFactory;
20518
+ }
20519
+ });
20520
+
18733
20521
  // node_modules/compare-versions/lib/umd/index.js
18734
20522
  var require_umd = __commonJS({
18735
20523
  "node_modules/compare-versions/lib/umd/index.js"(exports2, module2) {
@@ -18856,7 +20644,7 @@ var require_umd = __commonJS({
18856
20644
  });
18857
20645
 
18858
20646
  // packages/memory/dist/types.js
18859
- var init_types = __esm({
20647
+ var init_types2 = __esm({
18860
20648
  "packages/memory/dist/types.js"() {
18861
20649
  "use strict";
18862
20650
  }
@@ -20180,7 +21968,7 @@ __export(dist_exports2, {
20180
21968
  var init_dist2 = __esm({
20181
21969
  "packages/memory/dist/index.js"() {
20182
21970
  "use strict";
20183
- init_types();
21971
+ init_types2();
20184
21972
  init_adapters();
20185
21973
  init_factory();
20186
21974
  init_service();
@@ -20223,6 +22011,7 @@ __export(index_exports, {
20223
22011
  ERROR_SEARCH_HINT: () => ERROR_SEARCH_HINT,
20224
22012
  GEMINI_MODEL_OPTIONS: () => GEMINI_MODEL_OPTIONS,
20225
22013
  GeminiModels: () => GeminiModels,
22014
+ GitHubClient: () => GitHubClient,
20226
22015
  HARNESS_VALUES: () => HARNESS_VALUES,
20227
22016
  HOOK_ABI_VERSION: () => HOOK_ABI_VERSION,
20228
22017
  HookEmitter: () => HookEmitter,
@@ -20286,6 +22075,7 @@ __export(index_exports, {
20286
22075
  createConsensusEngine: () => createConsensusEngine,
20287
22076
  createContextCompactor: () => createContextCompactor,
20288
22077
  createDefaultEventLogger: () => createDefaultEventLogger,
22078
+ createGitHubStep: () => createGitHubStep,
20289
22079
  createLogger: () => createLogger,
20290
22080
  createMemoryAdapter: () => createMemoryAdapter,
20291
22081
  createMemoryHooks: () => createMemoryHooks,
@@ -20345,6 +22135,7 @@ __export(index_exports, {
20345
22135
  getSupportedPlatforms: () => getSupportedPlatforms,
20346
22136
  getSupportedReasoningEfforts: () => getSupportedReasoningEfforts,
20347
22137
  getTrajectoryHooks: () => getTrajectoryHooks,
22138
+ github: () => github_exports,
20348
22139
  handleResponse: () => handleResponse2,
20349
22140
  hasRelayPtyBinary: () => hasRelayPtyBinary,
20350
22141
  hasUnreadMessages: () => hasUnreadMessages,
@@ -20956,13 +22747,21 @@ var AgentRelayClient = class _AgentRelayClient {
20956
22747
  requestTimeoutMs: options?.requestTimeoutMs
20957
22748
  });
20958
22749
  client.child = child;
22750
+ const brokerExited = new Promise((_2, reject) => {
22751
+ child.once("exit", (code) => {
22752
+ reject(new Error(formatBrokerStartupError(`Broker process exited with code ${code} during initial handshake`, child, { binaryPath, args, cwd, stdoutLines, stderrLines })));
22753
+ });
22754
+ });
22755
+ brokerExited.catch(() => {
22756
+ });
20959
22757
  let session;
20960
22758
  for (let attempt = 0; attempt < 10; attempt++) {
20961
22759
  try {
20962
- session = await client.getSession();
22760
+ session = await Promise.race([client.getSession(), brokerExited]);
20963
22761
  break;
20964
22762
  } catch (err) {
20965
- const is503 = err instanceof Error && (err.message.includes("503") || err.message.includes("Service Unavailable"));
22763
+ const message = err instanceof Error ? err.message : String(err);
22764
+ const is503 = message.includes("503") || message.includes("Service Unavailable");
20966
22765
  if (!is503 || attempt >= 9)
20967
22766
  throw err;
20968
22767
  await new Promise((resolve4) => setTimeout(resolve4, 1e3));
@@ -21817,15 +23616,15 @@ var makeIssue = (params) => {
21817
23616
  message: issueData.message
21818
23617
  };
21819
23618
  }
21820
- let errorMessage = "";
23619
+ let errorMessage4 = "";
21821
23620
  const maps = errorMaps.filter((m2) => !!m2).slice().reverse();
21822
23621
  for (const map2 of maps) {
21823
- errorMessage = map2(fullIssue, { data, defaultError: errorMessage }).message;
23622
+ errorMessage4 = map2(fullIssue, { data, defaultError: errorMessage4 }).message;
21824
23623
  }
21825
23624
  return {
21826
23625
  ...issueData,
21827
23626
  path: fullPath,
21828
- message: errorMessage
23627
+ message: errorMessage4
21829
23628
  };
21830
23629
  };
21831
23630
  var EMPTY_PATH = [];
@@ -25423,19 +27222,19 @@ var getRefs = (options) => {
25423
27222
  };
25424
27223
 
25425
27224
  // node_modules/zod-to-json-schema/dist/esm/errorMessages.js
25426
- function addErrorMessage(res, key, errorMessage, refs) {
27225
+ function addErrorMessage(res, key, errorMessage4, refs) {
25427
27226
  if (!refs?.errorMessages)
25428
27227
  return;
25429
- if (errorMessage) {
27228
+ if (errorMessage4) {
25430
27229
  res.errorMessage = {
25431
27230
  ...res.errorMessage,
25432
- [key]: errorMessage
27231
+ [key]: errorMessage4
25433
27232
  };
25434
27233
  }
25435
27234
  }
25436
- function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
27235
+ function setResponseValueAndErrors(res, key, value, errorMessage4, refs) {
25437
27236
  res[key] = value;
25438
- addErrorMessage(res, key, errorMessage, refs);
27237
+ addErrorMessage(res, key, errorMessage4, refs);
25439
27238
  }
25440
27239
 
25441
27240
  // node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
@@ -43422,11 +45221,11 @@ var WsClient = class {
43422
45221
  this.reconnectAttempt += 1;
43423
45222
  const reconnectingEvent = { type: "reconnecting", attempt: this.reconnectAttempt };
43424
45223
  this.emit("reconnecting", reconnectingEvent);
43425
- const delay3 = this.computeReconnectDelayMs(this.reconnectAttempt);
45224
+ const delay4 = this.computeReconnectDelayMs(this.reconnectAttempt);
43426
45225
  this.reconnectTimer = setTimeout(() => {
43427
45226
  this.reconnectTimer = null;
43428
45227
  this.connect();
43429
- }, delay3);
45228
+ }, delay4);
43430
45229
  }
43431
45230
  };
43432
45231
 
@@ -53941,12 +55740,12 @@ function isUtf8(raw) {
53941
55740
  }
53942
55741
  }
53943
55742
  function buildSeedFilePayload(filePath, rootDir) {
53944
- const relative2 = import_node_path22.default.relative(rootDir, filePath).split(import_node_path22.default.sep).join("/");
55743
+ const relative3 = import_node_path22.default.relative(rootDir, filePath).split(import_node_path22.default.sep).join("/");
53945
55744
  const raw = import_node_fs15.default.readFileSync(filePath);
53946
55745
  if (isUtf8(raw)) {
53947
- return { path: `/${relative2}`, content: raw.toString("utf8"), encoding: "utf-8" };
55746
+ return { path: `/${relative3}`, content: raw.toString("utf8"), encoding: "utf-8" };
53948
55747
  }
53949
- return { path: `/${relative2}`, content: raw.toString("base64"), encoding: "base64" };
55748
+ return { path: `/${relative3}`, content: raw.toString("base64"), encoding: "base64" };
53950
55749
  }
53951
55750
  function collectSeedPaths(rootDir, currentRelative, excludeDirs, output) {
53952
55751
  const absoluteDir = import_node_path22.default.join(rootDir, currentRelative);
@@ -56767,7 +58566,7 @@ function delay(ms2) {
56767
58566
  // packages/sdk/dist/workflows/trajectory.js
56768
58567
  var import_node_path28 = require("node:path");
56769
58568
 
56770
- // node_modules/agent-trajectories/dist/chunk-27AQPWHK.js
58569
+ // node_modules/agent-trajectories/dist/chunk-WMJRBQB4.js
56771
58570
  var import_module = require("module");
56772
58571
  var import_crypto = require("crypto");
56773
58572
  var import_crypto2 = require("crypto");
@@ -57322,6 +59121,20 @@ function expandPath(path25) {
57322
59121
  }
57323
59122
  return path25;
57324
59123
  }
59124
+ function describeReadFailure(reason, error51) {
59125
+ if (reason === "schema_violation" && error51 && typeof error51 === "object" && "issues" in error51) {
59126
+ const issues = error51.issues ?? [];
59127
+ if (issues.length > 0) {
59128
+ const first = issues[0];
59129
+ const where = first.path.length > 0 ? first.path.join(".") : "root";
59130
+ const extra = issues.length > 1 ? ` (+${issues.length - 1} more)` : "";
59131
+ return `${where}: ${first.message}${extra}`;
59132
+ }
59133
+ return "schema validation failed";
59134
+ }
59135
+ if (error51 instanceof Error) return error51.message;
59136
+ return String(error51);
59137
+ }
57325
59138
  var indexLocks = /* @__PURE__ */ new Map();
57326
59139
  function withIndexLock(path25, task) {
57327
59140
  const prev = indexLocks.get(path25) ?? Promise.resolve();
@@ -57338,6 +59151,7 @@ var FileStorage = class {
57338
59151
  activeDir;
57339
59152
  completedDir;
57340
59153
  indexPath;
59154
+ lastReconcileSummary;
57341
59155
  constructor(baseDir) {
57342
59156
  this.baseDir = baseDir ?? process.cwd();
57343
59157
  const dataDir = process.env.TRAJECTORIES_DATA_DIR;
@@ -57387,7 +59201,8 @@ var FileStorage = class {
57387
59201
  alreadyIndexed: 0,
57388
59202
  skippedMalformedJson: 0,
57389
59203
  skippedSchemaViolation: 0,
57390
- skippedIoError: 0
59204
+ skippedIoError: 0,
59205
+ failures: []
57391
59206
  };
57392
59207
  await withIndexLock(this.indexPath, async () => {
57393
59208
  const index = await this.loadIndex();
@@ -57414,6 +59229,11 @@ var FileStorage = class {
57414
59229
  } else {
57415
59230
  summary.skippedIoError += 1;
57416
59231
  }
59232
+ summary.failures.push({
59233
+ path: result.path,
59234
+ reason: result.reason,
59235
+ message: describeReadFailure(result.reason, result.error)
59236
+ });
57417
59237
  continue;
57418
59238
  }
57419
59239
  const trajectory2 = result.trajectory;
@@ -57448,8 +59268,74 @@ var FileStorage = class {
57448
59268
  }
57449
59269
  console.warn(`[trajectories] ${parts.join(", ")}`);
57450
59270
  }
59271
+ this.lastReconcileSummary = summary;
57451
59272
  return summary;
57452
59273
  }
59274
+ /**
59275
+ * Returns the most recent reconcile summary, if any. Lets the CLI
59276
+ * inspect the failures collected during `initialize()` without having
59277
+ * to re-walk the directory tree (and re-emit the warn line).
59278
+ */
59279
+ getLastReconcileSummary() {
59280
+ return this.lastReconcileSummary;
59281
+ }
59282
+ /**
59283
+ * Move trajectory files that fail to load into `.trajectories/invalid/`
59284
+ * so reconcile no longer scans them. Only quarantines parse and schema
59285
+ * failures — transient io_error failures are left in place because the
59286
+ * file may load fine on the next attempt.
59287
+ *
59288
+ * Returns the list of files that were moved (with their original paths
59289
+ * and the destination directory) so the caller can report what changed.
59290
+ */
59291
+ async quarantineInvalid() {
59292
+ const summary = await this.reconcileIndex();
59293
+ const targetDir = (0, import_path4.join)(this.trajectoriesDir, "invalid");
59294
+ const candidates = summary.failures.filter((f2) => f2.reason !== "io_error");
59295
+ if (candidates.length === 0) {
59296
+ return { moved: [], targetDir };
59297
+ }
59298
+ await (0, import_promises7.mkdir)(targetDir, { recursive: true });
59299
+ const moved = [];
59300
+ for (const failure of candidates) {
59301
+ const dest = await this.resolveQuarantineDest(failure.path, targetDir);
59302
+ try {
59303
+ await (0, import_promises7.mkdir)((0, import_path4.dirname)(dest), { recursive: true });
59304
+ await (0, import_promises7.rename)(failure.path, dest);
59305
+ moved.push(failure);
59306
+ } catch (error51) {
59307
+ console.warn(
59308
+ `[trajectories] failed to quarantine ${failure.path}: ${error51 instanceof Error ? error51.message : String(error51)}`
59309
+ );
59310
+ }
59311
+ }
59312
+ return { moved, targetDir };
59313
+ }
59314
+ /**
59315
+ * Pick a destination path under `targetDir` for a quarantined file.
59316
+ *
59317
+ * Preserves the file's relative location under the trajectories root
59318
+ * (e.g. `completed/2026-04/foo.json` → `invalid/completed/2026-04/foo.json`)
59319
+ * so two invalid files that share a basename across `active/` and
59320
+ * `completed/` don't collapse onto each other and silently overwrite.
59321
+ *
59322
+ * Falls back to a numeric-suffix scheme for paths that live outside
59323
+ * the trajectories directory or that, after relative resolution, would
59324
+ * still collide with something already quarantined.
59325
+ */
59326
+ async resolveQuarantineDest(sourcePath, targetDir) {
59327
+ const rel = (0, import_path4.relative)(this.trajectoriesDir, sourcePath);
59328
+ const safeRel = rel && !rel.startsWith("..") && !(0, import_path4.isAbsolute)(rel) ? rel : (0, import_path4.basename)(sourcePath);
59329
+ let dest = (0, import_path4.join)(targetDir, safeRel);
59330
+ if (!(0, import_fs5.existsSync)(dest)) return dest;
59331
+ const ext = safeRel.endsWith(".json") ? ".json" : "";
59332
+ const stem = ext ? safeRel.slice(0, -ext.length) : safeRel;
59333
+ for (let i = 1; i < 1e3; i += 1) {
59334
+ dest = (0, import_path4.join)(targetDir, `${stem}.${i}${ext}`);
59335
+ if (!(0, import_fs5.existsSync)(dest)) return dest;
59336
+ }
59337
+ return dest;
59338
+ }
57453
59339
  /**
57454
59340
  * Recursively collect all .json file paths under `dir` into `out`.
57455
59341
  * Silently treats a missing directory as empty.
@@ -58765,14 +60651,14 @@ var WorkflowRunner = class _WorkflowRunner {
58765
60651
  if (!mount) {
58766
60652
  return cwd;
58767
60653
  }
58768
- const relative2 = import_node_path29.default.relative(this.cwd, cwd);
58769
- if (relative2 === "") {
60654
+ const relative3 = import_node_path29.default.relative(this.cwd, cwd);
60655
+ if (relative3 === "") {
58770
60656
  return mount.mountPoint;
58771
60657
  }
58772
- if (relative2 === ".." || relative2.startsWith(`..${import_node_path29.default.sep}`)) {
60658
+ if (relative3 === ".." || relative3.startsWith(`..${import_node_path29.default.sep}`)) {
58773
60659
  return cwd;
58774
60660
  }
58775
- return import_node_path29.default.resolve(mount.mountPoint, relative2);
60661
+ return import_node_path29.default.resolve(mount.mountPoint, relative3);
58776
60662
  }
58777
60663
  resolveExecutionCwd(step, agentDef) {
58778
60664
  const cwd = this.resolveEffectiveCwd(step, agentDef);
@@ -59147,10 +61033,10 @@ ${next}` : next;
59147
61033
  return changes.sort((a, b2) => a.path.localeCompare(b2.path));
59148
61034
  }
59149
61035
  normalizeEvidencePath(filePath) {
59150
- const relative2 = import_node_path29.default.relative(this.cwd, filePath);
59151
- if (!relative2 || relative2 === "")
61036
+ const relative3 = import_node_path29.default.relative(this.cwd, filePath);
61037
+ if (!relative3 || relative3 === "")
59152
61038
  return import_node_path29.default.basename(filePath);
59153
- return relative2.startsWith("..") ? filePath : relative2;
61039
+ return relative3.startsWith("..") ? filePath : relative3;
59154
61040
  }
59155
61041
  buildStepCompletionDecision(stepName, completionReason) {
59156
61042
  let reason;
@@ -60730,7 +62616,7 @@ ${trimmedOutput.slice(0, 200)}`);
60730
62616
  }
60731
62617
  async executeStep(step, state, stepStates, agentMap, errorHandling, runId, lifecycle) {
60732
62618
  if (this.isDeterministicStep(step)) {
60733
- return this.executeDeterministicStep(step, state, stepStates, runId, errorHandling, lifecycle);
62619
+ return this.executeDeterministicStep(step, state, stepStates, agentMap, runId, errorHandling, lifecycle);
60734
62620
  }
60735
62621
  if (this.isWorktreeStep(step)) {
60736
62622
  return this.executeWorktreeStep(step, state, stepStates, runId, lifecycle);
@@ -60744,13 +62630,18 @@ ${trimmedOutput.slice(0, 200)}`);
60744
62630
  * Execute a deterministic step (shell command).
60745
62631
  * Fast, reliable, $0 LLM cost.
60746
62632
  */
60747
- async executeDeterministicStep(step, state, stepStates, runId, errorHandling, lifecycle) {
60748
- const maxRetries = step.retries ?? errorHandling?.maxRetries ?? 0;
62633
+ async executeDeterministicStep(step, state, stepStates, agentMap, runId, errorHandling, lifecycle) {
62634
+ const repairRetries = errorHandling?.strategy === "retry" ? errorHandling.repairRetries ?? 0 : 0;
62635
+ const repairAgent = repairRetries > 0 ? this.resolveDeterministicRepairAgent(step, stepStates, agentMap, errorHandling) : void 0;
62636
+ const maxRetries = step.retries ?? errorHandling?.maxRetries ?? (repairAgent ? repairRetries : 0);
60749
62637
  const retryDelay = errorHandling?.retryDelayMs ?? 1e3;
60750
62638
  let lastError = "Unknown error";
60751
62639
  let lastCompletionReason;
60752
62640
  let lastExitCode;
60753
62641
  let lastExitSignal;
62642
+ let lastResolvedCommand = step.command ?? "";
62643
+ let lastStepCwd = this.cwd;
62644
+ let lastCommandOutput = "";
60754
62645
  const result = await lifecycle.monitorStep(step, state, {
60755
62646
  maxRetries,
60756
62647
  retryDelayMs: retryDelay,
@@ -60763,6 +62654,20 @@ ${trimmedOutput.slice(0, 200)}`);
60763
62654
  detail: `Retrying attempt ${attempt + 1}/${total + 1}`,
60764
62655
  raw: { attempt, maxRetries: total }
60765
62656
  });
62657
+ if (repairAgent) {
62658
+ await this.runDeterministicRepairAgent({
62659
+ step,
62660
+ agentDef: repairAgent,
62661
+ attempt,
62662
+ maxRetries: total,
62663
+ command: lastResolvedCommand,
62664
+ cwd: lastStepCwd,
62665
+ error: lastError,
62666
+ output: lastCommandOutput,
62667
+ exitCode: lastExitCode,
62668
+ exitSignal: lastExitSignal
62669
+ });
62670
+ }
60766
62671
  },
60767
62672
  execute: async () => {
60768
62673
  const stepOutputContext = this.buildStepOutputContext(stepStates, runId);
@@ -60774,12 +62679,15 @@ ${trimmedOutput.slice(0, 200)}`);
60774
62679
  return value !== void 0 ? String(value) : _match;
60775
62680
  });
60776
62681
  const stepCwd = this.resolveEffectiveCwd(step);
62682
+ lastResolvedCommand = resolvedCommand;
62683
+ lastStepCwd = stepCwd;
60777
62684
  this.beginStepEvidence(step.name, [stepCwd], state.row.startedAt);
60778
62685
  this.log(`[${step.name}] Running: ${resolvedCommand.slice(0, 200)}${resolvedCommand.length > 200 ? "..." : ""}`);
60779
62686
  if (this.executor?.executeDeterministicStep) {
60780
62687
  const executorResult = await this.executor.executeDeterministicStep(step, resolvedCommand, stepCwd);
60781
62688
  lastExitCode = executorResult.exitCode;
60782
62689
  lastExitSignal = void 0;
62690
+ lastCommandOutput = executorResult.output;
60783
62691
  const failOnError = step.failOnError !== false;
60784
62692
  if (failOnError && executorResult.exitCode !== 0) {
60785
62693
  this.log(`[${step.name}] Command failed (exit code ${executorResult.exitCode})`);
@@ -60851,6 +62759,7 @@ ${executorResult.output}`);
60851
62759
  commandStderr = stderr;
60852
62760
  lastExitCode = code ?? void 0;
60853
62761
  lastExitSignal = signal ?? void 0;
62762
+ lastCommandOutput = [stdout, stderr].filter(Boolean).join("\n");
60854
62763
  const failOnError = step.failOnError !== false;
60855
62764
  if (failOnError && code !== 0 && code !== null) {
60856
62765
  this.log(`[${step.name}] Command failed (exit code ${code})`);
@@ -60882,6 +62791,7 @@ ${stderr}`);
60882
62791
  combined: [commandStdout || output, commandStderr].filter(Boolean).join("\n")
60883
62792
  }, { exitCode: lastExitCode, exitSignal: lastExitSignal });
60884
62793
  const verificationResult = step.verification ? this.runVerification(step.verification, output, step.name) : void 0;
62794
+ lastCommandOutput = [commandStdout || output, commandStderr].filter(Boolean).join("\n");
60885
62795
  return {
60886
62796
  output,
60887
62797
  completionReason: verificationResult?.completionReason
@@ -60914,6 +62824,131 @@ ${stderr}`);
60914
62824
  throw new Error(`Step "${step.name}" failed: ${result.error ?? "Unknown error"}`);
60915
62825
  }
60916
62826
  }
62827
+ resolveDeterministicRepairAgent(step, stepStates, agentMap, errorHandling) {
62828
+ const explicitName = errorHandling?.repairAgent?.trim();
62829
+ if (explicitName) {
62830
+ const explicitAgent = agentMap.get(explicitName);
62831
+ if (explicitAgent)
62832
+ return _WorkflowRunner.resolveAgentDef(explicitAgent);
62833
+ this.log(`[${step.name}] repairAgent "${explicitName}" not found; falling back to workflow agents`);
62834
+ }
62835
+ if (step.agent) {
62836
+ const stepAgent = agentMap.get(step.agent);
62837
+ if (stepAgent)
62838
+ return _WorkflowRunner.resolveAgentDef(stepAgent);
62839
+ }
62840
+ for (const dependency of [...step.dependsOn ?? []].reverse()) {
62841
+ const dependencyAgent = stepStates.get(dependency)?.row.agentName;
62842
+ if (!dependencyAgent)
62843
+ continue;
62844
+ const agent = agentMap.get(dependencyAgent);
62845
+ if (agent)
62846
+ return _WorkflowRunner.resolveAgentDef(agent);
62847
+ }
62848
+ const candidates = [...agentMap.values()].map((agent) => _WorkflowRunner.resolveAgentDef(agent));
62849
+ candidates.sort((a, b2) => this.scoreRepairAgent(b2) - this.scoreRepairAgent(a));
62850
+ return candidates[0];
62851
+ }
62852
+ scoreRepairAgent(agent) {
62853
+ const text = `${agent.name} ${agent.role ?? ""} ${agent.preset ?? ""}`.toLowerCase();
62854
+ let score = 0;
62855
+ if (/\b(repair|fix|implement|implementation|engineer|developer|coder|worker|owner|lead|coordinator)\b/.test(text)) {
62856
+ score += 10;
62857
+ }
62858
+ if (agent.interactive === false || ["worker", "analyst"].includes(agent.preset ?? "")) {
62859
+ score += 2;
62860
+ }
62861
+ if (/\b(review|reviewer|audit|security|analyst)\b/.test(text)) {
62862
+ score -= 4;
62863
+ }
62864
+ if (agent.permissions?.access === "readonly") {
62865
+ score -= 20;
62866
+ }
62867
+ return score;
62868
+ }
62869
+ async runDeterministicRepairAgent(context) {
62870
+ const repairAgent = {
62871
+ ...context.agentDef,
62872
+ interactive: false
62873
+ };
62874
+ const repairPrompt = this.buildDeterministicRepairPrompt(context);
62875
+ const repairStep = {
62876
+ name: `${context.step.name}-repair-${context.attempt}`,
62877
+ type: "agent",
62878
+ agent: repairAgent.name,
62879
+ task: repairPrompt,
62880
+ cwd: context.cwd,
62881
+ workdir: void 0,
62882
+ retries: 0
62883
+ };
62884
+ const timeoutMs = repairAgent.constraints?.timeoutMs ?? context.step.timeoutMs ?? this.currentConfig?.swarm?.timeoutMs;
62885
+ this.log(`[${context.step.name}] Deterministic gate failed; asking "${repairAgent.name}" to repair before retry ${context.attempt + 1}/${context.maxRetries + 1}`);
62886
+ this.postToChannel(`**[${context.step.name}]** Deterministic gate failed; assigning repair to \`${repairAgent.name}\``);
62887
+ this.recordStepToolSideEffect(context.step.name, {
62888
+ type: "custom",
62889
+ detail: `Assigned deterministic gate repair to ${repairAgent.name}`,
62890
+ raw: {
62891
+ repairAgent: repairAgent.name,
62892
+ attempt: context.attempt,
62893
+ maxRetries: context.maxRetries,
62894
+ exitCode: context.exitCode,
62895
+ exitSignal: context.exitSignal
62896
+ }
62897
+ });
62898
+ try {
62899
+ this.ensureBudgetAllowsSpawn(context.step.name, repairAgent.name);
62900
+ let repairOutput;
62901
+ if (this.executor) {
62902
+ repairOutput = await this.executor.executeAgentStep(repairStep, repairAgent, repairPrompt, timeoutMs);
62903
+ } else if (repairAgent.cli === "api") {
62904
+ repairOutput = await executeApiStep(repairAgent.constraints?.model ?? "claude-sonnet-4-20250514", repairPrompt, {
62905
+ envSecrets: this.envSecrets,
62906
+ skills: repairAgent.skills,
62907
+ defaultMaxTokens: repairAgent.constraints?.maxTokens
62908
+ });
62909
+ } else {
62910
+ const result = await this.execNonInteractive(repairAgent, repairStep, timeoutMs);
62911
+ repairOutput = result.output;
62912
+ }
62913
+ this.recordStepToolSideEffect(context.step.name, {
62914
+ type: "custom",
62915
+ detail: `Repair agent ${repairAgent.name} completed before deterministic retry`,
62916
+ raw: { repairAgent: repairAgent.name, output: repairOutput.slice(0, 1e3) }
62917
+ });
62918
+ } catch (error51) {
62919
+ if (error51 instanceof BudgetExceededError || this.abortController?.signal.aborted) {
62920
+ throw error51;
62921
+ }
62922
+ const message = error51 instanceof Error ? error51.message : String(error51);
62923
+ this.log(`[${context.step.name}] Repair agent "${repairAgent.name}" failed: ${message}`);
62924
+ this.postToChannel(`**[${context.step.name}]** Repair agent \`${repairAgent.name}\` failed; retrying gate anyway`);
62925
+ this.recordStepToolSideEffect(context.step.name, {
62926
+ type: "custom",
62927
+ detail: `Repair agent ${repairAgent.name} failed before deterministic retry: ${message}`,
62928
+ raw: { repairAgent: repairAgent.name, error: message }
62929
+ });
62930
+ }
62931
+ }
62932
+ buildDeterministicRepairPrompt(context) {
62933
+ const output = context.output.trim();
62934
+ const clippedOutput = output.length > 4e3 ? output.slice(-4e3) : output;
62935
+ return `A deterministic workflow gate failed after an agent/team step. Fix the repository or workflow state so the same gate passes on the next retry.
62936
+
62937
+ Step: ${context.step.name}
62938
+ Working directory: ${context.cwd}
62939
+ Command:
62940
+ ${context.command}
62941
+
62942
+ Failure:
62943
+ ${context.error}
62944
+ Exit code: ${context.exitCode ?? "unknown"}
62945
+ Exit signal: ${context.exitSignal ?? "none"}
62946
+
62947
+ Command output:
62948
+ ${clippedOutput || "(no output captured)"}
62949
+
62950
+ Repair only what is needed for this gate to pass. Preserve unrelated user changes. After making the fix, report the files changed and the reason the gate should pass.`;
62951
+ }
60917
62952
  /**
60918
62953
  * Execute a worktree step (git worktree setup).
60919
62954
  * Fast, reliable, $0 LLM cost.
@@ -60931,7 +62966,7 @@ ${stderr}`);
60931
62966
  const branch = this.interpolateStepTask(step.branch ?? "", stepOutputContext);
60932
62967
  const baseBranch = step.baseBranch ? this.interpolateStepTask(step.baseBranch, stepOutputContext) : "HEAD";
60933
62968
  const worktreePath = step.path ? this.interpolateStepTask(step.path, stepOutputContext) : import_node_path29.default.join(".worktrees", step.name);
60934
- const createBranch = step.createBranch !== false;
62969
+ const createBranch2 = step.createBranch !== false;
60935
62970
  const stepCwd = this.resolveStepWorkdir(step) ?? this.cwd;
60936
62971
  this.beginStepEvidence(step.name, [stepCwd], state.row.startedAt);
60937
62972
  if (!branch) {
@@ -60954,7 +62989,7 @@ ${stderr}`);
60954
62989
  let worktreeArgs;
60955
62990
  if (branchExists) {
60956
62991
  worktreeArgs = ["worktree", "add", absoluteWorktreePath, branch];
60957
- } else if (createBranch) {
62992
+ } else if (createBranch2) {
60958
62993
  worktreeArgs = ["worktree", "add", "-b", branch, absoluteWorktreePath, baseBranch];
60959
62994
  } else {
60960
62995
  throw new Error(`Branch "${branch}" does not exist and createBranch is false`);
@@ -61032,7 +63067,7 @@ ${stderr}`);
61032
63067
  combined: [commandStdout || output, commandStderr].filter(Boolean).join("\n")
61033
63068
  }, { exitCode: lastExitCode, exitSignal: lastExitSignal });
61034
63069
  worktreeBranch = branch;
61035
- createdBranch = !branchExists && createBranch;
63070
+ createdBranch = !branchExists && createBranch2;
61036
63071
  return { output };
61037
63072
  },
61038
63073
  toCompletionResult: ({ output }, attempt) => ({
@@ -61151,18 +63186,18 @@ ${stderr}`);
61151
63186
  await this.persistStepOutput(runId, step.name, output);
61152
63187
  this.emit({ type: "step:completed", runId, stepName: step.name, output });
61153
63188
  } catch (apiError) {
61154
- const errorMessage = apiError instanceof Error ? apiError.message : String(apiError);
63189
+ const errorMessage4 = apiError instanceof Error ? apiError.message : String(apiError);
61155
63190
  state.row.status = "failed";
61156
- state.row.error = errorMessage;
63191
+ state.row.error = errorMessage4;
61157
63192
  state.row.completedAt = (/* @__PURE__ */ new Date()).toISOString();
61158
63193
  await this.db.updateStep(state.row.id, {
61159
63194
  status: "failed",
61160
- error: errorMessage,
63195
+ error: errorMessage4,
61161
63196
  completedAt: state.row.completedAt,
61162
63197
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
61163
63198
  });
61164
- this.emit({ type: "step:failed", runId, stepName: step.name, error: errorMessage });
61165
- this.postToChannel(`**[${step.name}]** Failed (api): ${errorMessage}`);
63199
+ this.emit({ type: "step:failed", runId, stepName: step.name, error: errorMessage4 });
63200
+ this.postToChannel(`**[${step.name}]** Failed (api): ${errorMessage4}`);
61166
63201
  throw apiError;
61167
63202
  }
61168
63203
  return;
@@ -62991,15 +65026,15 @@ DO NOT:
62991
65026
  throw error51;
62992
65027
  }
62993
65028
  }
62994
- updateCustomVerificationFailure(stepName, check2, errorMessage) {
62995
- if (check2.type !== "custom" || !check2.value || !errorMessage) {
65029
+ updateCustomVerificationFailure(stepName, check2, errorMessage4) {
65030
+ if (check2.type !== "custom" || !check2.value || !errorMessage4) {
62996
65031
  this.lastCustomVerificationFailure.delete(stepName);
62997
65032
  return;
62998
65033
  }
62999
65034
  const marker = `custom check "${check2.value}" failed
63000
65035
  `;
63001
- const markerIndex = errorMessage.indexOf(marker);
63002
- const output = markerIndex === -1 ? errorMessage.trim() : errorMessage.slice(markerIndex + marker.length).trim();
65036
+ const markerIndex = errorMessage4.indexOf(marker);
65037
+ const output = markerIndex === -1 ? errorMessage4.trim() : errorMessage4.slice(markerIndex + marker.length).trim();
63003
65038
  this.lastCustomVerificationFailure.set(stepName, {
63004
65039
  command: check2.value,
63005
65040
  output
@@ -64271,6 +66306,10 @@ var WorkflowBuilder = class {
64271
66306
  this._errorHandling.retryDelayMs = options.retryDelayMs;
64272
66307
  if (options?.notifyChannel !== void 0)
64273
66308
  this._errorHandling.notifyChannel = options.notifyChannel;
66309
+ if (options?.repairAgent !== void 0)
66310
+ this._errorHandling.repairAgent = options.repairAgent;
66311
+ if (options?.repairRetries !== void 0)
66312
+ this._errorHandling.repairRetries = options.repairRetries;
64274
66313
  return this;
64275
66314
  }
64276
66315
  validateBuilderState() {
@@ -66037,6 +68076,751 @@ Run ID: ${runId}`;
66037
68076
  throw new Error(`Unsupported file type: ${ext}. Use .yaml, .yml, .ts, or .py`);
66038
68077
  }
66039
68078
 
68079
+ // packages/sdk/dist/github.js
68080
+ var github_exports = {};
68081
+ __export(github_exports, {
68082
+ BaseGitHubAdapter: () => BaseGitHubAdapter,
68083
+ DEFAULT_GH_PATH: () => DEFAULT_GH_PATH,
68084
+ DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES,
68085
+ DEFAULT_NANGO_BASE_URL: () => DEFAULT_NANGO_BASE_URL,
68086
+ DEFAULT_NANGO_PROVIDER_CONFIG_KEY: () => DEFAULT_NANGO_PROVIDER_CONFIG_KEY,
68087
+ DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT: () => DEFAULT_RELAY_CLOUD_GITHUB_PROXY_ENDPOINT,
68088
+ DEFAULT_TIMEOUT: () => DEFAULT_TIMEOUT,
68089
+ DEFAULT_USER_AGENT: () => DEFAULT_USER_AGENT,
68090
+ GITHUB_ACTIONS: () => GITHUB_ACTIONS,
68091
+ GhCliClient: () => GhCliClient,
68092
+ GhCliError: () => GhCliError,
68093
+ GitHubAction: () => GitHubAction,
68094
+ GitHubAdapterFactory: () => GitHubAdapterFactory,
68095
+ GitHubApiError: () => GitHubApiError,
68096
+ GitHubClient: () => GitHubClient,
68097
+ GitHubClientFactory: () => GitHubClientFactory,
68098
+ GitHubClientInterface: () => GitHubClientInterface,
68099
+ GitHubRuntimeDetector: () => GitHubRuntimeDetector,
68100
+ GitHubStepExecutor: () => GitHubStepExecutor,
68101
+ NangoClient: () => NangoClient,
68102
+ createBranch: () => createBranch,
68103
+ createCommit: () => createCommit,
68104
+ createFile: () => createFile,
68105
+ createGitHubAdapter: () => createGitHubAdapter,
68106
+ createGitHubStep: () => createGitHubStep,
68107
+ createIssue: () => createIssue,
68108
+ createPR: () => createPR,
68109
+ deleteFile: () => deleteFile,
68110
+ detectGitHubRuntime: () => detectGitHubRuntime,
68111
+ getBranch: () => getBranch,
68112
+ getPR: () => getPR,
68113
+ getRepo: () => getRepo,
68114
+ getUser: () => getUser,
68115
+ githubStepConfigFromWorkflowStep: () => githubStepConfigFromWorkflowStep,
68116
+ listBranches: () => listBranches,
68117
+ listCommits: () => listCommits,
68118
+ listFiles: () => listFiles,
68119
+ listIssues: () => listIssues,
68120
+ listOrganizations: () => listOrganizations,
68121
+ listPRs: () => listPRs,
68122
+ listRepos: () => listRepos,
68123
+ mapBranch: () => mapBranch,
68124
+ mapCommit: () => mapCommit,
68125
+ mapFile: () => mapFile,
68126
+ mapIssue: () => mapIssue,
68127
+ mapOrganization: () => mapOrganization,
68128
+ mapPR: () => mapPR,
68129
+ mapRepo: () => mapRepo,
68130
+ mapUser: () => mapUser,
68131
+ mergePR: () => mergePR,
68132
+ normalizeGitHubRuntimeConfig: () => normalizeGitHubRuntimeConfig,
68133
+ readFile: () => readFile3,
68134
+ updateFile: () => updateFile,
68135
+ updateIssue: () => updateIssue,
68136
+ updatePR: () => updatePR
68137
+ });
68138
+
68139
+ // packages/github-primitive/src/index.ts
68140
+ init_constants();
68141
+ init_types();
68142
+ init_adapter();
68143
+ init_local_runtime();
68144
+ init_cloud_runtime();
68145
+
68146
+ // packages/github-primitive/src/client.ts
68147
+ init_adapter();
68148
+ var GitHubClient = class _GitHubClient {
68149
+ adapterPromise;
68150
+ constructor(config2 = {}) {
68151
+ this.adapterPromise = GitHubAdapterFactory.create(config2);
68152
+ }
68153
+ /**
68154
+ * Create a GitHub client and eagerly resolve runtime detection.
68155
+ */
68156
+ static async create(config2 = {}) {
68157
+ const client = new _GitHubClient(config2);
68158
+ await client.getAdapter();
68159
+ return client;
68160
+ }
68161
+ /**
68162
+ * Inspect runtime availability without creating a client.
68163
+ */
68164
+ static detect(config2 = {}) {
68165
+ return GitHubAdapterFactory.detect(config2);
68166
+ }
68167
+ /**
68168
+ * Detect the runtime that would be selected for the supplied configuration.
68169
+ */
68170
+ static detectRuntime(config2 = {}) {
68171
+ return GitHubAdapterFactory.detectRuntime(config2);
68172
+ }
68173
+ /**
68174
+ * Return the selected low-level adapter.
68175
+ */
68176
+ getAdapter() {
68177
+ return this.adapterPromise;
68178
+ }
68179
+ /**
68180
+ * Return the runtime selected by auto-detection or explicit configuration.
68181
+ */
68182
+ async getRuntime() {
68183
+ return (await this.getAdapter()).getRuntime();
68184
+ }
68185
+ /**
68186
+ * Check whether the selected runtime is authenticated.
68187
+ */
68188
+ async isAuthenticated() {
68189
+ return (await this.getAdapter()).isAuthenticated();
68190
+ }
68191
+ /**
68192
+ * Fetch the authenticated GitHub user for the selected runtime.
68193
+ */
68194
+ async getCurrentUser() {
68195
+ return (await this.getAdapter()).getCurrentUser();
68196
+ }
68197
+ /**
68198
+ * Execute a raw GitHub API request through the selected adapter.
68199
+ */
68200
+ async request(method, path25, options) {
68201
+ return (await this.getAdapter()).request(method, path25, options);
68202
+ }
68203
+ /**
68204
+ * Execute any registered GitHub primitive action by action name.
68205
+ */
68206
+ async executeAction(action, params) {
68207
+ return (await this.getAdapter()).executeAction(action, params);
68208
+ }
68209
+ /**
68210
+ * List repositories visible to the authenticated GitHub identity.
68211
+ */
68212
+ async listRepos(options = {}) {
68213
+ return (await this.getAdapter()).listRepositories(options);
68214
+ }
68215
+ /**
68216
+ * Fetch a repository by owner and name.
68217
+ */
68218
+ async getRepo(owner, repo) {
68219
+ return (await this.getAdapter()).getRepository({ owner, repo });
68220
+ }
68221
+ /**
68222
+ * List issues for a repository.
68223
+ */
68224
+ async listIssues(owner, repo, options = {}) {
68225
+ return (await this.getAdapter()).listIssues({ owner, repo, ...options });
68226
+ }
68227
+ /**
68228
+ * Create an issue in a repository.
68229
+ */
68230
+ async createIssue(owner, repo, title, body, options = {}) {
68231
+ return (await this.getAdapter()).createIssue({ owner, repo, title, body, ...options });
68232
+ }
68233
+ /**
68234
+ * Update an existing issue by issue number.
68235
+ */
68236
+ async updateIssue(owner, repo, number4, updates) {
68237
+ return (await this.getAdapter()).updateIssue({
68238
+ owner,
68239
+ repo,
68240
+ issueNumber: number4,
68241
+ ...updates
68242
+ });
68243
+ }
68244
+ /**
68245
+ * Close an issue by issue number.
68246
+ */
68247
+ async closeIssue(owner, repo, number4) {
68248
+ return (await this.getAdapter()).closeIssue({ owner, repo, issueNumber: number4 });
68249
+ }
68250
+ /**
68251
+ * List pull requests for a repository.
68252
+ */
68253
+ async listPRs(owner, repo, options = {}) {
68254
+ return (await this.getAdapter()).listPullRequests({ owner, repo, ...options });
68255
+ }
68256
+ /**
68257
+ * Fetch a pull request by pull request number.
68258
+ */
68259
+ async getPR(owner, repo, number4) {
68260
+ return (await this.getAdapter()).getPullRequest({ owner, repo, pullNumber: number4 });
68261
+ }
68262
+ /**
68263
+ * Create a pull request.
68264
+ */
68265
+ async createPR(owner, repo, title, body, base, head, options = {}) {
68266
+ return (await this.getAdapter()).createPullRequest({
68267
+ owner,
68268
+ repo,
68269
+ title,
68270
+ body,
68271
+ base,
68272
+ head,
68273
+ ...options
68274
+ });
68275
+ }
68276
+ /**
68277
+ * Update an existing pull request by pull request number.
68278
+ */
68279
+ async updatePR(owner, repo, number4, updates) {
68280
+ return (await this.getAdapter()).updatePullRequest({
68281
+ owner,
68282
+ repo,
68283
+ pullNumber: number4,
68284
+ ...updates
68285
+ });
68286
+ }
68287
+ /**
68288
+ * Merge a pull request and return the refreshed pull request.
68289
+ */
68290
+ async mergePR(owner, repo, number4, options = {}) {
68291
+ return (await this.getAdapter()).mergePullRequest({
68292
+ owner,
68293
+ repo,
68294
+ pullNumber: number4,
68295
+ ...options
68296
+ });
68297
+ }
68298
+ /**
68299
+ * List files or directories at a repository path.
68300
+ */
68301
+ async listFiles(owner, repo, path25 = "", options = {}) {
68302
+ return (await this.getAdapter()).listFiles({ owner, repo, path: path25, ...options });
68303
+ }
68304
+ /**
68305
+ * Read a repository file and return decoded UTF-8 content.
68306
+ */
68307
+ async readFile(owner, repo, path25, ref) {
68308
+ return (await this.getAdapter()).readFile({ owner, repo, path: path25, ref });
68309
+ }
68310
+ /**
68311
+ * Create a repository file with a commit message.
68312
+ */
68313
+ async createFile(owner, repo, path25, content, message, options = {}) {
68314
+ await (await this.getAdapter()).createFile({
68315
+ owner,
68316
+ repo,
68317
+ path: path25,
68318
+ content,
68319
+ message,
68320
+ ...options
68321
+ });
68322
+ }
68323
+ /**
68324
+ * Update a repository file with a commit message.
68325
+ */
68326
+ async updateFile(owner, repo, path25, content, message, sha, options = {}) {
68327
+ return (await this.getAdapter()).updateFile({
68328
+ owner,
68329
+ repo,
68330
+ path: path25,
68331
+ content,
68332
+ message,
68333
+ sha,
68334
+ ...options
68335
+ });
68336
+ }
68337
+ /**
68338
+ * Delete a repository file with a commit message.
68339
+ */
68340
+ async deleteFile(owner, repo, path25, sha, message, options = {}) {
68341
+ await (await this.getAdapter()).deleteFile({
68342
+ owner,
68343
+ repo,
68344
+ path: path25,
68345
+ sha,
68346
+ message,
68347
+ ...options
68348
+ });
68349
+ }
68350
+ /**
68351
+ * List repository branches.
68352
+ */
68353
+ async listBranches(owner, repo) {
68354
+ return (await this.getAdapter()).listBranches({ owner, repo });
68355
+ }
68356
+ /**
68357
+ * Create a branch from another branch, or from the repository default branch.
68358
+ */
68359
+ async createBranch(owner, repo, branch, options = {}) {
68360
+ await (await this.getAdapter()).createBranch({ owner, repo, branch, ...options });
68361
+ }
68362
+ /**
68363
+ * List repository commits.
68364
+ */
68365
+ async listCommits(owner, repo, options = {}) {
68366
+ return (await this.getAdapter()).listCommits({ owner, repo, ...options });
68367
+ }
68368
+ /**
68369
+ * Create a Git commit object.
68370
+ */
68371
+ async createCommit(owner, repo, message, tree, parents, options = {}) {
68372
+ return (await this.getAdapter()).createCommit({
68373
+ owner,
68374
+ repo,
68375
+ message,
68376
+ tree,
68377
+ parents,
68378
+ ...options
68379
+ });
68380
+ }
68381
+ /**
68382
+ * Fetch the authenticated user, or a public user by username.
68383
+ */
68384
+ async getUser(username) {
68385
+ return (await this.getAdapter()).getUser(username ? { username } : void 0);
68386
+ }
68387
+ /**
68388
+ * List organizations for the authenticated user, or for a public user.
68389
+ */
68390
+ async listOrganizations(username, options = {}) {
68391
+ return (await this.getAdapter()).listOrganizations({ username, ...options });
68392
+ }
68393
+ };
68394
+
68395
+ // packages/github-primitive/src/workflow-step.ts
68396
+ init_types();
68397
+ var GITHUB_INTEGRATION = "github";
68398
+ var RESERVED_PARAM_KEYS = /* @__PURE__ */ new Set([
68399
+ "action",
68400
+ "config",
68401
+ "githubConfig",
68402
+ "output",
68403
+ "params",
68404
+ "actionParams",
68405
+ "repository",
68406
+ "runtime",
68407
+ "ghPath",
68408
+ "timeout",
68409
+ "retryOnRateLimit",
68410
+ "maxRetries"
68411
+ ]);
68412
+ function createGitHubStep(config2) {
68413
+ validateGitHubStepConfig(config2);
68414
+ const params = {};
68415
+ if (config2.repo !== void 0) {
68416
+ params.repo = repoToString(config2.repo);
68417
+ }
68418
+ if (config2.params !== void 0) {
68419
+ params.params = JSON.stringify(config2.params);
68420
+ }
68421
+ if (config2.config !== void 0) {
68422
+ params.config = JSON.stringify(config2.config);
68423
+ }
68424
+ if (config2.output !== void 0) {
68425
+ params.output = JSON.stringify(config2.output);
68426
+ }
68427
+ const step = {
68428
+ name: config2.name,
68429
+ type: "integration",
68430
+ integration: GITHUB_INTEGRATION,
68431
+ action: config2.action,
68432
+ params
68433
+ };
68434
+ if (config2.dependsOn !== void 0) step.dependsOn = config2.dependsOn;
68435
+ if (config2.timeoutMs !== void 0) step.timeoutMs = config2.timeoutMs;
68436
+ if (config2.retries !== void 0) step.retries = config2.retries;
68437
+ return step;
68438
+ }
68439
+ var GitHubStepExecutor = class {
68440
+ constructor(options = {}) {
68441
+ this.options = options;
68442
+ }
68443
+ options;
68444
+ async executeAgentStep() {
68445
+ throw new Error("GitHubStepExecutor only executes GitHub integration steps.");
68446
+ }
68447
+ async execute(config2, context = {}) {
68448
+ validateGitHubStepConfig(config2);
68449
+ const runtimeConfig = mergeRuntimeConfig(this.options, context.config, config2.config);
68450
+ if (context.workspaceId && !runtimeConfig.relayCloud?.workspaceId) {
68451
+ runtimeConfig.relayCloud = {
68452
+ ...runtimeConfig.relayCloud,
68453
+ workspaceId: context.workspaceId
68454
+ };
68455
+ }
68456
+ const client = context.client ?? new GitHubClient(runtimeConfig);
68457
+ const actionParams = buildActionParams(config2);
68458
+ const result = await client.executeAction(config2.action, actionParams);
68459
+ const runtime = result.metadata?.runtime ?? await safeGetRuntime(client);
68460
+ const output = formatStepOutput2(config2, result, runtime);
68461
+ return {
68462
+ success: result.success,
68463
+ output,
68464
+ result,
68465
+ runtime,
68466
+ error: result.error
68467
+ };
68468
+ }
68469
+ async executeIntegrationStep(step, resolvedParams, context = {}) {
68470
+ if (step.integration !== GITHUB_INTEGRATION) {
68471
+ return {
68472
+ success: false,
68473
+ output: `GitHubStepExecutor only handles "${GITHUB_INTEGRATION}" integration steps`
68474
+ };
68475
+ }
68476
+ try {
68477
+ const config2 = githubStepConfigFromWorkflowStep(step, resolvedParams);
68478
+ const result = await this.execute(config2, context);
68479
+ return {
68480
+ success: result.success,
68481
+ output: result.success ? result.output : result.output || result.error || "GitHub step failed"
68482
+ };
68483
+ } catch (error51) {
68484
+ return {
68485
+ success: false,
68486
+ output: error51 instanceof Error ? error51.message : String(error51)
68487
+ };
68488
+ }
68489
+ }
68490
+ };
68491
+ function githubStepConfigFromWorkflowStep(step, resolvedParams) {
68492
+ const params = normalizeResolvedParams(resolvedParams);
68493
+ const action = step.action;
68494
+ if (!action) {
68495
+ throw new Error(`GitHub step "${step.name}" requires an action`);
68496
+ }
68497
+ const config2 = readJsonParam(params.config ?? params.githubConfig, "config") ?? runtimeConfigFromParams(params);
68498
+ const output = readJsonParam(params.output, "output") ?? void 0;
68499
+ const repo = readRepositoryParam(params);
68500
+ const actionParams = readActionParams(params);
68501
+ return {
68502
+ name: step.name,
68503
+ dependsOn: step.dependsOn,
68504
+ action,
68505
+ repo,
68506
+ params: actionParams,
68507
+ config: config2,
68508
+ output,
68509
+ timeoutMs: step.timeoutMs,
68510
+ retries: step.retries
68511
+ };
68512
+ }
68513
+ function validateGitHubStepConfig(config2) {
68514
+ if (!config2.name) {
68515
+ throw new Error("GitHub step requires a non-empty name");
68516
+ }
68517
+ if (!config2.action || typeof config2.action !== "string") {
68518
+ throw new Error(`GitHub step "${config2.name}" requires an action name`);
68519
+ }
68520
+ if (!GITHUB_ACTIONS.includes(config2.action)) {
68521
+ throw new Error(`GitHub step "${config2.name}" uses unsupported action "${config2.action}"`);
68522
+ }
68523
+ if (config2.repo !== void 0) {
68524
+ parseRepositoryRef(config2.repo);
68525
+ }
68526
+ if (config2.params !== void 0 && !isRecord2(config2.params)) {
68527
+ throw new Error(`GitHub step "${config2.name}" params must be an object`);
68528
+ }
68529
+ }
68530
+ function buildActionParams(config2) {
68531
+ const repo = config2.repo === void 0 ? void 0 : parseRepositoryRef(config2.repo);
68532
+ const params = config2.params ? { ...config2.params } : {};
68533
+ const merged = repo ? { ...repo, ...params } : params;
68534
+ return Object.keys(merged).length === 0 ? void 0 : merged;
68535
+ }
68536
+ function readActionParams(params) {
68537
+ const serializedParams = params.params ?? params.actionParams;
68538
+ if (serializedParams !== void 0) {
68539
+ const parsed = readJsonParam(serializedParams, "params");
68540
+ if (parsed === void 0) return {};
68541
+ if (!isRecord2(parsed)) {
68542
+ throw new Error("GitHub step params.params must be a JSON object");
68543
+ }
68544
+ return parsed;
68545
+ }
68546
+ const actionParams = {};
68547
+ const repoValue = params.repo;
68548
+ const repoIsRepositoryRef = params.owner === void 0 && typeof repoValue === "string" && repoValue.includes("/");
68549
+ for (const [key, value] of Object.entries(params)) {
68550
+ if (RESERVED_PARAM_KEYS.has(key)) continue;
68551
+ if (key === "repo" && repoIsRepositoryRef) continue;
68552
+ actionParams[key] = value;
68553
+ }
68554
+ return actionParams;
68555
+ }
68556
+ function readRepositoryParam(params) {
68557
+ const value = params.repository ?? (params.owner === void 0 ? params.repo : void 0);
68558
+ if (value === void 0) return void 0;
68559
+ if (typeof value === "string" || isRecord2(value)) {
68560
+ return parseRepositoryRef(value);
68561
+ }
68562
+ throw new Error("GitHub step repo must be in owner/repo format");
68563
+ }
68564
+ function runtimeConfigFromParams(params) {
68565
+ const config2 = {};
68566
+ if (typeof params.runtime === "string") {
68567
+ config2.runtime = params.runtime;
68568
+ }
68569
+ if (typeof params.ghPath === "string") {
68570
+ config2.ghPath = params.ghPath;
68571
+ }
68572
+ if (typeof params.timeout === "number") {
68573
+ config2.timeout = params.timeout;
68574
+ }
68575
+ if (typeof params.retryOnRateLimit === "boolean") {
68576
+ config2.retryOnRateLimit = params.retryOnRateLimit;
68577
+ }
68578
+ if (typeof params.maxRetries === "number") {
68579
+ config2.maxRetries = params.maxRetries;
68580
+ }
68581
+ return Object.keys(config2).length === 0 ? void 0 : config2;
68582
+ }
68583
+ function mergeRuntimeConfig(...configs) {
68584
+ const merged = {};
68585
+ for (const config2 of configs) {
68586
+ if (!config2) continue;
68587
+ const { nango, relayCloud, env, ...flatConfig } = config2;
68588
+ Object.assign(merged, flatConfig);
68589
+ if (nango) {
68590
+ merged.nango = {
68591
+ ...merged.nango,
68592
+ ...nango
68593
+ };
68594
+ }
68595
+ if (relayCloud) {
68596
+ merged.relayCloud = {
68597
+ ...merged.relayCloud,
68598
+ ...relayCloud
68599
+ };
68600
+ }
68601
+ if (env) {
68602
+ merged.env = {
68603
+ ...merged.env,
68604
+ ...env
68605
+ };
68606
+ }
68607
+ }
68608
+ return merged;
68609
+ }
68610
+ function formatStepOutput2(config2, result, runtime) {
68611
+ const outputConfig = config2.output ?? {};
68612
+ const mode = outputConfig.mode ?? "data";
68613
+ const format2 = outputConfig.format ?? "json";
68614
+ if (mode === "none") {
68615
+ return "";
68616
+ }
68617
+ let projection = buildOutputProjection(mode, result, runtime, outputConfig);
68618
+ if (outputConfig.path) {
68619
+ projection = resolvePath2(projection, outputConfig.path);
68620
+ }
68621
+ if (format2 === "text") {
68622
+ return projectionToText(projection);
68623
+ }
68624
+ return JSON.stringify(projection, void 0, outputConfig.pretty ? 2 : void 0);
68625
+ }
68626
+ function buildOutputProjection(mode, result, runtime, outputConfig) {
68627
+ if (mode === "raw") {
68628
+ return result.output;
68629
+ }
68630
+ if (mode === "summary") {
68631
+ return withOptionalMetadata(summarizeResult(result, runtime), result, runtime, outputConfig);
68632
+ }
68633
+ if (mode === "result") {
68634
+ const projected = {
68635
+ success: result.success,
68636
+ output: result.output
68637
+ };
68638
+ if (result.data !== void 0) projected.data = result.data;
68639
+ if (result.error !== void 0) projected.error = result.error;
68640
+ return withOptionalMetadata(projected, result, runtime, outputConfig);
68641
+ }
68642
+ const data = result.data ?? (result.output ? result.output : null);
68643
+ return withOptionalMetadata(data, result, runtime, outputConfig);
68644
+ }
68645
+ function summarizeResult(result, runtime) {
68646
+ if (!result.success) {
68647
+ return {
68648
+ success: false,
68649
+ error: result.error ?? "GitHub action failed",
68650
+ runtime
68651
+ };
68652
+ }
68653
+ const data = result.data;
68654
+ if (Array.isArray(data)) {
68655
+ return {
68656
+ success: true,
68657
+ count: data.length,
68658
+ items: data.slice(0, 10).map(summarizeValue),
68659
+ runtime
68660
+ };
68661
+ }
68662
+ return {
68663
+ success: true,
68664
+ value: summarizeValue(data ?? result.output),
68665
+ runtime
68666
+ };
68667
+ }
68668
+ function summarizeValue(value) {
68669
+ if (!isRecord2(value)) {
68670
+ return value;
68671
+ }
68672
+ const summary = {};
68673
+ for (const key of [
68674
+ "fullName",
68675
+ "name",
68676
+ "number",
68677
+ "title",
68678
+ "state",
68679
+ "path",
68680
+ "sha",
68681
+ "type",
68682
+ "defaultBranch",
68683
+ "visibility",
68684
+ "private",
68685
+ "createdAt",
68686
+ "updatedAt",
68687
+ "htmlUrl",
68688
+ "url"
68689
+ ]) {
68690
+ if (value[key] !== void 0) {
68691
+ summary[key] = value[key];
68692
+ }
68693
+ }
68694
+ return Object.keys(summary).length > 0 ? summary : value;
68695
+ }
68696
+ function withOptionalMetadata(value, result, runtime, outputConfig) {
68697
+ if (!outputConfig.includeMetadata && !outputConfig.includeRuntime) {
68698
+ return value;
68699
+ }
68700
+ const metadata = {};
68701
+ if (outputConfig.includeRuntime && runtime !== void 0) metadata.runtime = runtime;
68702
+ if (outputConfig.includeMetadata && result.metadata !== void 0) {
68703
+ Object.assign(metadata, result.metadata);
68704
+ }
68705
+ return { value, metadata };
68706
+ }
68707
+ function projectionToText(value) {
68708
+ if (typeof value === "string") return value;
68709
+ if (value === null || value === void 0) return "";
68710
+ if (Array.isArray(value)) {
68711
+ return value.map((entry) => projectionToText(entry)).join("\n");
68712
+ }
68713
+ if (isRecord2(value)) {
68714
+ if ("output" in value) return projectionToText(value.output);
68715
+ if ("value" in value) return projectionToText(value.value);
68716
+ if ("data" in value) return projectionToText(value.data);
68717
+ if ("content" in value) return projectionToText(value.content);
68718
+ if ("body" in value) return projectionToText(value.body);
68719
+ if ("title" in value) return projectionToText(value.title);
68720
+ if ("fullName" in value) return projectionToText(value.fullName);
68721
+ if ("path" in value) return projectionToText(value.path);
68722
+ if ("url" in value) return projectionToText(value.url);
68723
+ }
68724
+ return JSON.stringify(value);
68725
+ }
68726
+ function resolvePath2(value, path25) {
68727
+ if (!path25) return value;
68728
+ let current = value;
68729
+ for (const segment of path25.split(".")) {
68730
+ if (Array.isArray(current) && /^\d+$/.test(segment)) {
68731
+ current = current[Number(segment)];
68732
+ continue;
68733
+ }
68734
+ if (isRecord2(current)) {
68735
+ current = current[segment];
68736
+ continue;
68737
+ }
68738
+ return void 0;
68739
+ }
68740
+ return current;
68741
+ }
68742
+ function parseRepositoryRef(repo) {
68743
+ if (typeof repo === "string") {
68744
+ const [owner2, name2, ...rest] = repo.split("/");
68745
+ if (!owner2 || !name2 || rest.length > 0) {
68746
+ throw new Error(`GitHub repo must be in owner/repo format: ${repo}`);
68747
+ }
68748
+ return {
68749
+ owner: owner2,
68750
+ repo: name2,
68751
+ fullName: `${owner2}/${name2}`
68752
+ };
68753
+ }
68754
+ const owner = typeof repo.owner === "string" ? repo.owner : void 0;
68755
+ const name = typeof repo.repo === "string" ? repo.repo : void 0;
68756
+ if (!owner || !name) {
68757
+ throw new Error("GitHub repo object requires owner and repo");
68758
+ }
68759
+ return {
68760
+ owner,
68761
+ repo: name,
68762
+ fullName: typeof repo.fullName === "string" ? repo.fullName : `${owner}/${name}`
68763
+ };
68764
+ }
68765
+ function repoToString(repo) {
68766
+ return typeof repo === "string" ? repo : `${repo.owner}/${repo.repo}`;
68767
+ }
68768
+ async function safeGetRuntime(client) {
68769
+ try {
68770
+ return await client.getRuntime();
68771
+ } catch {
68772
+ return void 0;
68773
+ }
68774
+ }
68775
+ function normalizeResolvedParams(params) {
68776
+ const normalized = {};
68777
+ for (const [key, value] of Object.entries(params)) {
68778
+ normalized[key] = coerceScalar(value);
68779
+ }
68780
+ return normalized;
68781
+ }
68782
+ function coerceScalar(value) {
68783
+ if (typeof value !== "string") {
68784
+ return value;
68785
+ }
68786
+ const trimmed = value.trim();
68787
+ if (trimmed === "true") return true;
68788
+ if (trimmed === "false") return false;
68789
+ if (trimmed === "null") return null;
68790
+ if (/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/.test(trimmed)) return Number(trimmed);
68791
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
68792
+ try {
68793
+ return JSON.parse(trimmed);
68794
+ } catch {
68795
+ return value;
68796
+ }
68797
+ }
68798
+ return value;
68799
+ }
68800
+ function readJsonParam(value, name) {
68801
+ if (value === void 0) return void 0;
68802
+ if (typeof value !== "string") return value;
68803
+ try {
68804
+ return JSON.parse(value);
68805
+ } catch (error51) {
68806
+ throw new Error(
68807
+ `GitHub step params.${name} must be valid JSON: ${error51 instanceof Error ? error51.message : String(error51)}`
68808
+ );
68809
+ }
68810
+ }
68811
+ function isRecord2(value) {
68812
+ return typeof value === "object" && value !== null && !Array.isArray(value);
68813
+ }
68814
+
68815
+ // packages/github-primitive/src/index.ts
68816
+ init_branches();
68817
+ init_commits();
68818
+ init_repos();
68819
+ init_issues();
68820
+ init_pulls();
68821
+ init_files();
68822
+ init_users();
68823
+
66040
68824
  // packages/utils/dist/name-generator.js
66041
68825
  var ADJECTIVES = [
66042
68826
  "Blue",
@@ -66508,14 +69292,14 @@ function benchmarkPatterns(iterations = 1e4) {
66508
69292
  }
66509
69293
 
66510
69294
  // packages/utils/dist/command-resolver.js
66511
- var import_node_child_process10 = require("node:child_process");
69295
+ var import_node_child_process12 = require("node:child_process");
66512
69296
  var import_node_fs26 = __toESM(require("node:fs"), 1);
66513
69297
  function resolveCommand(command) {
66514
69298
  if (command.startsWith("/")) {
66515
69299
  return resolveSymlinks(command);
66516
69300
  }
66517
69301
  try {
66518
- const output = (0, import_node_child_process10.execSync)(`which ${command}`, {
69302
+ const output = (0, import_node_child_process12.execSync)(`which ${command}`, {
66519
69303
  encoding: "utf-8",
66520
69304
  stdio: ["pipe", "pipe", "pipe"],
66521
69305
  // Ensure we have a reasonable PATH
@@ -66549,7 +69333,7 @@ function resolveSymlinks(filePath) {
66549
69333
  }
66550
69334
  function commandExists(command) {
66551
69335
  try {
66552
- (0, import_node_child_process10.execSync)(`which ${command}`, {
69336
+ (0, import_node_child_process12.execSync)(`which ${command}`, {
66553
69337
  encoding: "utf-8",
66554
69338
  stdio: ["pipe", "pipe", "pipe"]
66555
69339
  });
@@ -66562,7 +69346,7 @@ function commandExists(command) {
66562
69346
  // packages/utils/dist/git-remote.js
66563
69347
  var fs9 = __toESM(require("node:fs"), 1);
66564
69348
  var path21 = __toESM(require("node:path"), 1);
66565
- var import_node_child_process11 = require("node:child_process");
69349
+ var import_node_child_process13 = require("node:child_process");
66566
69350
  function parseGitRemoteUrl(url2) {
66567
69351
  if (!url2)
66568
69352
  return null;
@@ -66582,7 +69366,7 @@ function getGitRemoteUrl(workingDirectory, remoteName = "origin") {
66582
69366
  if (!fs9.existsSync(gitDir)) {
66583
69367
  return null;
66584
69368
  }
66585
- const result = (0, import_node_child_process11.execSync)(`git remote get-url ${remoteName}`, {
69369
+ const result = (0, import_node_child_process13.execSync)(`git remote get-url ${remoteName}`, {
66586
69370
  cwd: workingDirectory,
66587
69371
  encoding: "utf-8",
66588
69372
  timeout: 5e3,
@@ -67713,7 +70497,7 @@ var HookRegistry = class {
67713
70497
  };
67714
70498
 
67715
70499
  // packages/trajectory/dist/integration.js
67716
- var import_node_child_process12 = require("node:child_process");
70500
+ var import_node_child_process14 = require("node:child_process");
67717
70501
 
67718
70502
  // packages/config/dist/project-namespace.js
67719
70503
  var import_node_crypto16 = __toESM(require("node:crypto"), 1);
@@ -67842,7 +70626,7 @@ function getTrajectoryEnvVars(projectRoot) {
67842
70626
  async function runTrail(args) {
67843
70627
  return new Promise((resolve4) => {
67844
70628
  const trajectoryEnv = getTrajectoryEnvVars();
67845
- const proc = (0, import_node_child_process12.spawn)("trail", args, {
70629
+ const proc = (0, import_node_child_process14.spawn)("trail", args, {
67846
70630
  cwd: getProjectPaths2().projectRoot,
67847
70631
  env: { ...process.env, ...trajectoryEnv },
67848
70632
  stdio: ["pipe", "pipe", "pipe"]
@@ -68113,7 +70897,7 @@ var TrajectoryIntegration = class {
68113
70897
  */
68114
70898
  isTrailInstalledSync() {
68115
70899
  try {
68116
- (0, import_node_child_process12.execSync)("which trail", { stdio: "pipe" });
70900
+ (0, import_node_child_process14.execSync)("which trail", { stdio: "pipe" });
68117
70901
  return true;
68118
70902
  } catch {
68119
70903
  return false;
@@ -68572,6 +71356,7 @@ init_dist2();
68572
71356
  ERROR_SEARCH_HINT,
68573
71357
  GEMINI_MODEL_OPTIONS,
68574
71358
  GeminiModels,
71359
+ GitHubClient,
68575
71360
  HARNESS_VALUES,
68576
71361
  HOOK_ABI_VERSION,
68577
71362
  HookEmitter,
@@ -68635,6 +71420,7 @@ init_dist2();
68635
71420
  createConsensusEngine,
68636
71421
  createContextCompactor,
68637
71422
  createDefaultEventLogger,
71423
+ createGitHubStep,
68638
71424
  createLogger,
68639
71425
  createMemoryAdapter,
68640
71426
  createMemoryHooks,
@@ -68694,6 +71480,7 @@ init_dist2();
68694
71480
  getSupportedPlatforms,
68695
71481
  getSupportedReasoningEfforts,
68696
71482
  getTrajectoryHooks,
71483
+ github,
68697
71484
  handleResponse,
68698
71485
  hasRelayPtyBinary,
68699
71486
  hasUnreadMessages,