feat(core): refactor project copies for v2 (#31943)

This commit is contained in:
James Long 2026-06-12 14:45:16 -04:00 committed by GitHub
commit c2e6b18076
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1461 additions and 829 deletions

View file

@ -36,12 +36,8 @@ import type {
ExperimentalConsoleSwitchOrgResponses,
ExperimentalControlPlaneMoveSessionErrors,
ExperimentalControlPlaneMoveSessionResponses,
ExperimentalProjectCopyCreateErrors,
ExperimentalProjectCopyCreateResponses,
ExperimentalProjectCopyRefreshErrors,
ExperimentalProjectCopyRefreshResponses,
ExperimentalProjectCopyRemoveErrors,
ExperimentalProjectCopyRemoveResponses,
ExperimentalProjectCopyGenerateNameErrors,
ExperimentalProjectCopyGenerateNameResponses,
ExperimentalResourceListErrors,
ExperimentalResourceListResponses,
ExperimentalSessionBackgroundErrors,
@ -303,6 +299,12 @@ import type {
V2PermissionSavedListResponses,
V2PermissionSavedRemoveErrors,
V2PermissionSavedRemoveResponses,
V2ProjectCopyCreateErrors,
V2ProjectCopyCreateResponses,
V2ProjectCopyRefreshErrors,
V2ProjectCopyRefreshResponses,
V2ProjectCopyRemoveErrors,
V2ProjectCopyRemoveResponses,
V2ProviderGetErrors,
V2ProviderGetResponses,
V2ProviderListErrors,
@ -842,107 +844,18 @@ export class Resource extends HeyApiClient {
export class ProjectCopy extends HeyApiClient {
/**
* Remove project copy
* Generate project copy name
*
* Remove a local physical copy of a project using the selected strategy.
* Generate a short name for a project copy from task context.
*/
public remove<ThrowOnError extends boolean = false>(
public generateName<ThrowOnError extends boolean = false>(
parameters: {
projectID: string
workspace?: string
directory?: string
force?: boolean
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "path", key: "projectID" },
{ in: "query", key: "workspace" },
{ in: "body", key: "directory" },
{ in: "body", key: "force" },
],
},
],
)
return (options?.client ?? this.client).delete<
ExperimentalProjectCopyRemoveResponses,
ExperimentalProjectCopyRemoveErrors,
ThrowOnError
>({
url: "/experimental/project/{projectID}/copy",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
/**
* Create project copy
*
* Create a local physical copy of a project using the selected strategy.
*/
public create<ThrowOnError extends boolean = false>(
parameters: {
projectID: string
workspace?: string
strategy?: "git_worktree"
directory?: string
name?: string
context?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "path", key: "projectID" },
{ in: "query", key: "workspace" },
{ in: "body", key: "strategy" },
{ in: "body", key: "directory" },
{ in: "body", key: "name" },
{ in: "body", key: "context" },
],
},
],
)
return (options?.client ?? this.client).post<
ExperimentalProjectCopyCreateResponses,
ExperimentalProjectCopyCreateErrors,
ThrowOnError
>({
url: "/experimental/project/{projectID}/copy",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
/**
* Refresh project copies
*
* Discover local project copies using one or all configured strategies.
*/
public refresh<ThrowOnError extends boolean = false>(
parameters: {
projectID: string
directory?: string
workspace?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
@ -952,18 +865,24 @@ export class ProjectCopy extends HeyApiClient {
{ in: "path", key: "projectID" },
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "body", key: "context" },
],
},
],
)
return (options?.client ?? this.client).post<
ExperimentalProjectCopyRefreshResponses,
ExperimentalProjectCopyRefreshErrors,
ExperimentalProjectCopyGenerateNameResponses,
ExperimentalProjectCopyGenerateNameErrors,
ThrowOnError
>({
url: "/experimental/project/{projectID}/copy/refresh",
url: "/experimental/project/{projectID}/copy/generate-name",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
}
@ -6241,6 +6160,122 @@ export class Reference extends HeyApiClient {
}
}
export class ProjectCopy2 extends HeyApiClient {
public remove<ThrowOnError extends boolean = false>(
parameters: {
projectID: string
location?: {
directory?: string
workspace?: string
}
directory?: string
force?: boolean
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "path", key: "projectID" },
{ in: "query", key: "location" },
{ in: "body", key: "directory" },
{ in: "body", key: "force" },
],
},
],
)
return (options?.client ?? this.client).delete<
V2ProjectCopyRemoveResponses,
V2ProjectCopyRemoveErrors,
ThrowOnError
>({
url: "/experimental/project/{projectID}/copy",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
public create<ThrowOnError extends boolean = false>(
parameters: {
projectID: string
location?: {
directory?: string
workspace?: string
}
strategy?: string
directory?: string
name?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "path", key: "projectID" },
{ in: "query", key: "location" },
{ in: "body", key: "strategy" },
{ in: "body", key: "directory" },
{ in: "body", key: "name" },
],
},
],
)
return (options?.client ?? this.client).post<V2ProjectCopyCreateResponses, V2ProjectCopyCreateErrors, ThrowOnError>(
{
url: "/experimental/project/{projectID}/copy",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
},
)
}
public refresh<ThrowOnError extends boolean = false>(
parameters: {
projectID: string
location?: {
directory?: string
workspace?: string
}
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "path", key: "projectID" },
{ in: "query", key: "location" },
],
},
],
)
return (options?.client ?? this.client).post<
V2ProjectCopyRefreshResponses,
V2ProjectCopyRefreshErrors,
ThrowOnError
>({
url: "/experimental/project/{projectID}/copy/refresh",
...options,
...params,
})
}
}
export class V2 extends HeyApiClient {
private _health?: Health
get health(): Health {
@ -6316,6 +6351,11 @@ export class V2 extends HeyApiClient {
get reference(): Reference {
return (this._reference ??= new Reference({ client: this.client }))
}
private _projectCopy?: ProjectCopy2
get projectCopy(): ProjectCopy2 {
return (this._projectCopy ??= new ProjectCopy2({ client: this.client }))
}
}
export class OpencodeClient extends HeyApiClient {

View file

@ -56,6 +56,7 @@ export type Event =
| EventPermissionV2Asked
| EventPermissionV2Replied
| EventReferenceUpdated
| EventProjectDirectoriesUpdated
| EventFileWatcherUpdated
| EventPtyCreated
| EventPtyUpdated
@ -75,7 +76,6 @@ export type Event =
| EventMcpToolsChanged
| EventMcpBrowserOpenFailed
| EventCommandExecuted
| EventProjectDirectoriesUpdated
| EventProjectUpdated
| EventSessionStatus
| EventSessionIdle
@ -1294,6 +1294,13 @@ export type GlobalEvent = {
[key: string]: unknown
}
}
| {
id: string
type: "project.directories.updated"
properties: {
projectID: string
}
}
| {
id: string
type: "file.watcher.updated"
@ -1479,13 +1486,6 @@ export type GlobalEvent = {
messageID: string
}
}
| {
id: string
type: "project.directories.updated"
properties: {
projectID: string
}
}
| {
id: string
type: "project.updated"
@ -2464,14 +2464,6 @@ export type ProjectNotFoundError = {
message: string
}
export type ProjectCopyError = {
name: "ProjectCopyError"
data: {
message: string
forceRequired?: boolean
}
}
export type PtyNotFoundError = {
_tag: "PtyNotFoundError"
ptyID: string
@ -2767,6 +2759,14 @@ export type ProviderNotFoundError = {
message: string
}
export type ProjectCopyError = {
name: "ProjectCopyError"
data: {
message: string
forceRequired?: boolean
}
}
export type EffectHttpApiErrorForbidden = {
_tag: "Forbidden"
}
@ -3699,13 +3699,9 @@ export type ConfigV2ExperimentalPolicy = {
export type ProjectDirectories = Array<{
directory: string
type: "main" | "root" | "git_worktree"
strategy?: string
}>
export type ProjectCopyCopy = {
directory: string
}
export type LocationInfo = {
directory: string
workspaceID?: string
@ -4226,6 +4222,10 @@ export type ReferenceInfo = {
source: ReferenceLocalSource | ReferenceGitSource
}
export type ProjectCopyCopy = {
directory: string
}
export type EventModelsDevRefreshed = {
id: string
type: "models-dev.refreshed"
@ -4938,6 +4938,14 @@ export type EventReferenceUpdated = {
}
}
export type EventProjectDirectoriesUpdated = {
id: string
type: "project.directories.updated"
properties: {
projectID: string
}
}
export type EventFileWatcherUpdated = {
id: string
type: "file.watcher.updated"
@ -5087,14 +5095,6 @@ export type EventCommandExecuted = {
}
}
export type EventProjectDirectoriesUpdated = {
id: string
type: "project.directories.updated"
properties: {
projectID: string
}
}
export type EventProjectUpdated = {
id: string
type: "project.updated"
@ -6994,107 +6994,41 @@ export type ProjectDirectoriesResponses = {
export type ProjectDirectoriesResponse = ProjectDirectoriesResponses[keyof ProjectDirectoriesResponses]
export type ExperimentalProjectCopyRemoveData = {
export type ExperimentalProjectCopyGenerateNameData = {
body?: {
directory: string
force: boolean
}
path: {
projectID: string
}
query?: {
workspace?: string
}
url: "/experimental/project/{projectID}/copy"
}
export type ExperimentalProjectCopyRemoveErrors = {
/**
* ProjectCopyError | InvalidRequestError
*/
400: ProjectCopyError | InvalidRequestError
}
export type ExperimentalProjectCopyRemoveError =
ExperimentalProjectCopyRemoveErrors[keyof ExperimentalProjectCopyRemoveErrors]
export type ExperimentalProjectCopyRemoveResponses = {
/**
* Project copy removed
*/
204: void
}
export type ExperimentalProjectCopyRemoveResponse =
ExperimentalProjectCopyRemoveResponses[keyof ExperimentalProjectCopyRemoveResponses]
export type ExperimentalProjectCopyCreateData = {
body?: {
strategy: "git_worktree"
directory: string
name?: string
context?: string
}
path: {
projectID: string
}
query?: {
workspace?: string
}
url: "/experimental/project/{projectID}/copy"
}
export type ExperimentalProjectCopyCreateErrors = {
/**
* ProjectCopyError | InvalidRequestError
*/
400: ProjectCopyError | InvalidRequestError
}
export type ExperimentalProjectCopyCreateError =
ExperimentalProjectCopyCreateErrors[keyof ExperimentalProjectCopyCreateErrors]
export type ExperimentalProjectCopyCreateResponses = {
/**
* Project copy created
*/
200: ProjectCopyCopy
}
export type ExperimentalProjectCopyCreateResponse =
ExperimentalProjectCopyCreateResponses[keyof ExperimentalProjectCopyCreateResponses]
export type ExperimentalProjectCopyRefreshData = {
body?: never
path: {
projectID: string
}
query?: {
directory?: string
workspace?: string
}
url: "/experimental/project/{projectID}/copy/refresh"
url: "/experimental/project/{projectID}/copy/generate-name"
}
export type ExperimentalProjectCopyRefreshErrors = {
export type ExperimentalProjectCopyGenerateNameErrors = {
/**
* ProjectCopyError | InvalidRequestError
* Bad request
*/
400: ProjectCopyError | InvalidRequestError
400: BadRequestError
}
export type ExperimentalProjectCopyRefreshError =
ExperimentalProjectCopyRefreshErrors[keyof ExperimentalProjectCopyRefreshErrors]
export type ExperimentalProjectCopyGenerateNameError =
ExperimentalProjectCopyGenerateNameErrors[keyof ExperimentalProjectCopyGenerateNameErrors]
export type ExperimentalProjectCopyRefreshResponses = {
export type ExperimentalProjectCopyGenerateNameResponses = {
/**
* Project copies refreshed
* Success
*/
204: void
200: {
name: string
}
}
export type ExperimentalProjectCopyRefreshResponse =
ExperimentalProjectCopyRefreshResponses[keyof ExperimentalProjectCopyRefreshResponses]
export type ExperimentalProjectCopyGenerateNameResponse =
ExperimentalProjectCopyGenerateNameResponses[keyof ExperimentalProjectCopyGenerateNameResponses]
export type PtyShellsData = {
body?: never
@ -10951,6 +10885,109 @@ export type V2ReferenceListResponses = {
export type V2ReferenceListResponse = V2ReferenceListResponses[keyof V2ReferenceListResponses]
export type V2ProjectCopyRemoveData = {
body?: {
directory: string
force: boolean
}
path: {
projectID: string
}
query?: {
location?: {
directory?: string
workspace?: string
}
}
url: "/experimental/project/{projectID}/copy"
}
export type V2ProjectCopyRemoveErrors = {
/**
* ProjectCopyError | InvalidRequestError
*/
400: ProjectCopyError | InvalidRequestError
}
export type V2ProjectCopyRemoveError = V2ProjectCopyRemoveErrors[keyof V2ProjectCopyRemoveErrors]
export type V2ProjectCopyRemoveResponses = {
/**
* <No Content>
*/
204: void
}
export type V2ProjectCopyRemoveResponse = V2ProjectCopyRemoveResponses[keyof V2ProjectCopyRemoveResponses]
export type V2ProjectCopyCreateData = {
body?: {
strategy: string
directory: string
name?: string
}
path: {
projectID: string
}
query?: {
location?: {
directory?: string
workspace?: string
}
}
url: "/experimental/project/{projectID}/copy"
}
export type V2ProjectCopyCreateErrors = {
/**
* ProjectCopyError | InvalidRequestError
*/
400: ProjectCopyError | InvalidRequestError
}
export type V2ProjectCopyCreateError = V2ProjectCopyCreateErrors[keyof V2ProjectCopyCreateErrors]
export type V2ProjectCopyCreateResponses = {
/**
* ProjectCopy.Copy
*/
200: ProjectCopyCopy
}
export type V2ProjectCopyCreateResponse = V2ProjectCopyCreateResponses[keyof V2ProjectCopyCreateResponses]
export type V2ProjectCopyRefreshData = {
body?: never
path: {
projectID: string
}
query?: {
location?: {
directory?: string
workspace?: string
}
}
url: "/experimental/project/{projectID}/copy/refresh"
}
export type V2ProjectCopyRefreshErrors = {
/**
* ProjectCopyError | InvalidRequestError
*/
400: ProjectCopyError | InvalidRequestError
}
export type V2ProjectCopyRefreshError = V2ProjectCopyRefreshErrors[keyof V2ProjectCopyRefreshErrors]
export type V2ProjectCopyRefreshResponses = {
/**
* <No Content>
*/
204: void
}
export type V2ProjectCopyRefreshResponse = V2ProjectCopyRefreshResponses[keyof V2ProjectCopyRefreshResponses]
export type PtyConnectData = {
body?: never
path: {