mirror of
https://github.com/stablyai/orca.git
synced 2026-10-21 00:03:46 +00:00
Route agent lineage links diagonally
This commit is contained in:
@@ -12,7 +12,7 @@ import type {
|
||||
} from './agent-map-layout'
|
||||
import { AGENT_MAP_LINEAGE_RELATION, shouldAggregateAgentMapWorktree } from './agent-map-layout'
|
||||
import { selectVisibleAgentMapLabels } from './agent-map-label-declutter'
|
||||
import { agentMapLineageChevronPath } from './agent-map-lineage-chevron-path'
|
||||
import { agentMapDirectLineageChevronPath } from './agent-map-lineage-chevron-path'
|
||||
import { AgentMapWorktreeLabel } from './AgentMapWorktreeLabel'
|
||||
import { AgentMapWorktreeRingNode } from './AgentMapWorktreeRingNode'
|
||||
|
||||
@@ -53,18 +53,7 @@ type VisibleAgentLocation = {
|
||||
}
|
||||
|
||||
function agentLineagePath(parent: AgentMapAgentNode, child: AgentMapAgentNode): string {
|
||||
const dx = child.x - parent.x
|
||||
const dy = child.y - parent.y
|
||||
const distance = Math.hypot(dx, dy)
|
||||
if (distance === 0) {
|
||||
return `M ${parent.x} ${parent.y}`
|
||||
}
|
||||
const unitX = dx / distance
|
||||
const unitY = dy / distance
|
||||
return agentMapLineageChevronPath([
|
||||
{ x: parent.x + unitX * parent.radius, y: parent.y + unitY * parent.radius },
|
||||
{ x: child.x - unitX * child.radius, y: child.y - unitY * child.radius }
|
||||
])
|
||||
return agentMapDirectLineageChevronPath(parent, child)
|
||||
}
|
||||
|
||||
/** Memoization keeps pointer panning to one SVG viewBox write, not a map rerender. */
|
||||
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
AgentMapWorktreeRing
|
||||
} from './agent-map-layout'
|
||||
import { AGENT_MAP_LINEAGE_RELATION, shouldAggregateAgentMapWorktree } from './agent-map-layout'
|
||||
import { agentMapLineageChevronPath } from './agent-map-lineage-chevron-path'
|
||||
import { agentMapDirectLineageChevronPath } from './agent-map-lineage-chevron-path'
|
||||
import { agentMapWorktreeActiveStatus } from './agent-map-worktree-active-status'
|
||||
|
||||
type AgentMapWorktreeRingNodeProps = {
|
||||
@@ -51,20 +51,8 @@ function formatDuration(minutes: number): string {
|
||||
})
|
||||
}
|
||||
|
||||
// Why direction-aware: packing can place a child level with or above its parent, and
|
||||
// a fixed downward elbow would then exit the wrong side and draw back through both
|
||||
// nodes. Leaving the rank tie at +1 keeps the common downward case byte-identical.
|
||||
function lineagePath(parent: AgentMapAgentNode, child: AgentMapAgentNode): string {
|
||||
const direction = child.y < parent.y ? -1 : 1
|
||||
const startY = parent.y + parent.radius * direction
|
||||
const endY = child.y - child.radius * direction
|
||||
const branchY = (startY + endY) / 2
|
||||
return agentMapLineageChevronPath([
|
||||
{ x: parent.x, y: startY },
|
||||
{ x: parent.x, y: branchY },
|
||||
{ x: child.x, y: branchY },
|
||||
{ x: child.x, y: endY }
|
||||
])
|
||||
return agentMapDirectLineageChevronPath(parent, child)
|
||||
}
|
||||
|
||||
function agentName(card: DashboardCard): string {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { agentMapDirectLineageChevronPath } from './agent-map-lineage-chevron-path'
|
||||
|
||||
describe('agentMapDirectLineageChevronPath', () => {
|
||||
it('runs every chevron directly from the parent toward the child', () => {
|
||||
const path = agentMapDirectLineageChevronPath(
|
||||
{ x: 0, y: 0, radius: 4 },
|
||||
{ x: 40, y: 40, radius: 4 }
|
||||
)
|
||||
const tips = [...path.matchAll(/M [-\d.]+ [-\d.]+ L ([-\d.]+) ([-\d.]+) L/g)].map((match) => ({
|
||||
x: Number(match[1]),
|
||||
y: Number(match[2])
|
||||
}))
|
||||
|
||||
expect(tips.length).toBeGreaterThan(1)
|
||||
expect(tips.every((tip) => tip.x === tip.y)).toBe(true)
|
||||
expect(tips.at(-1)?.x).toBeGreaterThan(tips[0].x)
|
||||
})
|
||||
})
|
||||
@@ -3,6 +3,10 @@ export type AgentMapLineagePoint = {
|
||||
y: number
|
||||
}
|
||||
|
||||
type AgentMapLineageNode = AgentMapLineagePoint & {
|
||||
radius: number
|
||||
}
|
||||
|
||||
type LineageSegment = {
|
||||
start: AgentMapLineagePoint
|
||||
unitX: number
|
||||
@@ -64,3 +68,21 @@ export function agentMapLineageChevronPath(points: AgentMapLineagePoint[]): stri
|
||||
}
|
||||
return commands.join(' ')
|
||||
}
|
||||
|
||||
export function agentMapDirectLineageChevronPath(
|
||||
parent: AgentMapLineageNode,
|
||||
child: AgentMapLineageNode
|
||||
): string {
|
||||
const dx = child.x - parent.x
|
||||
const dy = child.y - parent.y
|
||||
const distance = Math.hypot(dx, dy)
|
||||
if (distance === 0) {
|
||||
return agentMapLineageChevronPath([parent])
|
||||
}
|
||||
const unitX = dx / distance
|
||||
const unitY = dy / distance
|
||||
return agentMapLineageChevronPath([
|
||||
{ x: parent.x + unitX * parent.radius, y: parent.y + unitY * parent.radius },
|
||||
{ x: child.x - unitX * child.radius, y: child.y - unitY * child.radius }
|
||||
])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user