Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/relay/agent-status-store-relay-context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { makeStructuredAgentStatusSubject } from '../shared/agent-status-subject
const SHARED_CORE_FILES = [
'agent-status-child-work.ts',
'agent-status-child-work-codec.ts',
'agent-status-child-work-activity-codec.ts',
'agent-status-child-work-legality.ts',
'agent-status-child-work-value-guards.ts',
'agent-status-child-work-view.ts',
'agent-status-child-work-admission.ts',
'agent-status-child-work-admission-core.ts',
'agent-status-child-work-admission-operations.ts',
Expand Down
101 changes: 101 additions & 0 deletions src/shared/agent-status-child-work-activity-codec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
AGENT_CHILD_WORK_LAST_MESSAGE_MAX_LENGTH,
AGENT_CHILD_WORK_OPERATION_BASES,
AGENT_CHILD_WORK_RESIDENCIES,
type AgentChildWorkInput,
type AgentChildWorkOperation,
type AgentChildWorkOperationBasis,
type AgentChildWorkResidency
} from './agent-status-child-work'
import {
AGENT_STATUS_TOOL_INPUT_MAX_LENGTH,
AGENT_STATUS_TOOL_NAME_MAX_LENGTH
} from './agent-status-types'
import {
hasOnlyKeys,
isBoundedString,
isChildWorkText,
isRecord,
isTimestamp
} from './agent-status-child-work-value-guards'

const RESIDENCY_SET: ReadonlySet<string> = new Set(AGENT_CHILD_WORK_RESIDENCIES)
const OPERATION_BASIS_SET: ReadonlySet<string> = new Set(AGENT_CHILD_WORK_OPERATION_BASES)

export type AgentChildWorkActivityFields = Pick<
AgentChildWorkInput,
'parentChildWorkId' | 'residency' | 'operation' | 'lastMessage'
>

type AgentChildWorkActivityClock = Pick<
AgentChildWorkInput,
'childWorkId' | 'firstObservedAt' | 'observedAt'
>

export function isAgentChildWorkResidency(value: unknown): value is AgentChildWorkResidency {
return typeof value === 'string' && RESIDENCY_SET.has(value)
}

export function isAgentChildWorkOperationBasis(
value: unknown
): value is AgentChildWorkOperationBasis {
return typeof value === 'string' && OPERATION_BASIS_SET.has(value)
}

/** An owner is another child's id; a child never owns itself. */
export function isAgentChildWorkOwner(value: unknown, childWorkId: string): value is string {
return isBoundedString(value) && value !== childWorkId
}

function parseOperation(
value: unknown,
clock: AgentChildWorkActivityClock
): AgentChildWorkOperation | null {
if (
!isRecord(value) ||
!hasOnlyKeys(value, ['toolName', 'basis', 'observedAt'], ['input']) ||
!isChildWorkText(value.toolName, AGENT_STATUS_TOOL_NAME_MAX_LENGTH) ||
(value.input !== undefined &&
!isChildWorkText(value.input, AGENT_STATUS_TOOL_INPUT_MAX_LENGTH)) ||
!isAgentChildWorkOperationBasis(value.basis) ||
!isTimestamp(value.observedAt) ||
// The record's own clock is the newest evidence for this child, so it bounds the operation's.
value.observedAt < clock.firstObservedAt ||
value.observedAt > clock.observedAt
) {
return null
}
return {
toolName: value.toolName,
...(typeof value.input === 'string' ? { input: value.input } : {}),
basis: value.basis,
observedAt: value.observedAt
}
}

/** Null when any present field is outside what admission can produce. */
export function parseAgentChildWorkActivityFields(
value: Record<string, unknown>,
clock: AgentChildWorkActivityClock
): AgentChildWorkActivityFields | null {
const operation =
value.operation === undefined ? undefined : parseOperation(value.operation, clock)
if (
operation === null ||
(value.parentChildWorkId !== undefined &&
!isAgentChildWorkOwner(value.parentChildWorkId, clock.childWorkId)) ||
(value.residency !== undefined && !isAgentChildWorkResidency(value.residency)) ||
(value.lastMessage !== undefined &&
!isChildWorkText(value.lastMessage, AGENT_CHILD_WORK_LAST_MESSAGE_MAX_LENGTH))
) {
return null
}
return {
...(typeof value.parentChildWorkId === 'string'
? { parentChildWorkId: value.parentChildWorkId }
: {}),
...(isAgentChildWorkResidency(value.residency) ? { residency: value.residency } : {}),
...(operation ? { operation } : {}),
...(typeof value.lastMessage === 'string' ? { lastMessage: value.lastMessage } : {})
}
}
Loading
Loading