mirror of
https://github.com/stablyai/orca.git
synced 2026-10-16 08:03:09 +00:00
Persist automation run context from UI saves
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -192,6 +192,7 @@ Done means: reviewers and future agents can understand the vision, implementatio
|
||||
- [x] 2026-06-12: Seeded New Workspace run-target selection from the incoming task source context so Linear/Jira starts preselect the logical project/source host instead of the ambient active repo; verified with a focused composer host-boundary test, targeted oxlint, and full typecheck.
|
||||
- [x] 2026-06-12: Added explicit disabled-reason copy for external automation actions when an SSH host is disconnected/connecting, another action is in flight, or the local/remote automation source tool is missing; verified with focused availability tests, targeted oxlint, git diff --check, and full typecheck.
|
||||
- [x] 2026-06-12: Added Tasks source-host availability for remote servers that are still loading capabilities or lack task-source-context.v1, so older servers degrade with explicit update/checking copy instead of looking connected-but-empty; verified with focused TaskPage/source-summary tests, targeted oxlint, git diff --check, and full typecheck.
|
||||
- [x] 2026-06-12: Updated the Automations UI save path to persist WorkspaceRunContext for created/edited Orca automations while keeping legacy projectId as repo-id compatibility data; verified with focused run-context tests, targeted oxlint, git diff --check, and full typecheck.
|
||||
- [x] 2026-06-12: Fed Tasks source-context diagnostics from the shared execution-host registry so the source chip now reports SSH availability and blocked/incompatible remote-server hosts; verified with summary tests and web typecheck.
|
||||
- [x] 2026-06-12: Extended Linear/Jira Tasks source diagnostics to include the account-owning host plus blocked remote-server availability, keeping account source separate from workspace run host; verified with summary tests and web typecheck.
|
||||
- [x] 2026-06-12: Started the user-facing Host copy audit by replacing stale “remote project” and “Remote SSH” UI labels with project-on-host / SSH-host language; verified with web typecheck.
|
||||
|
||||
@@ -89,6 +89,7 @@ import { AutomationRunPageFrame } from './AutomationRunPageFrame'
|
||||
import { AutomationRunHistory } from './AutomationRunHistory'
|
||||
import { getAutomationTemplates, type AutomationTemplate } from './automation-templates'
|
||||
import { getAutomationTargetAvailability } from './automation-target-availability'
|
||||
import { buildAutomationRunContextForRepo } from './automation-run-context'
|
||||
import {
|
||||
getExternalAutomationActionDisabledMessage,
|
||||
getExternalAutomationSourceAvailability,
|
||||
@@ -262,6 +263,7 @@ async function waitForAutomationRerunPendingVisibility(pendingStartedAt: number)
|
||||
|
||||
export default function AutomationsPage(): React.JSX.Element {
|
||||
const repos = useAppStore((s) => s.repos)
|
||||
const projectHostSetups = useAppStore((s) => s.projectHostSetups)
|
||||
const worktreesByRepo = useAppStore((s) => s.worktreesByRepo)
|
||||
const unifiedTabsByWorktree = useAppStore((s) => s.unifiedTabsByWorktree)
|
||||
const activeWorktreeId = useAppStore((s) => s.activeWorktreeId)
|
||||
@@ -1062,6 +1064,20 @@ export default function AutomationsPage(): React.JSX.Element {
|
||||
? Math.max(0, rawMissedRunGraceMinutes)
|
||||
: 720
|
||||
const precheck = buildDraftPrecheck(draft)
|
||||
const runContext = buildAutomationRunContextForRepo({
|
||||
repoId: draft.projectId,
|
||||
repos,
|
||||
projectHostSetups
|
||||
})
|
||||
if (!runContext) {
|
||||
toast.error(
|
||||
translate(
|
||||
'auto.components.automations.AutomationsPage.32534e7c9c',
|
||||
'Choose an available workspace before saving.'
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
let currentAutomation = editingAutomationId
|
||||
? (automations.find((automation) => automation.id === editingAutomationId) ?? null)
|
||||
: null
|
||||
@@ -1080,6 +1096,7 @@ export default function AutomationsPage(): React.JSX.Element {
|
||||
prompt: draft.prompt,
|
||||
precheck,
|
||||
agentId: draft.agentId,
|
||||
runContext,
|
||||
projectId: draft.projectId,
|
||||
workspaceMode: draft.workspaceMode,
|
||||
workspaceId: draft.workspaceId,
|
||||
@@ -1103,6 +1120,7 @@ export default function AutomationsPage(): React.JSX.Element {
|
||||
prompt: draft.prompt,
|
||||
precheck,
|
||||
agentId: draft.agentId,
|
||||
runContext,
|
||||
projectId: draft.projectId,
|
||||
workspaceMode: draft.workspaceMode,
|
||||
workspaceId: draft.workspaceId,
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { ProjectHostSetup, Repo } from '../../../../shared/types'
|
||||
import { buildAutomationRunContextForRepo } from './automation-run-context'
|
||||
|
||||
function repo(id: string, path = `/repos/${id}`): Repo {
|
||||
return {
|
||||
id,
|
||||
path,
|
||||
displayName: id,
|
||||
badgeColor: '#000000',
|
||||
addedAt: 1
|
||||
}
|
||||
}
|
||||
|
||||
function setup(overrides: Partial<ProjectHostSetup> = {}): ProjectHostSetup {
|
||||
return {
|
||||
id: 'setup-builder',
|
||||
projectId: 'github:stablyai/orca',
|
||||
hostId: 'ssh:builder',
|
||||
repoId: 'repo-builder',
|
||||
path: '/remote/orca',
|
||||
displayName: 'orca',
|
||||
setupState: 'ready',
|
||||
setupMethod: 'cloned',
|
||||
createdAt: 1,
|
||||
updatedAt: 1,
|
||||
...overrides
|
||||
}
|
||||
}
|
||||
|
||||
describe('buildAutomationRunContextForRepo', () => {
|
||||
it('persists logical project and host setup identity for the selected run repo', () => {
|
||||
expect(
|
||||
buildAutomationRunContextForRepo({
|
||||
repoId: 'repo-builder',
|
||||
repos: [repo('repo-local', '/local/orca'), repo('repo-builder', '/remote/orca')],
|
||||
projectHostSetups: [
|
||||
setup({
|
||||
id: 'setup-local',
|
||||
hostId: 'local',
|
||||
repoId: 'repo-local',
|
||||
path: '/local/orca'
|
||||
}),
|
||||
setup()
|
||||
]
|
||||
})
|
||||
).toEqual({
|
||||
kind: 'workspace-run',
|
||||
projectId: 'github:stablyai/orca',
|
||||
hostId: 'ssh:builder',
|
||||
projectHostSetupId: 'setup-builder',
|
||||
repoId: 'repo-builder',
|
||||
path: '/remote/orca'
|
||||
})
|
||||
})
|
||||
|
||||
it('does not build a run context for missing or not-ready setups', () => {
|
||||
expect(
|
||||
buildAutomationRunContextForRepo({
|
||||
repoId: 'repo-builder',
|
||||
repos: [repo('repo-builder')],
|
||||
projectHostSetups: [setup({ setupState: 'setting-up' })]
|
||||
})
|
||||
).toBeNull()
|
||||
|
||||
expect(
|
||||
buildAutomationRunContextForRepo({
|
||||
repoId: 'repo-builder',
|
||||
repos: [],
|
||||
projectHostSetups: [setup()]
|
||||
})
|
||||
).toBeNull()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
import {
|
||||
buildWorkspaceRunContext,
|
||||
type WorkspaceRunContext
|
||||
} from '../../../../shared/task-source-context'
|
||||
import type { ProjectHostSetup, Repo } from '../../../../shared/types'
|
||||
|
||||
export function buildAutomationRunContextForRepo(args: {
|
||||
repoId: string
|
||||
repos: readonly Repo[]
|
||||
projectHostSetups: readonly ProjectHostSetup[]
|
||||
}): WorkspaceRunContext | null {
|
||||
const setup = args.projectHostSetups.find(
|
||||
(candidate) => candidate.repoId === args.repoId && candidate.setupState === 'ready'
|
||||
)
|
||||
if (!setup) {
|
||||
return null
|
||||
}
|
||||
const repo = args.repos.find((candidate) => candidate.id === setup.repoId)
|
||||
if (!repo) {
|
||||
return null
|
||||
}
|
||||
return buildWorkspaceRunContext({
|
||||
projectId: setup.projectId,
|
||||
hostId: setup.hostId,
|
||||
projectHostSetupId: setup.id,
|
||||
repoId: setup.repoId,
|
||||
path: setup.path || repo.path
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user