mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 16:03:49 +00:00
Add the structured agent-session host
One place where the lease, the journal, and the provider adapter meet: every mutating call recomputes the fingerprint, admits through the durable operation ledger, checks the lease, then acts, so no method can grow its own admission rules. Journal recovery rehydrates an unreadable journal from provider history into a fresh epoch and tells subscribers which reset they are seeing. Attach adjudicates the leases it loaded from disk before granting any writer. Without that step every lease stays unreconciled for the life of the process and a restarted host refuses every persisted session forever.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
// Ledger admission for mutations that are not reservations — send, cancel, an
|
||||
// approval answer. Split from the store so the store keeps only the transaction.
|
||||
|
||||
import {
|
||||
agentSessionOperationKey,
|
||||
evaluateAgentSessionOperation,
|
||||
pruneAgentSessionOperationRows,
|
||||
type AgentSessionOperationDecision,
|
||||
type AgentSessionOperationRow
|
||||
} from '../../shared/agent-session-operation-ledger'
|
||||
|
||||
export type AgentSessionOperationAdmission = {
|
||||
callerKey: string
|
||||
operationId: string
|
||||
fingerprint: string
|
||||
now: number
|
||||
}
|
||||
|
||||
type OperationRows = Map<string, AgentSessionOperationRow>
|
||||
|
||||
/** Prune, evaluate, and (on admit) place the row. The caller runs this inside one
|
||||
* transaction, so two concurrent copies of an operation id cannot both admit. */
|
||||
export function admitAgentSessionOperationRow(
|
||||
rows: OperationRows,
|
||||
args: AgentSessionOperationAdmission
|
||||
): { rows: OperationRows; decision: AgentSessionOperationDecision } {
|
||||
const pruned = pruneAgentSessionOperationRows(rows, args.now)
|
||||
const decision = evaluateAgentSessionOperation({ rows: pruned, ...args })
|
||||
if (decision.decision === 'admit') {
|
||||
pruned.set(agentSessionOperationKey(args.callerKey, args.operationId), decision.row)
|
||||
}
|
||||
return { rows: pruned, decision }
|
||||
}
|
||||
@@ -12,9 +12,14 @@
|
||||
import {
|
||||
pruneAgentSessionOperationRows,
|
||||
agentSessionOperationKey,
|
||||
type AgentSessionOperationDecision,
|
||||
type AgentSessionOperationOutcome,
|
||||
type AgentSessionOperationRow
|
||||
} from '../../shared/agent-session-operation-ledger'
|
||||
import {
|
||||
admitAgentSessionOperationRow,
|
||||
type AgentSessionOperationAdmission
|
||||
} from './agent-session-operation-admission'
|
||||
import type { AgentSessionOwnerProbe } from '../../shared/agent-session-lease-adjudication'
|
||||
import { classifyObservedAgentSessionSpawnToken } from '../../shared/agent-session-lease-adjudication'
|
||||
import type { AgentSessionProviderHandleLink } from '../../shared/agent-session-provider-handle'
|
||||
@@ -276,6 +281,17 @@ export class AgentSessionRecordStore {
|
||||
})
|
||||
}
|
||||
|
||||
/** Admits one non-reservation mutation through the durable ledger. */
|
||||
async admitOperation(
|
||||
args: AgentSessionOperationAdmission
|
||||
): Promise<AgentSessionOperationDecision> {
|
||||
return this.transact(() => {
|
||||
const admitted = admitAgentSessionOperationRow(this.state.operations, args)
|
||||
this.state.operations = admitted.rows
|
||||
return admitted.decision
|
||||
})
|
||||
}
|
||||
|
||||
async recordOperationOutcome(args: {
|
||||
callerKey: string
|
||||
operationId: string
|
||||
|
||||
Reference in New Issue
Block a user