mirror of
https://github.com/stablyai/orca.git
synced 2026-11-01 09:37:33 +00:00
* feat(ports): host-scoped port scan and stop on the server Add workspacePorts.scanHost/killHost, addressed by workspace and resolved on the server to the workspace's own execution host (this machine or one of its SSH hosts). Stop is bound to the host its row was scanned on and is refused on SSH hosts, where ownership cannot be proven. Advertised as workspace-ports.host-scoped.v1. * fix(ports): only this host's workspaces authorize Stop; a failed relay scan is not empty Port ownership probes now come from host routing instead of the repo row's connectionId, so an SSH repo that carries only executionHostId (or a runtime- hosted repo) can no longer make a local listener look workspace-owned. The relay's ports.detect now fails when it could not read the socket table (unreadable /proc/net/tcp, or neither Windows scanner answering) instead of answering an empty list, so a host scan reports unavailable rather than none. --------- Co-authored-by: m4air <m4air@Mac.localdomain>
89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
export type WorkspacePortProbe = {
|
|
id: string
|
|
repoId: string
|
|
displayName: string
|
|
path: string
|
|
}
|
|
|
|
export type WorkspacePortAttributionConfidence = 'cwd' | 'command' | 'none'
|
|
|
|
export type WorkspacePortOwner = {
|
|
worktreeId: string
|
|
repoId: string
|
|
displayName: string
|
|
path: string
|
|
confidence: WorkspacePortAttributionConfidence
|
|
}
|
|
|
|
type WorkspacePortBase = {
|
|
id: string
|
|
/** Address reported by the OS listener. May be a wildcard bind. */
|
|
bindHost: string
|
|
/** Address the renderer should copy/open. Wildcard binds are normalized to localhost. */
|
|
connectHost: string
|
|
port: number
|
|
pid?: number
|
|
processName?: string
|
|
protocol: 'http' | 'https' | 'unknown'
|
|
}
|
|
|
|
export type WorkspacePort =
|
|
| (WorkspacePortBase & {
|
|
kind: 'workspace'
|
|
owner: WorkspacePortOwner
|
|
/** Origin captured from terminal output (e.g. Vite's `Network: https://...:3001/`).
|
|
* Only set when a workspace-attributed PTY printed a URL whose port matches
|
|
* this listener. Origin only — never includes path, query, fragment, or
|
|
* userinfo. Prefer this over `protocol://connectHost:port` for the open and
|
|
* copy-link actions. */
|
|
advertisedUrl?: string
|
|
})
|
|
| (WorkspacePortBase & {
|
|
kind: 'container'
|
|
})
|
|
| (WorkspacePortBase & {
|
|
kind: 'external'
|
|
})
|
|
|
|
export type WorkspacePortScanRequest = {
|
|
repoId?: string
|
|
}
|
|
|
|
export type WorkspacePortAdvertisedUrlChangedEvent = {
|
|
worktreeId: string
|
|
port: number
|
|
}
|
|
|
|
export type WorkspacePortKillRequest = {
|
|
repoId?: string
|
|
pid: number
|
|
port: number
|
|
}
|
|
|
|
export type WorkspacePortKillResult =
|
|
| { ok: true }
|
|
| {
|
|
ok: false
|
|
reason: string
|
|
}
|
|
|
|
export type WorkspacePortScanResult = {
|
|
platform: NodeJS.Platform | 'unknown'
|
|
scannedAt: number
|
|
ports: WorkspacePort[]
|
|
unavailableReason?: string
|
|
}
|
|
|
|
/** A scan of one execution host, named endpoint-relative (`local` or `ssh:<target>` as the host sees it). */
|
|
export type WorkspacePortHostScanResult = WorkspacePortScanResult & {
|
|
executionHostId: string
|
|
}
|
|
|
|
export type WorkspacePortHostKillRequest = {
|
|
worktree: string
|
|
/** The host the row was scanned on; Stop is refused when the workspace now resolves elsewhere. */
|
|
executionHostId: string
|
|
pid: number
|
|
port: number
|
|
}
|