Skip to content
中文

Family ​

KIT · constant · Runtime value

Import ​

ts
import { Family } from '@jangts/agent-core/kits/family';
js
import { Family } from '@jangts/agent-core/kits/family';

Other public entry points:@jangts/agent-core/types, @jangts/agent-core/kits, @jangts/agent-core/kits/family.

Definition ​

Member index ​

MemberPurpose
defineAgentFamilySee the overload below for full inputs and outputs.

Member details ​

defineAgentFamily ​

ts
Family.defineAgentFamily<State, App>(definition: FamilyDefinition<State, App>): AgentFamily<State, App>

Compile a versioned family backed by an App-owned compare-and-swap store.

Every mutation reads the record, verifies the caller's expected revision, then commits with a compare-and-swap, so concurrent writers fail with a revision conflict rather than overwriting each other. Reads are also treated as policy checks because the App binds its read rules into the store it supplies.

Type parameterConstraintDefault type
State——
App——
ParameterTypePassingDescription
definitionFamilyDefinition<State, App>Required—
Fields of definition
FieldTypeRequiredDescription
storeFamilyStore<State>RequiredRead-only. See the type definition and usage context.
maxVersionsnumber | undefinedOptionalRead-only. Maximum retained versions; older versions are dropped once the bound is exceeded.
retentionMsnumber | undefinedOptionalRead-only. Retention window in milliseconds, measured from a write.
now(() => number) | undefinedOptionalRead-only. Clock override for timestamps and expiry; defaults to Date.now.
isState(value: unknown) => value is StateRequiredValidates a state loaded from the store before it is used.
authorize(operation: FamilyOperation, record: FamilyRecord<State> | undefined, context: OperationContext<App>) => MaybePromise<void>RequiredGuards one mutation; called before any write, including with an absent record.
validate(candidate: FamilyVersion<State>, context: OperationContext<App>) => MaybePromise<void>RequiredValidates a candidate version before it is appended.
merge((input: { base: State; target: State; source: State; }, context: OperationContext<App>) => MaybePromise<{ value?: State | undefined; conflicts: readonly string[]; }>) | undefinedOptionalResolves a three-way merge. Returns the merged state and any conflicts. A non-empty conflict list aborts the merge without writing a version, so value is ignored in that case.

Returns: AgentFamily<State, App>.

Return value structure
FieldTypeRequiredDescription
read(id: string, context: OperationContext<App>) => Promise<FamilyRecord<State>>RequiredReads the record; throws when the family does not exist or has expired.
create(request: { id: string; branch: AgentBranch; state: State; }, context: OperationContext<App>) => Promise<FamilyRecord<State>>RequiredCreates the first version and makes it active.
fork(request: { id: string; revision: number; parentId: string; branch: AgentBranch; state: State; }, context: OperationContext<App>) => Promise<FamilyRecord<State>>RequiredAppends a version forked from parentId; the active pointer does not change.
merge(request: { id: string; revision: number; baseId: string; targetId: string; sourceId: string; }, context: OperationContext<App>) => Promise<{ saved: boolean; record: FamilyRecord<State>; conflicts: readonly string[]; }>RequiredMerges source into target; saved is false when the merge reported conflicts.
promote(request: { id: string; revision: number; candidateId: string; expectedActiveId: string; }, context: OperationContext<App>) => Promise<FamilyRecord<State>>RequiredMakes candidateId active; fails when the active version changed since expectedActiveId.

Examples ​

Configure state checks, source verification, and three-way merge ​

Configuration · Node.js

ts
import { defineAgentFamily } from '@jangts/agent-core/kits/family';
import type { FamilyStore } from '@jangts/agent-core/kits/family';
import type { OperationContext } from '@jangts/agent-core';

type State = { goal: string; sourceRevision: string };
export function family<App>(store: FamilyStore<State>,
  authorize: (context: OperationContext<App>) => Promise<void>,
  verify: (state: State) => Promise<void>) {
  return defineAgentFamily<State, App>({
    store, maxVersions: 16, retentionMs: 7 * 86400000,
    isState: (value): value is State => !!value && typeof (value as State).goal === 'string'
      && typeof (value as State).sourceRevision === 'string',
    authorize: (_operation, _record, context) => authorize(context),
    validate: candidate => verify(candidate.state),
    async merge({ base, target, source }) {
      if (target.goal !== base.goal && source.goal !== base.goal && target.goal !== source.goal)
        return { conflicts: ['goal'] };
      return { value: target.goal === base.goal ? source : target, conflicts: [] };
    },
  });
}
js
import { defineAgentFamily } from '@jangts/agent-core/kits/family';
export function family(store, authorize, verify) {
    return defineAgentFamily({
        store, maxVersions: 16, retentionMs: 7 * 86400000,
        isState: (value) => !!value && typeof value.goal === 'string'
            && typeof value.sourceRevision === 'string',
        authorize: (_operation, _record, context) => authorize(context),
        validate: candidate => verify(candidate.state),
        async merge({ base, target, source }) {
            if (target.goal !== base.goal && source.goal !== base.goal && target.goal !== source.goal)
                return { conflicts: ['goal'] };
            return { value: target.goal === base.goal ? source : target, conflicts: [] };
        },
    });
}

Explicitly promote an approved candidate version ​

Extension · Node.js

The App calls this after real approval; promote still re-runs source, authorization, revision, and CAS checks.

ts
import type { AgentFamily } from '@jangts/agent-core/kits/family';
import type { OperationContext } from '@jangts/agent-core';

export async function activate<State, App>(family: AgentFamily<State, App>, id: string,
  candidateId: string, context: OperationContext<App>) {
  const record = await family.read(id, context);
  return family.promote({ id, revision: record.revision, candidateId,
    expectedActiveId: record.activeId }, context);
}
js
export async function activate(family, id, candidateId, context) {
    const record = await family.read(id, context);
    return family.promote({ id, revision: record.revision, candidateId,
        expectedActiveId: record.activeId }, context);
}

API reference, usage examples and developer guides.