@morphllm/morphsdk 0.2.110 → 0.2.111

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.
@@ -28,8 +28,10 @@ interface GitHubClientConfig {
28
28
  apiKey?: string;
29
29
  /** Default installation ID to use (optional, can be specified per-request) */
30
30
  installationId?: string;
31
- /** Base URL for the Morph API (defaults to https://api.morphllm.com) */
31
+ /** Base URL for the Morph landing API — used for Octokit-based endpoints (defaults to https://api.morphllm.com) */
32
32
  baseUrl?: string;
33
+ /** Base URL for the browser backend API — used for CRUD endpoints (defaults to https://browser.morphllm.com) */
34
+ backendUrl?: string;
33
35
  /** Request timeout in milliseconds */
34
36
  timeout?: number;
35
37
  /** Enable debug logging */
@@ -47,6 +49,151 @@ interface Installation {
47
49
  accountType: "User" | "Organization";
48
50
  /** Custom display name (set in Morph dashboard) */
49
51
  displayName?: string;
52
+ /** Whether check runs are disabled (only PR comments posted) */
53
+ disableCheckRun: boolean;
54
+ /** Whether to keep all previous PR comments (vs. replacing with latest) */
55
+ keepCommentHistory: boolean;
56
+ /** Browser automation model used for preview tests */
57
+ model: string;
58
+ }
59
+ /**
60
+ * Input for updating installation settings
61
+ */
62
+ interface UpdateInstallationInput {
63
+ /** Installation ID to update */
64
+ installationId: string;
65
+ /** Custom display name */
66
+ displayName?: string;
67
+ /** Whether to disable check runs */
68
+ disableCheckRun?: boolean;
69
+ /** Whether to keep comment history */
70
+ keepCommentHistory?: boolean;
71
+ /** Browser automation model */
72
+ model?: string;
73
+ }
74
+ /**
75
+ * Site authentication credentials for a repo or project
76
+ */
77
+ interface SiteAuth {
78
+ /** Login username or email */
79
+ username: string | null;
80
+ /** Login password */
81
+ password: string | null;
82
+ }
83
+ /**
84
+ * A repository with its Morph configuration
85
+ */
86
+ interface RepoConfig {
87
+ /** Database UUID — use this for update/remove operations */
88
+ id: string;
89
+ /** GitHub's numeric repo ID */
90
+ githubId: number;
91
+ /** Full name including owner (e.g., "acme/app") */
92
+ fullName: string;
93
+ /** Repository name (e.g., "app") */
94
+ name: string;
95
+ /** Whether Morph tests are enabled */
96
+ enabled: boolean;
97
+ /** Whether to also test on mobile viewport */
98
+ testMobile: boolean;
99
+ /** Path filter — only trigger tests when files match this prefix */
100
+ pathFilter: string | null;
101
+ /** Custom instructions for the AI agent */
102
+ customInstructions: string | null;
103
+ /** Site authentication credentials */
104
+ auth: SiteAuth | null;
105
+ }
106
+ /**
107
+ * Input for updating a repo's configuration
108
+ */
109
+ interface UpdateRepoInput {
110
+ /** Repo DB ID (from RepoConfig.id) */
111
+ repoId: string;
112
+ /** Whether Morph tests are enabled */
113
+ enabled?: boolean;
114
+ /** Whether to also test on mobile viewport */
115
+ testMobile?: boolean;
116
+ /** Path filter for conditional triggers */
117
+ pathFilter?: string | null;
118
+ /** Custom instructions for the AI agent */
119
+ customInstructions?: string | null;
120
+ /** Site auth credentials (null to clear) */
121
+ auth?: {
122
+ username?: string;
123
+ password?: string;
124
+ cookies?: unknown;
125
+ } | null;
126
+ }
127
+ /**
128
+ * Input for syncing repos from GitHub
129
+ */
130
+ interface SyncReposInput {
131
+ /** Installation ID to sync repos for */
132
+ installationId: string;
133
+ }
134
+ /**
135
+ * A monorepo sub-project scoped under a repo
136
+ */
137
+ interface Project {
138
+ /** Project DB UUID */
139
+ id: string;
140
+ /** Parent repo DB UUID */
141
+ repoId: string;
142
+ /** Project name */
143
+ name: string;
144
+ /** Path filter within the repo */
145
+ pathFilter: string | null;
146
+ /** Whether tests are enabled */
147
+ enabled: boolean;
148
+ /** Whether to test on mobile viewport */
149
+ testMobile: boolean;
150
+ /** Custom instructions for the AI agent */
151
+ customInstructions: string | null;
152
+ /** Site authentication credentials */
153
+ auth: SiteAuth | null;
154
+ /** Creation timestamp (ISO 8601) */
155
+ createdAt: string;
156
+ }
157
+ /**
158
+ * Input for creating a project
159
+ */
160
+ interface CreateProjectInput {
161
+ /** Parent repo DB ID */
162
+ repoId: string;
163
+ /** Project name (must be unique within the repo) */
164
+ name: string;
165
+ /** Path filter within the repo (e.g., "packages/web/") */
166
+ pathFilter: string;
167
+ /** Custom instructions for the AI agent */
168
+ customInstructions?: string;
169
+ }
170
+ /**
171
+ * Input for updating a project
172
+ */
173
+ interface UpdateProjectInput {
174
+ /** Project DB ID */
175
+ projectId: string;
176
+ /** Whether tests are enabled */
177
+ enabled?: boolean;
178
+ /** Whether to test on mobile viewport */
179
+ testMobile?: boolean;
180
+ /** Path filter within the repo */
181
+ pathFilter?: string | null;
182
+ /** Custom instructions for the AI agent */
183
+ customInstructions?: string | null;
184
+ /** Site auth credentials (null to clear) */
185
+ auth?: {
186
+ username?: string;
187
+ password?: string;
188
+ cookies?: unknown;
189
+ } | null;
190
+ }
191
+ /**
192
+ * Input for listing projects
193
+ */
194
+ interface ListProjectsInput {
195
+ /** Parent repo DB ID */
196
+ repoId: string;
50
197
  }
51
198
  /**
52
199
  * A GitHub repository
@@ -370,7 +517,8 @@ declare class PermissionError extends GitHubError {
370
517
  */
371
518
  declare class GitHubClient {
372
519
  private apiKey;
373
- private baseUrl;
520
+ private landingUrl;
521
+ private backendUrl;
374
522
  private timeout;
375
523
  private debug;
376
524
  private defaultInstallationId?;
@@ -378,10 +526,33 @@ declare class GitHubClient {
378
526
  installations: {
379
527
  list: () => Promise<Installation[]>;
380
528
  get: (installationId: string) => Promise<Installation>;
529
+ update: (input: UpdateInstallationInput) => Promise<Installation>;
530
+ disconnect: (installationId: string) => Promise<{
531
+ success: boolean;
532
+ alreadyDeleted: boolean;
533
+ }>;
381
534
  };
382
535
  /** Repository operations */
383
536
  repos: {
384
- list: (input: ListReposInput) => Promise<Repo[]>;
537
+ list: (input: ListReposInput) => Promise<RepoConfig[]>;
538
+ get: (repoId: string) => Promise<RepoConfig>;
539
+ update: (input: UpdateRepoInput) => Promise<RepoConfig>;
540
+ remove: (repoId: string) => Promise<{
541
+ success: boolean;
542
+ alreadyRemoved: boolean;
543
+ }>;
544
+ sync: (input: SyncReposInput) => Promise<{
545
+ count: number;
546
+ }>;
547
+ };
548
+ /** Project operations (monorepo sub-projects) */
549
+ projects: {
550
+ list: (input: ListProjectsInput) => Promise<Project[]>;
551
+ create: (input: CreateProjectInput) => Promise<Project>;
552
+ update: (input: UpdateProjectInput) => Promise<Project>;
553
+ delete: (projectId: string) => Promise<{
554
+ success: boolean;
555
+ }>;
385
556
  };
386
557
  /** Pull request operations */
387
558
  pullRequests: {
@@ -404,18 +575,41 @@ declare class GitHubClient {
404
575
  create: (input: CreateCheckRunInput) => Promise<CheckRun>;
405
576
  update: (input: UpdateCheckRunInput) => Promise<CheckRun>;
406
577
  };
578
+ /**
579
+ * Get the GitHub App installation URL.
580
+ * Users visit this URL once to install the Morph GitHub App on their account/org.
581
+ */
582
+ getInstallUrl(): string;
407
583
  constructor(config?: GitHubClientConfig);
408
584
  /**
409
- * Make an API request to the Morph GitHub proxy
585
+ * Make an API request to the browser backend (CRUD endpoints)
410
586
  */
411
587
  private request;
588
+ /**
589
+ * Make an API request to the landing app (Octokit-based endpoints)
590
+ */
591
+ private landingRequest;
592
+ /**
593
+ * Shared fetch logic for both backend and landing requests
594
+ */
595
+ private _fetch;
412
596
  /**
413
597
  * Get the installation ID to use for a request
414
598
  */
415
599
  private getInstallationId;
416
600
  private listInstallations;
417
601
  private getInstallation;
602
+ private updateInstallation;
603
+ private disconnectInstallation;
418
604
  private listRepos;
605
+ private getRepo;
606
+ private updateRepo;
607
+ private removeRepo;
608
+ private syncRepos;
609
+ private listProjects;
610
+ private createProject;
611
+ private updateProject;
612
+ private deleteProject;
419
613
  private listPullRequests;
420
614
  private getPullRequest;
421
615
  private listDeployments;
@@ -730,4 +924,4 @@ declare class MorphClient {
730
924
  constructor(config?: MorphClientConfig);
731
925
  }
732
926
 
733
- export { AnthropicToolFactory as A, type Comment as C, type Deployment as D, type FileChange as F, GitHubClient as G, type Installation as I, type ListReposInput as L, MorphClient as M, NoInstallationError as N, OpenAIToolFactory as O, type PullRequest as P, type Repo as R, type UpdateCommentInput as U, VercelToolFactory as V, type MorphClientConfig as a, type GitHubClientConfig as b, type PullRequestWithContext as c, type CheckRun as d, type ListPullRequestsInput as e, type GetPullRequestInput as f, type ListDeploymentsInput as g, type ListCommentsInput as h, type CreateCommentInput as i, type DeleteCommentInput as j, type CreateCheckRunInput as k, type UpdateCheckRunInput as l, GitHubError as m, NotFoundError as n, PermissionError as o };
927
+ export { AnthropicToolFactory as A, type Comment as C, type Deployment as D, type FileChange as F, GitHubClient as G, type Installation as I, type ListReposInput as L, MorphClient as M, NoInstallationError as N, OpenAIToolFactory as O, type Project as P, type Repo as R, type SiteAuth as S, type UpdateCommentInput as U, VercelToolFactory as V, type MorphClientConfig as a, type GitHubClientConfig as b, type RepoConfig as c, type PullRequest as d, type PullRequestWithContext as e, type CheckRun as f, type ListPullRequestsInput as g, type GetPullRequestInput as h, type ListDeploymentsInput as i, type ListCommentsInput as j, type CreateCommentInput as k, type DeleteCommentInput as l, type CreateCheckRunInput as m, type UpdateCheckRunInput as n, type UpdateInstallationInput as o, type UpdateRepoInput as p, type SyncReposInput as q, type CreateProjectInput as r, type UpdateProjectInput as s, type ListProjectsInput as t, GitHubError as u, NotFoundError as v, PermissionError as w };
package/dist/client.cjs CHANGED
@@ -3688,11 +3688,13 @@ var PermissionError = class extends GitHubError {
3688
3688
  };
3689
3689
 
3690
3690
  // tools/github/core.ts
3691
- var DEFAULT_BASE_URL = "https://api.morphllm.com";
3691
+ var LANDING_BASE_URL = "https://api.morphllm.com";
3692
+ var BACKEND_BASE_URL = "https://browser.morphllm.com";
3692
3693
  var DEFAULT_TIMEOUT2 = 3e4;
3693
3694
  var GitHubClient = class {
3694
3695
  apiKey;
3695
- baseUrl;
3696
+ landingUrl;
3697
+ backendUrl;
3696
3698
  timeout;
3697
3699
  debug;
3698
3700
  defaultInstallationId;
@@ -3700,6 +3702,8 @@ var GitHubClient = class {
3700
3702
  installations;
3701
3703
  /** Repository operations */
3702
3704
  repos;
3705
+ /** Project operations (monorepo sub-projects) */
3706
+ projects;
3703
3707
  /** Pull request operations */
3704
3708
  pullRequests;
3705
3709
  /** Deployment operations */
@@ -3708,9 +3712,17 @@ var GitHubClient = class {
3708
3712
  comments;
3709
3713
  /** Check run operations */
3710
3714
  checkRuns;
3715
+ /**
3716
+ * Get the GitHub App installation URL.
3717
+ * Users visit this URL once to install the Morph GitHub App on their account/org.
3718
+ */
3719
+ getInstallUrl() {
3720
+ return "https://github.com/apps/morph-subagents/installations/new";
3721
+ }
3711
3722
  constructor(config = {}) {
3712
3723
  this.apiKey = config.apiKey || process.env.MORPH_API_KEY || "";
3713
- this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
3724
+ this.landingUrl = config.baseUrl || LANDING_BASE_URL;
3725
+ this.backendUrl = config.backendUrl || BACKEND_BASE_URL;
3714
3726
  this.timeout = config.timeout || DEFAULT_TIMEOUT2;
3715
3727
  this.debug = config.debug || false;
3716
3728
  this.defaultInstallationId = config.installationId;
@@ -3719,10 +3731,22 @@ var GitHubClient = class {
3719
3731
  }
3720
3732
  this.installations = {
3721
3733
  list: this.listInstallations.bind(this),
3722
- get: this.getInstallation.bind(this)
3734
+ get: this.getInstallation.bind(this),
3735
+ update: this.updateInstallation.bind(this),
3736
+ disconnect: this.disconnectInstallation.bind(this)
3723
3737
  };
3724
3738
  this.repos = {
3725
- list: this.listRepos.bind(this)
3739
+ list: this.listRepos.bind(this),
3740
+ get: this.getRepo.bind(this),
3741
+ update: this.updateRepo.bind(this),
3742
+ remove: this.removeRepo.bind(this),
3743
+ sync: this.syncRepos.bind(this)
3744
+ };
3745
+ this.projects = {
3746
+ list: this.listProjects.bind(this),
3747
+ create: this.createProject.bind(this),
3748
+ update: this.updateProject.bind(this),
3749
+ delete: this.deleteProject.bind(this)
3726
3750
  };
3727
3751
  this.pullRequests = {
3728
3752
  list: this.listPullRequests.bind(this),
@@ -3743,10 +3767,24 @@ var GitHubClient = class {
3743
3767
  };
3744
3768
  }
3745
3769
  /**
3746
- * Make an API request to the Morph GitHub proxy
3770
+ * Make an API request to the browser backend (CRUD endpoints)
3747
3771
  */
3748
3772
  async request(method, path5, body) {
3749
- const url = `${this.baseUrl}${path5}`;
3773
+ return this._fetch(this.backendUrl, method, path5, body);
3774
+ }
3775
+ // TODO: These endpoints use Octokit and currently live in landing.
3776
+ // Move them to the backend so all GitHub SDK traffic goes through a single URL.
3777
+ /**
3778
+ * Make an API request to the landing app (Octokit-based endpoints)
3779
+ */
3780
+ async landingRequest(method, path5, body) {
3781
+ return this._fetch(this.landingUrl, method, path5, body);
3782
+ }
3783
+ /**
3784
+ * Shared fetch logic for both backend and landing requests
3785
+ */
3786
+ async _fetch(baseUrl, method, path5, body) {
3787
+ const url = `${baseUrl}${path5}`;
3750
3788
  if (this.debug) {
3751
3789
  console.log(`[GitHub SDK] ${method} ${path5}`, body || "");
3752
3790
  }
@@ -3765,7 +3803,7 @@ var GitHubClient = class {
3765
3803
  clearTimeout(timeoutId);
3766
3804
  if (!response.ok) {
3767
3805
  const errorData = await response.json().catch(() => ({}));
3768
- const message = errorData.error || errorData.message || response.statusText;
3806
+ const message = errorData.error || errorData.detail || errorData.message || response.statusText;
3769
3807
  if (this.debug) {
3770
3808
  console.error(`[GitHub SDK] Error ${response.status}:`, message);
3771
3809
  }
@@ -3815,6 +3853,15 @@ var GitHubClient = class {
3815
3853
  async getInstallation(installationId) {
3816
3854
  return this.request("GET", `/api/v1/github/installations/${installationId}`);
3817
3855
  }
3856
+ async updateInstallation(input) {
3857
+ if (this.debug) console.log("[GitHub SDK] updateInstallation", input.installationId);
3858
+ const { installationId, ...body } = input;
3859
+ return this.request("PATCH", `/api/v1/github/installations/${installationId}`, body);
3860
+ }
3861
+ async disconnectInstallation(installationId) {
3862
+ if (this.debug) console.log("[GitHub SDK] disconnectInstallation", installationId);
3863
+ return this.request("DELETE", `/api/v1/github/installations/${installationId}`);
3864
+ }
3818
3865
  // ==========================================================================
3819
3866
  // Repositories
3820
3867
  // ==========================================================================
@@ -3825,8 +3872,51 @@ var GitHubClient = class {
3825
3872
  }
3826
3873
  return this.request("GET", `/api/v1/github/installations/${installationId}/repos`);
3827
3874
  }
3875
+ async getRepo(repoId) {
3876
+ if (this.debug) console.log("[GitHub SDK] getRepo", repoId);
3877
+ return this.request("GET", `/api/v1/github/repos/${repoId}`);
3878
+ }
3879
+ async updateRepo(input) {
3880
+ if (this.debug) console.log("[GitHub SDK] updateRepo", input.repoId);
3881
+ const { repoId, ...body } = input;
3882
+ return this.request("PATCH", `/api/v1/github/repos/${repoId}`, body);
3883
+ }
3884
+ async removeRepo(repoId) {
3885
+ if (this.debug) console.log("[GitHub SDK] removeRepo", repoId);
3886
+ return this.request("DELETE", `/api/v1/github/repos/${repoId}`);
3887
+ }
3888
+ async syncRepos(input) {
3889
+ const installationId = input.installationId || this.defaultInstallationId;
3890
+ if (!installationId) {
3891
+ throw new NoInstallationError("installationId required. Call installations.list() first.");
3892
+ }
3893
+ if (this.debug) console.log("[GitHub SDK] syncRepos", installationId);
3894
+ return this.request("POST", `/api/v1/github/installations/${installationId}/repos/sync`);
3895
+ }
3896
+ // ==========================================================================
3897
+ // Projects (monorepo sub-projects)
3898
+ // ==========================================================================
3899
+ async listProjects(input) {
3900
+ if (this.debug) console.log("[GitHub SDK] listProjects", input.repoId);
3901
+ return this.request("GET", `/api/v1/github/repos/${input.repoId}/projects`);
3902
+ }
3903
+ async createProject(input) {
3904
+ if (this.debug) console.log("[GitHub SDK] createProject", input.repoId, input.name);
3905
+ const { repoId, ...body } = input;
3906
+ return this.request("POST", `/api/v1/github/repos/${repoId}/projects`, body);
3907
+ }
3908
+ async updateProject(input) {
3909
+ if (this.debug) console.log("[GitHub SDK] updateProject", input.projectId);
3910
+ const { projectId, ...body } = input;
3911
+ return this.request("PATCH", `/api/v1/github/projects/${projectId}`, body);
3912
+ }
3913
+ async deleteProject(projectId) {
3914
+ if (this.debug) console.log("[GitHub SDK] deleteProject", projectId);
3915
+ return this.request("DELETE", `/api/v1/github/projects/${projectId}`);
3916
+ }
3828
3917
  // ==========================================================================
3829
3918
  // Pull Requests
3919
+ // TODO: Move to backend — currently uses Octokit in landing
3830
3920
  // ==========================================================================
3831
3921
  async listPullRequests(input) {
3832
3922
  const installationId = this.getInstallationId(input);
@@ -3836,7 +3926,7 @@ var GitHubClient = class {
3836
3926
  ...input.state && { state: input.state },
3837
3927
  ...installationId && { installationId }
3838
3928
  });
3839
- return this.request("GET", `/api/v1/github/pulls?${params}`);
3929
+ return this.landingRequest("GET", `/api/v1/github/pulls?${params}`);
3840
3930
  }
3841
3931
  async getPullRequest(input) {
3842
3932
  const installationId = this.getInstallationId(input);
@@ -3845,13 +3935,14 @@ var GitHubClient = class {
3845
3935
  repo: input.repo,
3846
3936
  ...installationId && { installationId }
3847
3937
  });
3848
- return this.request(
3938
+ return this.landingRequest(
3849
3939
  "GET",
3850
3940
  `/api/v1/github/pulls/${input.number}?${params}`
3851
3941
  );
3852
3942
  }
3853
3943
  // ==========================================================================
3854
3944
  // Deployments
3945
+ // TODO: Move to backend — currently uses Octokit in landing
3855
3946
  // ==========================================================================
3856
3947
  async listDeployments(input) {
3857
3948
  const installationId = this.getInstallationId(input);
@@ -3862,10 +3953,11 @@ var GitHubClient = class {
3862
3953
  ...input.environment && { environment: input.environment },
3863
3954
  ...installationId && { installationId }
3864
3955
  });
3865
- return this.request("GET", `/api/v1/github/deployments?${params}`);
3956
+ return this.landingRequest("GET", `/api/v1/github/deployments?${params}`);
3866
3957
  }
3867
3958
  // ==========================================================================
3868
3959
  // Comments
3960
+ // TODO: Move to backend — currently uses Octokit in landing
3869
3961
  // ==========================================================================
3870
3962
  async listComments(input) {
3871
3963
  const installationId = this.getInstallationId(input);
@@ -3875,11 +3967,11 @@ var GitHubClient = class {
3875
3967
  pr: String(input.pr),
3876
3968
  ...installationId && { installationId }
3877
3969
  });
3878
- return this.request("GET", `/api/v1/github/comments?${params}`);
3970
+ return this.landingRequest("GET", `/api/v1/github/comments?${params}`);
3879
3971
  }
3880
3972
  async createComment(input) {
3881
3973
  const installationId = this.getInstallationId(input);
3882
- return this.request("POST", "/api/v1/github/comments", {
3974
+ return this.landingRequest("POST", "/api/v1/github/comments", {
3883
3975
  owner: input.owner,
3884
3976
  repo: input.repo,
3885
3977
  pr: input.pr,
@@ -3889,7 +3981,7 @@ var GitHubClient = class {
3889
3981
  }
3890
3982
  async updateComment(input) {
3891
3983
  const installationId = this.getInstallationId(input);
3892
- return this.request("PATCH", `/api/v1/github/comments/${input.commentId}`, {
3984
+ return this.landingRequest("PATCH", `/api/v1/github/comments/${input.commentId}`, {
3893
3985
  owner: input.owner,
3894
3986
  repo: input.repo,
3895
3987
  body: input.body,
@@ -3903,14 +3995,15 @@ var GitHubClient = class {
3903
3995
  repo: input.repo,
3904
3996
  ...installationId && { installationId }
3905
3997
  });
3906
- await this.request("DELETE", `/api/v1/github/comments/${input.commentId}?${params}`);
3998
+ await this.landingRequest("DELETE", `/api/v1/github/comments/${input.commentId}?${params}`);
3907
3999
  }
3908
4000
  // ==========================================================================
3909
4001
  // Check Runs
4002
+ // TODO: Move to backend — currently uses Octokit in landing
3910
4003
  // ==========================================================================
3911
4004
  async createCheckRun(input) {
3912
4005
  const installationId = this.getInstallationId(input);
3913
- return this.request("POST", "/api/v1/github/check-runs", {
4006
+ return this.landingRequest("POST", "/api/v1/github/check-runs", {
3914
4007
  owner: input.owner,
3915
4008
  repo: input.repo,
3916
4009
  sha: input.sha,
@@ -3923,7 +4016,7 @@ var GitHubClient = class {
3923
4016
  }
3924
4017
  async updateCheckRun(input) {
3925
4018
  const installationId = this.getInstallationId(input);
3926
- return this.request("PATCH", `/api/v1/github/check-runs/${input.checkRunId}`, {
4019
+ return this.landingRequest("PATCH", `/api/v1/github/check-runs/${input.checkRunId}`, {
3927
4020
  owner: input.owner,
3928
4021
  repo: input.repo,
3929
4022
  ...input.status && { status: input.status },