@weiliang0121/capix-records 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/attempt/record.d.ts +1 -1
- package/dist/book.d.ts +1 -1
- package/dist/callable/helper.d.ts +1 -1
- package/dist/callable/record.d.ts +1 -1
- package/dist/construction.d.ts +1 -1
- package/dist/content.d.ts +10 -0
- package/dist/content.js +2 -0
- package/dist/data/archive.d.ts +9 -0
- package/dist/data/archive.js +2 -0
- package/dist/data/changes.d.ts +43 -0
- package/dist/data/changes.js +1 -0
- package/dist/data/index.d.ts +8 -0
- package/dist/data/index.js +2 -0
- package/dist/data/invocation.d.ts +10 -0
- package/dist/data/invocation.js +2 -0
- package/dist/data/memory.d.ts +26 -0
- package/dist/data/memory.js +2 -0
- package/dist/data/resource.d.ts +10 -0
- package/dist/data/resource.js +1 -0
- package/dist/data/transcript.d.ts +19 -0
- package/dist/data/transcript.js +1 -0
- package/dist/data/types.d.ts +189 -0
- package/dist/data/types.js +1 -0
- package/dist/data/validate.d.ts +4 -0
- package/dist/data/validate.js +2 -0
- package/dist/execution/helper.d.ts +1 -1
- package/dist/execution/record.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/invocation/boundary/helper.d.ts +1 -1
- package/dist/invocation/boundary/record.d.ts +1 -1
- package/dist/invocation/record.d.ts +2 -2
- package/dist/invocation/record.js +1 -1
- package/dist/memory/helper.d.ts +1 -1
- package/dist/memory/observe.d.ts +6 -7
- package/dist/memory/observe.js +1 -1
- package/dist/memory/record.d.ts +1 -1
- package/dist/memory/record.js +1 -1
- package/dist/operation/record.d.ts +1 -1
- package/dist/record.d.ts +1 -1
- package/dist/recorder.d.ts +1 -1
- package/dist/resource/record.d.ts +1 -1
- package/dist/resource.d.ts +1 -1
- package/dist/restoration/check.d.ts +1 -1
- package/dist/restoration/check.js +1 -1
- package/dist/restoration/entry.d.ts +1 -1
- package/dist/restoration/tree.js +1 -1
- package/dist/root/record.d.ts +1 -1
- package/dist/runtime/record.d.ts +1 -1
- package/dist/transcript/helper.d.ts +1 -1
- package/dist/transcript/record.d.ts +1 -1
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @weiliang0121/capix-records
|
|
2
2
|
|
|
3
|
-
Optional recording entities and resource contracts for CAPiX.
|
|
3
|
+
Optional recording entities and resource packages/contracts for CAPiX.
|
|
4
4
|
|
|
5
5
|
ES modules and TypeScript declarations. Requires Node.js 22.23.2 or newer.
|
|
6
6
|
|
|
@@ -12,9 +12,18 @@ npm install @weiliang0121/capix-records
|
|
|
12
12
|
|
|
13
13
|
- `@weiliang0121/capix-records`
|
|
14
14
|
- `@weiliang0121/capix-records/construction`
|
|
15
|
+
- `@weiliang0121/capix-records/data`
|
|
16
|
+
|
|
17
|
+
The root entry exports live record entities and recording helpers. The `data` entry owns their plain record shapes, archive identities, change records, output resolution, and full subtree/body validation. It has no Node.js or live-entity imports and is suitable for browser and wire consumers. Identically named data interfaces and entity classes are deliberately separated by these entries.
|
|
18
|
+
|
|
19
|
+
`CallableRecordHelper.snapshot` reads the caller-selected invocation subtree and its actual ancestor path; selecting a business task, Observer overview, and environment aggregation remain application responsibilities. `ExecutionRecordHelper.snapshot` and the corresponding legacy-named validators retain their existing record representation and validation; these APIs do not upgrade old data or resume execution. Memory recording and `observeMemory` expose only `MemoryRecordContent` (`content`) and available records, not arbitrary metadata or recovery material.
|
|
20
|
+
|
|
21
|
+
This ownership change removes the dependency on `capix-protocol`. Consumers of the former protocol recording/archive exports must import `capix-records/data`; shared invocation vocabulary belongs to `capix-contracts`.
|
|
22
|
+
|
|
23
|
+
`ResourceRecord.sequence` retains the owning call's shared resource order, which also numbers forwarded domain facts. Because those facts are projected separately or intentionally left uninterpreted, resource record numbers may have gaps. Subtree validation and record-book restoration require positive safe integers in strictly increasing order per owner; identity, binding phases, and started/returned/threw pairing remain checked. Missing numbers do not establish missing effects or authorize replay.
|
|
15
24
|
|
|
16
25
|
This package is part of CAPiX. The npm distribution contains compiled JavaScript, type declarations, and this package's MIT license. Reference services and client applications are not included in this package or the initial npm release.
|
|
17
26
|
|
|
18
27
|
## License
|
|
19
28
|
|
|
20
|
-
MIT. Copyright (c) 2026 wei.liang. See [LICENSE](
|
|
29
|
+
MIT. Copyright (c) 2026 wei.liang. See [LICENSE](LICENSE).
|
package/dist/attempt/record.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AttemptRecord as AttemptData, AttemptValue } from '
|
|
1
|
+
import type { AttemptRecord as AttemptData, AttemptValue } from '../data/index.js';
|
|
2
2
|
import { InvocationRecord } from '../invocation/record.js';
|
|
3
3
|
export type AttemptRecordOptions = Omit<AttemptData, 'id' | 'value' | 'status' | 'parentId' | 'childIds'>;
|
|
4
4
|
export declare class AttemptRecord extends InvocationRecord<AttemptValue> implements AttemptData {
|
package/dist/book.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseRecord } from './record.js';
|
|
2
2
|
import { removeRegistration } from './tree/access.js';
|
|
3
|
-
import type { RecordEntry } from '
|
|
3
|
+
import type { RecordEntry } from './data/index.js';
|
|
4
4
|
export interface RecordBookState {
|
|
5
5
|
readonly entries: readonly RecordEntry[];
|
|
6
6
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExecutionRecordSnapshot } from '
|
|
1
|
+
import type { ExecutionRecordSnapshot } from '../data/index.js';
|
|
2
2
|
import type { Recorder } from '../recorder.js';
|
|
3
3
|
export declare class CallableRecordHelper {
|
|
4
4
|
static snapshot(recorder: Recorder, id: string): ExecutionRecordSnapshot;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CallableRecord as CallableRecordData, CallableValue } from '
|
|
1
|
+
import type { CallableRecord as CallableRecordData, CallableValue } from '../data/index.js';
|
|
2
2
|
import { InvocationRecord } from '../invocation/record.js';
|
|
3
3
|
export type CallableRecordOptions = Omit<CallableRecordData, 'id' | 'value' | 'status' | 'childIds'>;
|
|
4
4
|
export declare class CallableRecord extends InvocationRecord<CallableValue> implements CallableRecordData {
|
package/dist/construction.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ResourceOffer } from '@weiliang0121/capix-resources';
|
|
2
|
-
import type { InvocationBoundaryValue, RecordMutation } from '
|
|
2
|
+
import type { InvocationBoundaryValue, RecordMutation } from './data/index.js';
|
|
3
3
|
import type { BaseRecord } from './record.js';
|
|
4
4
|
import type { Recorder } from './recorder.js';
|
|
5
5
|
import { InvocationBoundaryRecordHelper } from './invocation/boundary/helper.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type TranscriptEvent } from '@weiliang0121/capix-transcript';
|
|
2
|
+
import { type MemoryEvent } from '@weiliang0121/capix-memory';
|
|
3
|
+
import type { ResourceFact } from '@weiliang0121/capix-resources';
|
|
4
|
+
import type { RecordWriter } from './construction.js';
|
|
5
|
+
import type { RecordChangeSource } from './source.js';
|
|
6
|
+
import { TranscriptRecord } from './transcript/record.js';
|
|
7
|
+
import { MemoryRecord } from './memory/record.js';
|
|
8
|
+
export declare function transcriptRecord(event: TranscriptEvent, source?: RecordChangeSource): TranscriptRecord;
|
|
9
|
+
export declare function memoryRecord(event: MemoryEvent<unknown>, source?: RecordChangeSource): MemoryRecord;
|
|
10
|
+
export declare function recordContentFact(fact: ResourceFact, source: RecordChangeSource, writer: RecordWriter): void;
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{TranscriptFacts}from"@weiliang0121/capix-transcript";import{MemoryFacts}from"@weiliang0121/capix-memory";import{TranscriptRecord}from"./transcript/record.js";import{MemoryRecord}from"./memory/record.js";function transcriptRecord(event,source){const change=event.change;return new TranscriptRecord({transcriptId:event.transcriptId,revision:event.revision,occurredAt:event.occurredAt,...source?{source}:{}},change.kind==="messages-appended"?{action:"append",start:change.start,end:change.start+change.messages.length}:{action:"segment",previousStart:change.previousStart,start:change.start,end:change.end})}__name(transcriptRecord,"transcriptRecord");function memoryRecord(event,source){return new MemoryRecord({memoriesId:event.memoriesId,memoryId:event.change.memoryId,sequence:event.sequence,...source?{source}:{}},{action:event.change.action,...event.change.reason!==void 0?{reason:event.change.reason}:{},result:{content:event.change.value.content}})}__name(memoryRecord,"memoryRecord");function recordContentFact(fact,source,writer){if(fact.contextId!==source.contextId)throw new Error("Content fact forwarding context does not match record source");TranscriptFacts.match(fact.fact,event=>{if(event.origin?.contextId!==source.contextId)throw new Error("Transcript fact origin does not match record source");writer.add(transcriptRecord(event,source))})||MemoryFacts.match(fact.fact,event=>{if(event.origin?.contextId!==source.contextId)throw new Error("Memory fact origin does not match record source");writer.add(memoryRecord(event,source))})}__name(recordContentFact,"recordContentFact");export{memoryRecord,recordContentFact,transcriptRecord};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface RecordingArchive {
|
|
2
|
+
readonly sourceId: string;
|
|
3
|
+
readonly rootIds: readonly string[];
|
|
4
|
+
readonly revision: number;
|
|
5
|
+
readonly state: 'open' | 'sealed' | 'incomplete';
|
|
6
|
+
}
|
|
7
|
+
export type RecordingArchiveOrigin = Omit<RecordingArchive, 'rootIds'>;
|
|
8
|
+
export declare function validateRecordingArchiveOrigin(value: unknown): asserts value is RecordingArchiveOrigin;
|
|
9
|
+
export declare function validateRecordingArchives(value: unknown): asserts value is readonly RecordingArchive[];
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});function validateRecordingArchiveOrigin(value){if(!value||typeof value!="object")throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u683C\u5F0F\u65E0\u6548\u3002");const source=value;if(typeof source.sourceId!="string"||!source.sourceId||!Number.isSafeInteger(source.revision)||source.revision<0||!["open","sealed","incomplete"].includes(source.state))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u683C\u5F0F\u65E0\u6548\u3002")}__name(validateRecordingArchiveOrigin,"validateRecordingArchiveOrigin");function validateRecordingArchives(value){if(!Array.isArray(value))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u683C\u5F0F\u65E0\u6548\u3002");const sources=new Set,roots=new Set;for(const archive of value){validateRecordingArchiveOrigin(archive);const source=archive;if(sources.has(source.sourceId)||!Array.isArray(source.rootIds)||source.rootIds.some(id=>typeof id!="string"||!id||roots.has(id)))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u5F52\u5C5E\u65E0\u6548\u3002");sources.add(source.sourceId);for(const id of source.rootIds){if(roots.has(id))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u5F52\u5C5E\u65E0\u6548\u3002");roots.add(id)}}}__name(validateRecordingArchives,"validateRecordingArchives");export{validateRecordingArchiveOrigin,validateRecordingArchives};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { BaseRecord, ProcessRecord, RelationChangeRecord } from './types.js';
|
|
2
|
+
import type { RuntimeErrorValue, InvocationFailureFact } from '@weiliang0121/capix-contracts';
|
|
3
|
+
export type RecordKind = 'invocation' | 'runtime' | 'runtime-call' | 'execution' | 'operation' | 'attempt' | 'invocation-boundary' | 'transcript' | 'memory' | 'resource' | 'custom';
|
|
4
|
+
export interface RecordEntry {
|
|
5
|
+
readonly kind: RecordKind;
|
|
6
|
+
readonly data: BaseRecord;
|
|
7
|
+
}
|
|
8
|
+
export type RecordMutation = Readonly<{
|
|
9
|
+
kind: 'added';
|
|
10
|
+
entry: RecordEntry;
|
|
11
|
+
parent?: Readonly<{
|
|
12
|
+
id: string;
|
|
13
|
+
childId: string;
|
|
14
|
+
}>;
|
|
15
|
+
}> | Readonly<{
|
|
16
|
+
kind: 'process-appended';
|
|
17
|
+
id: string;
|
|
18
|
+
process: ProcessRecord;
|
|
19
|
+
}> | Readonly<{
|
|
20
|
+
kind: 'relation-appended';
|
|
21
|
+
id: string;
|
|
22
|
+
relation: RelationChangeRecord;
|
|
23
|
+
}> | Readonly<{
|
|
24
|
+
kind: 'finished';
|
|
25
|
+
id: string;
|
|
26
|
+
status: 'succeeded' | 'failed';
|
|
27
|
+
result: Readonly<{
|
|
28
|
+
output?: unknown;
|
|
29
|
+
resultOf?: number;
|
|
30
|
+
error?: RuntimeErrorValue;
|
|
31
|
+
failure?: InvocationFailureFact;
|
|
32
|
+
}>;
|
|
33
|
+
}> | Readonly<{
|
|
34
|
+
kind: 'replaced';
|
|
35
|
+
entry: RecordEntry;
|
|
36
|
+
}>;
|
|
37
|
+
export type RecordChangeEvent = Readonly<{
|
|
38
|
+
type: 'record';
|
|
39
|
+
recorderId: string;
|
|
40
|
+
revision: number;
|
|
41
|
+
occurredAt: string;
|
|
42
|
+
change: RecordMutation;
|
|
43
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
+
export*from"./types.js";export*from"./invocation.js";export*from"./memory.js";export*from"./transcript.js";export*from"./resource.js";export*from"./changes.js";export*from"./archive.js";export*from"./validate.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { InvocationValue, ProcessRecord } from './types.js';
|
|
2
|
+
type OutputProcess = Extract<ProcessRecord, {
|
|
3
|
+
type: 'return';
|
|
4
|
+
output: unknown;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function outputProcess(value: Pick<InvocationValue, 'processes'>, sequence: number, before?: number): OutputProcess;
|
|
7
|
+
export declare function hasOutput(value: InvocationValue): boolean;
|
|
8
|
+
export declare function finalOutputProcess(value: Pick<InvocationValue, 'processes'>, sequence: number): OutputProcess;
|
|
9
|
+
export declare function readOutput<Input, Output>(value: InvocationValue<Input, Output>): Output | undefined;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});function outputProcess(value,sequence,before=value.processes.length+1){const process=value.processes[sequence-1];if(!Number.isSafeInteger(sequence)||sequence<1||sequence>=before||!process||process.sequence!==sequence||process.type!=="return"||!Object.hasOwn(process,"output")||Object.hasOwn(process,"resultOf"))throw new Error("Invalid local result reference");return process}__name(outputProcess,"outputProcess");function hasOutput(value){return Object.hasOwn(value,"output")||Object.hasOwn(value,"resultOf")}__name(hasOutput,"hasOutput");function finalOutputProcess(value,sequence){const last=value.processes.at(-1);if(!last||last.type!=="return"||sequence!==("resultOf"in last?last.resultOf:last.sequence))throw new Error("Final result must reference the last returned output");return outputProcess(value,sequence)}__name(finalOutputProcess,"finalOutputProcess");function readOutput(value){if(Object.hasOwn(value,"resultOf")){if(Object.hasOwn(value,"output"))throw new Error("Output and local result reference are mutually exclusive");return finalOutputProcess(value,value.resultOf).output}return value.output}__name(readOutput,"readOutput");export{finalOutputProcess,hasOutput,outputProcess,readOutput};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BaseRecord } from './types.js';
|
|
2
|
+
export interface MemoryRecordContent {
|
|
3
|
+
readonly content: string;
|
|
4
|
+
}
|
|
5
|
+
export interface MemoryRecordObservation {
|
|
6
|
+
readonly items: readonly {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly value: MemoryRecordContent;
|
|
9
|
+
readonly records: readonly MemoryRecord[];
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export interface MemoryRecordValue {
|
|
13
|
+
readonly action: 'create' | 'update';
|
|
14
|
+
readonly reason?: string;
|
|
15
|
+
readonly result: MemoryRecordContent;
|
|
16
|
+
}
|
|
17
|
+
export interface MemoryRecord extends BaseRecord<MemoryRecordValue> {
|
|
18
|
+
readonly memoryId: string;
|
|
19
|
+
readonly memoriesId: string;
|
|
20
|
+
readonly sequence: number;
|
|
21
|
+
readonly contextId?: string;
|
|
22
|
+
readonly callId?: string;
|
|
23
|
+
readonly executionId?: string;
|
|
24
|
+
readonly operationId?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function validateMemoryRecordValue(value: unknown): asserts value is MemoryRecordValue;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});function validateMemoryRecordValue(value){if(!value||typeof value!="object"||Array.isArray(value))throw new Error("Invalid memory record value");const record=value;if(!Object.hasOwn(record,"action")||!Object.hasOwn(record,"result")||record.action!=="create"&&record.action!=="update"||Object.keys(record).some(key=>!["action","reason","result"].includes(key))||Object.hasOwn(record,"reason")&&typeof record.reason!="string")throw new Error("Invalid memory record value");const result=record.result;if(!result||typeof result!="object"||Array.isArray(result)||Object.keys(result).length!==1||!Object.hasOwn(result,"content")||typeof result.content!="string")throw new Error("Invalid memory display value")}__name(validateMemoryRecordValue,"validateMemoryRecordValue");export{validateMemoryRecordValue};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BaseRecord } from './types.js';
|
|
2
|
+
export interface ResourceRecord<Detail = unknown> extends BaseRecord<Detail> {
|
|
3
|
+
readonly parentId: string;
|
|
4
|
+
readonly access: string;
|
|
5
|
+
readonly supplyId: string;
|
|
6
|
+
readonly sequence: number;
|
|
7
|
+
readonly occurredAt: string;
|
|
8
|
+
readonly phase: 'bound' | 'available' | 'unavailable' | 'started' | 'returned' | 'threw';
|
|
9
|
+
readonly interactionId?: string;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BaseRecord } from './types.js';
|
|
2
|
+
export type TranscriptChange = {
|
|
3
|
+
readonly action: 'append';
|
|
4
|
+
readonly start: number;
|
|
5
|
+
readonly end: number;
|
|
6
|
+
} | {
|
|
7
|
+
readonly action: 'segment';
|
|
8
|
+
readonly previousStart: number;
|
|
9
|
+
readonly start: number;
|
|
10
|
+
readonly end: number;
|
|
11
|
+
};
|
|
12
|
+
export interface TranscriptRecord extends BaseRecord<TranscriptChange> {
|
|
13
|
+
readonly transcriptId: string;
|
|
14
|
+
readonly revision: number;
|
|
15
|
+
readonly occurredAt: string;
|
|
16
|
+
readonly contextId?: string;
|
|
17
|
+
readonly callId?: string;
|
|
18
|
+
readonly executionId?: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { RecordingArchiveOrigin } from './archive.js';
|
|
2
|
+
import type { InvocationFailureFact, RuntimeErrorValue } from '@weiliang0121/capix-contracts';
|
|
3
|
+
import type { CallableKind } from '@weiliang0121/capix-contracts';
|
|
4
|
+
import type { TranscriptRecord } from './transcript.js';
|
|
5
|
+
import type { MemoryRecord } from './memory.js';
|
|
6
|
+
import type { ResourceRecord } from './resource.js';
|
|
7
|
+
import type { InvocationRelationIdentity } from '@weiliang0121/capix-contracts';
|
|
8
|
+
export interface BaseRecord<Value = unknown> {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly parentId?: string;
|
|
11
|
+
readonly value: Value;
|
|
12
|
+
}
|
|
13
|
+
export interface CompositeRecord<Value = unknown> extends BaseRecord<Value> {
|
|
14
|
+
readonly childIds: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
export interface RecordingRootValue {
|
|
17
|
+
readonly createdAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RecordingRootRecord extends CompositeRecord<RecordingRootValue> {
|
|
20
|
+
}
|
|
21
|
+
export type ProcessRecord = Readonly<{
|
|
22
|
+
sequence: number;
|
|
23
|
+
eventSequence: number;
|
|
24
|
+
round: number;
|
|
25
|
+
occurredAt: string;
|
|
26
|
+
offsetMs: number;
|
|
27
|
+
} & ({
|
|
28
|
+
stage: 'execute';
|
|
29
|
+
type: 'start';
|
|
30
|
+
input: unknown;
|
|
31
|
+
} | {
|
|
32
|
+
stage: 'execute' | 'receive' | 'handling';
|
|
33
|
+
type: 'return';
|
|
34
|
+
output: unknown;
|
|
35
|
+
} | {
|
|
36
|
+
stage: 'receive';
|
|
37
|
+
type: 'return';
|
|
38
|
+
resultOf: number;
|
|
39
|
+
} | {
|
|
40
|
+
stage: 'execute' | 'receive' | 'handling';
|
|
41
|
+
type: 'throw';
|
|
42
|
+
error: RuntimeErrorValue;
|
|
43
|
+
failure?: InvocationFailureFact;
|
|
44
|
+
} | {
|
|
45
|
+
stage: 'receive' | 'handling';
|
|
46
|
+
type: 'continue';
|
|
47
|
+
input: unknown;
|
|
48
|
+
reason: string;
|
|
49
|
+
} | {
|
|
50
|
+
stage: 'handling';
|
|
51
|
+
type: 'start' | 'unhandled';
|
|
52
|
+
error: RuntimeErrorValue;
|
|
53
|
+
failure?: InvocationFailureFact;
|
|
54
|
+
} | {
|
|
55
|
+
stage: 'control';
|
|
56
|
+
type: 'stop';
|
|
57
|
+
error: RuntimeErrorValue;
|
|
58
|
+
failure?: InvocationFailureFact;
|
|
59
|
+
})>;
|
|
60
|
+
export type RecordedInvocationResult = Readonly<{
|
|
61
|
+
status: 'succeeded';
|
|
62
|
+
output: unknown;
|
|
63
|
+
} | {
|
|
64
|
+
status: 'failed';
|
|
65
|
+
error: RuntimeErrorValue;
|
|
66
|
+
failure?: InvocationFailureFact;
|
|
67
|
+
}>;
|
|
68
|
+
export type RecordedRelationChange = Readonly<{
|
|
69
|
+
kind: 'attached';
|
|
70
|
+
} | {
|
|
71
|
+
kind: 'returned';
|
|
72
|
+
result: RecordedInvocationResult;
|
|
73
|
+
} | {
|
|
74
|
+
kind: 'receiving';
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'accepted';
|
|
77
|
+
output: unknown;
|
|
78
|
+
} | {
|
|
79
|
+
kind: 'handled';
|
|
80
|
+
output: unknown;
|
|
81
|
+
} | {
|
|
82
|
+
kind: 'failed';
|
|
83
|
+
source: 'work' | 'observation';
|
|
84
|
+
error: RuntimeErrorValue;
|
|
85
|
+
failure?: InvocationFailureFact;
|
|
86
|
+
}>;
|
|
87
|
+
export interface RelationChangeRecord {
|
|
88
|
+
readonly identity: InvocationRelationIdentity;
|
|
89
|
+
readonly eventSequence: number;
|
|
90
|
+
readonly occurredAt: string;
|
|
91
|
+
readonly offsetMs: number;
|
|
92
|
+
readonly childId?: string;
|
|
93
|
+
readonly change: RecordedRelationChange;
|
|
94
|
+
}
|
|
95
|
+
export interface InvocationValue<Input = unknown, Output = unknown> {
|
|
96
|
+
readonly processes: readonly ProcessRecord[];
|
|
97
|
+
readonly relationChanges: readonly RelationChangeRecord[];
|
|
98
|
+
input: Input;
|
|
99
|
+
output?: Output;
|
|
100
|
+
resultOf?: number;
|
|
101
|
+
error?: RuntimeErrorValue;
|
|
102
|
+
failure?: InvocationFailureFact;
|
|
103
|
+
}
|
|
104
|
+
export interface RuntimeCallValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
|
|
105
|
+
readonly startedAt: string;
|
|
106
|
+
}
|
|
107
|
+
export interface RuntimeCallRecord<Input = unknown, Output = unknown> extends CompositeRecord<RuntimeCallValue<Input, Output>> {
|
|
108
|
+
readonly contextId: string;
|
|
109
|
+
readonly runtimeInstanceId: string;
|
|
110
|
+
readonly status: 'running' | 'succeeded' | 'failed';
|
|
111
|
+
}
|
|
112
|
+
export interface ExecutionValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
|
|
113
|
+
startedAt: string;
|
|
114
|
+
}
|
|
115
|
+
export interface ExecutionRecord<Input = unknown, Output = unknown> extends CompositeRecord<ExecutionValue<Input, Output>> {
|
|
116
|
+
readonly contextId: string;
|
|
117
|
+
readonly status: 'running' | 'succeeded' | 'failed';
|
|
118
|
+
}
|
|
119
|
+
export interface OperationRecord<Input = unknown, Output = unknown> extends CompositeRecord<InvocationValue<Input, Output>> {
|
|
120
|
+
readonly contextId: string;
|
|
121
|
+
readonly status: 'running' | 'succeeded' | 'failed';
|
|
122
|
+
readonly executionId: string;
|
|
123
|
+
readonly operationInstanceId: string;
|
|
124
|
+
readonly parentOperationId?: string;
|
|
125
|
+
readonly operation: string;
|
|
126
|
+
readonly label: string;
|
|
127
|
+
readonly source: string;
|
|
128
|
+
readonly caller: string;
|
|
129
|
+
readonly callee: string;
|
|
130
|
+
}
|
|
131
|
+
export interface AttemptValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
|
|
132
|
+
}
|
|
133
|
+
export interface AttemptRecord<Input = unknown, Output = unknown> extends CompositeRecord<AttemptValue<Input, Output>> {
|
|
134
|
+
readonly contextId: string;
|
|
135
|
+
readonly status: 'running' | 'succeeded' | 'failed';
|
|
136
|
+
readonly operationId: string;
|
|
137
|
+
readonly name: string;
|
|
138
|
+
readonly label: string;
|
|
139
|
+
readonly source: string;
|
|
140
|
+
readonly caller: string;
|
|
141
|
+
readonly callee: string;
|
|
142
|
+
}
|
|
143
|
+
export interface InvocationBoundaryValue {
|
|
144
|
+
readonly type: 'call' | 'return' | 'throw';
|
|
145
|
+
readonly scope: 'work';
|
|
146
|
+
}
|
|
147
|
+
export interface InvocationBoundaryRecord extends BaseRecord<InvocationBoundaryValue> {
|
|
148
|
+
readonly scopeId: string;
|
|
149
|
+
readonly executionId?: string;
|
|
150
|
+
readonly callId: string;
|
|
151
|
+
readonly sequence: number;
|
|
152
|
+
readonly occurredAt: string;
|
|
153
|
+
readonly offsetMs: number;
|
|
154
|
+
}
|
|
155
|
+
export interface LegacyExecutionRecordSnapshot {
|
|
156
|
+
readonly archive?: RecordingArchiveOrigin;
|
|
157
|
+
runtimeCall: RuntimeCallRecord;
|
|
158
|
+
runtimeEvents: InvocationBoundaryRecord[];
|
|
159
|
+
execution: ExecutionRecord;
|
|
160
|
+
operations: OperationRecord[];
|
|
161
|
+
attempts: AttemptRecord[];
|
|
162
|
+
events: InvocationBoundaryRecord[];
|
|
163
|
+
resources: ResourceRecord[];
|
|
164
|
+
}
|
|
165
|
+
export interface CallableValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
|
|
166
|
+
readonly startedAt?: string;
|
|
167
|
+
}
|
|
168
|
+
export interface CallableRecord<Input = unknown, Output = unknown> extends CompositeRecord<CallableValue<Input, Output>> {
|
|
169
|
+
readonly contextId: string;
|
|
170
|
+
readonly structureKind: CallableKind;
|
|
171
|
+
readonly structureId?: string;
|
|
172
|
+
readonly name?: string;
|
|
173
|
+
readonly label?: string;
|
|
174
|
+
readonly source?: string;
|
|
175
|
+
readonly callee?: string;
|
|
176
|
+
readonly role?: string;
|
|
177
|
+
readonly status: 'running' | 'succeeded' | 'failed';
|
|
178
|
+
}
|
|
179
|
+
export interface ExecutionRecordSnapshot {
|
|
180
|
+
readonly archive?: RecordingArchiveOrigin;
|
|
181
|
+
readonly execution: CallableRecord;
|
|
182
|
+
readonly calls: readonly CallableRecord[];
|
|
183
|
+
readonly rootCall?: CallableRecord;
|
|
184
|
+
readonly ancestors?: readonly CallableRecord[];
|
|
185
|
+
readonly boundaries: readonly InvocationBoundaryRecord[];
|
|
186
|
+
readonly transcripts: readonly TranscriptRecord[];
|
|
187
|
+
readonly memories: readonly MemoryRecord[];
|
|
188
|
+
readonly resources: readonly ResourceRecord[];
|
|
189
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ExecutionRecordSnapshot, LegacyExecutionRecordSnapshot, InvocationValue } from './types.js';
|
|
2
|
+
export declare function validateExecutionRecordSnapshot(value: unknown): asserts value is ExecutionRecordSnapshot;
|
|
3
|
+
export declare function validateLegacyExecutionRecordSnapshot(value: unknown): asserts value is LegacyExecutionRecordSnapshot;
|
|
4
|
+
export declare function validateInvocationRecordValue(value: unknown, ownerContextId: string): asserts value is InvocationValue;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{validateMemoryRecordValue}from"./memory.js";import{validateRecordingArchiveOrigin}from"./archive.js";import{hasOutput,outputProcess,readOutput}from"./invocation.js";function validateExecutionRecordSnapshot(value){function fail(){throw new Error("\u8C03\u7528\u8BB0\u5F55\u683C\u5F0F\u65E0\u6548\u6216\u5173\u8054\u7F3A\u5931\u3002")}__name(fail,"fail"),(!value||typeof value!="object")&&fail();const snapshot=value;snapshot.archive!==void 0&&validateRecordingArchiveOrigin(snapshot.archive),(!snapshot.execution||!Array.isArray(snapshot.calls)||!Array.isArray(snapshot.boundaries)||!Array.isArray(snapshot.resources)||!Array.isArray(snapshot.transcripts)||!Array.isArray(snapshot.memories))&&fail();const records=new Map,contexts=new Set,accept=__name(record=>{(!record||typeof record.id!="string"||!record.id||typeof record.contextId!="string"||!record.contextId||record.contextId===record.id||records.has(record.id)||contexts.has(record.id)||records.has(record.contextId)||contexts.has(record.contextId)||!["scene","group","node"].includes(record.structureKind)||!Array.isArray(record.childIds)||new Set(record.childIds).size!==record.childIds.length||record.childIds.some(id=>typeof id!="string"||!id)||!record.value)&&fail(),(record.value.startedAt===void 0?!snapshot.archive:typeof record.value.startedAt!="string"||!Number.isFinite(Date.parse(record.value.startedAt)))&&fail();for(const key of["structureId","name","label","callee","role"])record[key]!==void 0&&(typeof record[key]!="string"||!record[key].trim())&&fail();record.source!==void 0&&typeof record.source!="string"&&fail(),record.parentId!==void 0&&(typeof record.parentId!="string"||!record.parentId)&&fail(),validateInvocationRecordValue(record.value,record.contextId),validRecordedStatus(record.status,record.value)||fail(),records.set(record.id,record),contexts.add(record.contextId)},"accept");for(const record of snapshot.calls)accept(record);const selected=records.get(snapshot.execution.id);(!selected||JSON.stringify(selected)!==JSON.stringify(snapshot.execution))&&fail(),snapshot.rootCall&&snapshot.rootCall.id!==selected.id?accept(snapshot.rootCall):snapshot.rootCall&&JSON.stringify(snapshot.rootCall)!==JSON.stringify(selected)&&fail(),snapshot.ancestors!==void 0&&!Array.isArray(snapshot.ancestors)&&fail();const ancestors=snapshot.ancestors??[];ancestors.length&&(!snapshot.rootCall||snapshot.rootCall.id===selected.id)&&fail();for(const ancestor of ancestors)accept(ancestor);const path=snapshot.rootCall&&snapshot.rootCall.id!==selected.id?[snapshot.rootCall,...ancestors,selected]:[selected];for(let index=1;index<path.length;index++){const parent=path[index-1],child=path[index];(parent.structureKind==="node"||child.parentId!==parent.id||!parent.childIds.includes(child.id))&&fail()}const root=path[0];root.parentId&&records.has(root.parentId)&&fail();for(const record of snapshot.calls){if(contexts.has(record.id)&&fail(),record.id===selected.id)continue;const visited=new Set([record.id]);let current=record;for(;current.id!==selected.id;){const parent=current.parentId?records.get(current.parentId):void 0;(!parent||visited.has(parent.id)||parent.structureKind==="node"||!parent.childIds.includes(current.id))&&fail(),visited.add(parent.id),current=parent}}for(const record of records.values()){record.structureKind==="scene"&&record.parentId&&records.has(record.parentId)&&fail();for(const relation of record.value.relationChanges){const child=relation.childId?records.get(relation.childId):void 0;child&&(child.parentId!==record.id||child.contextId!==relation.identity.childContextId)&&fail()}}const seen=new Set([...records.keys(),...contexts]),timing=new Map,scopes=new Map;for(const boundary of snapshot.boundaries){const call=records.get(boundary?.callId),prior=scopes.get(boundary?.scopeId);(!boundary||typeof boundary.id!="string"||!boundary.id||seen.has(boundary.id)||!call||boundary.parentId!==call.id||typeof boundary.scopeId!="string"||!boundary.scopeId||!Number.isSafeInteger(boundary.sequence)||boundary.sequence<1||prior&&boundary.sequence<=prior.sequence||!Number.isFinite(boundary.offsetMs)||boundary.offsetMs<(prior?.offsetMs??0)||typeof boundary.occurredAt!="string"||!Number.isFinite(Date.parse(boundary.occurredAt))||boundary.value?.scope!=="work")&&fail(),!snapshot.archive&&(boundary.scopeId!==(snapshot.rootCall??selected).id||boundary.executionId!==void 0)&&fail(),seen.add(boundary.id),scopes.set(boundary.scopeId,{sequence:boundary.sequence,offsetMs:boundary.offsetMs});const state=timing.get(call.id)??{scopeId:boundary.scopeId};state.scopeId!==boundary.scopeId&&fail();const time=boundary.offsetMs;boundary.value.type==="call"?((state.started!==void 0||state.ended!==void 0)&&fail(),state.started=time):boundary.value.type==="return"||boundary.value.type==="throw"?((state.started===void 0||state.ended!==void 0||time<state.started||call.status!==(boundary.value.type==="return"?"succeeded":"failed"))&&fail(),state.ended=time):fail(),timing.set(call.id,state)}for(const record of records.values()){const time=timing.get(record.id);!snapshot.archive&&(!time||time.started===void 0||record.status!=="running"&&time.ended===void 0)&&fail();const parentTime=record.parentId?timing.get(record.parentId):void 0;time?.scopeId===parentTime?.scopeId&&(time?.started!==void 0&&parentTime?.started!==void 0&&time.started<parentTime.started&&fail(),time?.ended!==void 0&&parentTime?.ended!==void 0&&time.ended>parentTime.ended&&fail(),time?.started!==void 0&&parentTime?.ended!==void 0&&time.ended===void 0&&fail())}const resourceSequences=new Map,accesses=new Map,interactions=new Map;for(const resource of snapshot.resources){(!resource||typeof resource.id!="string"||!resource.id||seen.has(resource.id)||!records.has(resource.parentId)||typeof resource.access!="string"||!resource.access||typeof resource.supplyId!="string"||!resource.supplyId||typeof resource.occurredAt!="string"||!Number.isFinite(Date.parse(resource.occurredAt))||!Object.hasOwn(resource,"value")||!Number.isSafeInteger(resource.sequence)||resource.sequence<=(resourceSequences.get(resource.parentId)??0))&&fail(),resourceSequences.set(resource.parentId,resource.sequence),seen.add(resource.id);const key=JSON.stringify([resource.parentId,resource.supplyId,resource.access]);resource.phase==="bound"?((accesses.has(key)||resource.interactionId!==void 0)&&fail(),accesses.set(key,"bound")):resource.phase==="available"||resource.phase==="unavailable"?((accesses.get(key)!=="bound"||resource.interactionId!==void 0)&&fail(),accesses.set(key,resource.phase)):resource.phase==="started"?((accesses.get(key)!=="available"||typeof resource.interactionId!="string"||!resource.interactionId||interactions.has(resource.interactionId))&&fail(),interactions.set(resource.interactionId,key)):resource.phase==="returned"||resource.phase==="threw"?((typeof resource.interactionId!="string"||interactions.get(resource.interactionId)!==key)&&fail(),interactions.delete(resource.interactionId)):fail()}for(const memory of snapshot.memories)validateMemoryRecordValue(memory?.value);for(const content of[...snapshot.transcripts,...snapshot.memories]){const call=content.callId?records.get(content.callId):void 0;(!content||typeof content.id!="string"||!content.id||seen.has(content.id)||!call||content.parentId!==call.id||content.contextId!==call.contextId||!Object.hasOwn(content,"value"))&&fail(),seen.add(content.id)}}__name(validateExecutionRecordSnapshot,"validateExecutionRecordSnapshot");function validateLegacyExecutionRecordSnapshot(value){const fail=__name(()=>{throw new Error("\u8FD0\u884C\u8BB0\u5F55\u683C\u5F0F\u65E0\u6548\u6216\u5173\u8054\u7F3A\u5931\u3002")},"fail");if(!value||typeof value!="object")return fail();const snapshot=value;snapshot.archive!==void 0&&validateRecordingArchiveOrigin(snapshot.archive);const historical=snapshot.archive!==void 0;if(!snapshot.execution||typeof snapshot.execution.id!="string"||!snapshot.execution.id||!snapshot.execution.value||typeof snapshot.execution.value.startedAt!="string"||!Array.isArray(snapshot.operations)||!Array.isArray(snapshot.attempts)||!Array.isArray(snapshot.events)||!Array.isArray(snapshot.resources))return fail();const executionId=snapshot.execution.id,operations=new Map,parents=new Map,statuses=new Map([[executionId,snapshot.execution.status]]),bodies=new Map([[executionId,snapshot.execution.value]]),contextsByRecord=new Map,contextIds=new Set,acceptContextIdentity=__name(record=>{if(typeof record.contextId!="string"||!record.contextId||record.contextId===record.id||contextIds.has(record.contextId))return fail();contextIds.add(record.contextId),contextsByRecord.set(record.id,record.contextId)},"acceptContextIdentity");acceptContextIdentity(snapshot.execution);const runtimeCall=snapshot.runtimeCall;if(!runtimeCall||typeof runtimeCall.id!="string"||!runtimeCall.id||runtimeCall.id===executionId||typeof runtimeCall.runtimeInstanceId!="string"||!runtimeCall.runtimeInstanceId||!runtimeCall.value||typeof runtimeCall.value.startedAt!="string"||snapshot.execution.parentId!==runtimeCall.id||!["running","succeeded","failed"].includes(runtimeCall.status))return fail();acceptContextIdentity(runtimeCall);const validParticipant=__name(value2=>typeof value2=="string"&&value2.trim().length>0,"validParticipant");for(const operationRecord of snapshot.operations){if(!operationRecord||typeof operationRecord.id!="string"||!operationRecord.id||bodies.has(operationRecord.id)||operationRecord.executionId!==executionId||typeof operationRecord.operationInstanceId!="string"||!operationRecord.operationInstanceId||typeof operationRecord.operation!="string"||typeof operationRecord.label!="string"||typeof operationRecord.source!="string"||!validParticipant(operationRecord.caller)||!validParticipant(operationRecord.callee)||operationRecord.parentOperationId!==void 0&&typeof operationRecord.parentOperationId!="string")return fail();acceptContextIdentity(operationRecord),operations.set(operationRecord.id,operationRecord),parents.set(operationRecord.id,operationRecord.parentOperationId??executionId),statuses.set(operationRecord.id,operationRecord.status),bodies.set(operationRecord.id,operationRecord.value)}for(const attemptRecord of snapshot.attempts){if(!attemptRecord||typeof attemptRecord.id!="string"||!attemptRecord.id||bodies.has(attemptRecord.id)||typeof attemptRecord.operationId!="string"||!operations.has(attemptRecord.operationId)||typeof attemptRecord.name!="string"||!attemptRecord.name.trim()||typeof attemptRecord.label!="string"||!attemptRecord.label.trim()||typeof attemptRecord.source!="string"||!validParticipant(attemptRecord.caller)||!validParticipant(attemptRecord.callee))return fail();acceptContextIdentity(attemptRecord),parents.set(attemptRecord.id,attemptRecord.operationId),statuses.set(attemptRecord.id,attemptRecord.status),bodies.set(attemptRecord.id,attemptRecord.value)}if(bodies.has(runtimeCall.id))return fail();const observedBodies=new Map(bodies);observedBodies.set(runtimeCall.id,runtimeCall.value);for(const id of contextIds)if(observedBodies.has(id))return fail();for(const status of statuses.values())if(!["running","succeeded","failed"].includes(status))return fail();for(const[owner,body]of observedBodies)validateInvocationRecordValue(body,contextsByRecord.get(owner));for(const operationRecord of operations.values())if(operationRecord.parentOperationId!==void 0&&!operations.has(operationRecord.parentOperationId))return fail();for(const id of parents.keys()){const visited=new Set([id]);let ancestor=parents.get(id);for(;ancestor&&ancestor!==executionId;){if(visited.has(ancestor))return fail();visited.add(ancestor),ancestor=parents.get(ancestor)}}const active=new Set,entered=new Set,ended=new Set,boundaryIds=new Set;let time=0;for(const[i,boundary]of snapshot.events.entries()){if(!boundary||typeof boundary.id!="string"||!boundary.id||bodies.has(boundary.id)||contextIds.has(boundary.id)||boundaryIds.has(boundary.id)||boundary.executionId!==executionId||boundary.scopeId!==executionId||!boundary.value||boundary.value.scope!=="work"||!["call","return","throw"].includes(boundary.value.type)||typeof boundary.occurredAt!="string"||!Number.isFinite(Date.parse(boundary.occurredAt))||!bodies.has(boundary.callId)||boundary.sequence!==i+1||!Number.isFinite(boundary.offsetMs)||boundary.offsetMs<time)return fail();boundaryIds.add(boundary.id),time=boundary.offsetMs;const parentId=parents.get(boundary.callId);if(boundary.value.type==="call"){if(entered.has(boundary.callId)||parentId!==void 0&&(!active.has(executionId)||!active.has(parentId))||boundary.callId===executionId&&i!==0)return fail();entered.add(boundary.callId),active.add(boundary.callId)}else{const body=bodies.get(boundary.callId);if(!["return","throw"].includes(boundary.value.type)||!active.has(boundary.callId)||[...active].some(id=>id!==boundary.callId&&(boundary.callId===executionId||parents.get(id)===boundary.callId))||!(boundary.value.type==="return"?hasOutput(body):Object.hasOwn(body,"error"))||statuses.get(boundary.callId)!==(boundary.value.type==="return"?"succeeded":"failed"))return fail();active.delete(boundary.callId),ended.add(boundary.callId)}}if(!historical&&entered.size!==bodies.size)return fail();for(const[id,body]of bodies)if(!historical&&!ended.has(id)&&(statuses.get(id)!=="running"||hasOutput(body)||Object.hasOwn(body,"error"))||historical&&!validRecordedStatus(statuses.get(id),body))return fail();if(!Array.isArray(snapshot.runtimeEvents)||!validRuntimeCallBoundaries(snapshot.runtimeEvents,runtimeCall.id,runtimeCall.status,runtimeCall.value,historical))return fail();for(const boundary of snapshot.runtimeEvents){if(boundaryIds.has(boundary.id)||observedBodies.has(boundary.id)||contextIds.has(boundary.id))return fail();boundaryIds.add(boundary.id)}const resourceIds=new Set,resourceSequences=new Map,accesses=new Map,interactions=new Map;for(const resourceRecord of snapshot.resources){if(!resourceRecord||typeof resourceRecord.id!="string"||!resourceRecord.id||bodies.has(resourceRecord.id)||contextIds.has(resourceRecord.id)||boundaryIds.has(resourceRecord.id)||resourceIds.has(resourceRecord.id)||typeof resourceRecord.parentId!="string"||!observedBodies.has(resourceRecord.parentId)||typeof resourceRecord.access!="string"||!resourceRecord.access||typeof resourceRecord.supplyId!="string"||!resourceRecord.supplyId||typeof resourceRecord.occurredAt!="string"||!Number.isFinite(Date.parse(resourceRecord.occurredAt))||!Object.hasOwn(resourceRecord,"value")||!Number.isSafeInteger(resourceRecord.sequence)||resourceRecord.sequence<=(resourceSequences.get(resourceRecord.parentId)??0))return fail();resourceSequences.set(resourceRecord.parentId,resourceRecord.sequence),resourceIds.add(resourceRecord.id);const accessKey=JSON.stringify([resourceRecord.parentId,resourceRecord.supplyId,resourceRecord.access]);if(resourceRecord.phase==="bound"){if(accesses.has(accessKey)||resourceRecord.interactionId!==void 0)return fail();accesses.set(accessKey,"bound")}else if(resourceRecord.phase==="available"||resourceRecord.phase==="unavailable"){if(accesses.get(accessKey)!=="bound"||resourceRecord.interactionId!==void 0)return fail();accesses.set(accessKey,resourceRecord.phase)}else if(resourceRecord.phase==="started"){if(accesses.get(accessKey)!=="available"||typeof resourceRecord.interactionId!="string"||!resourceRecord.interactionId||interactions.has(resourceRecord.interactionId))return fail();interactions.set(resourceRecord.interactionId,accessKey)}else if(resourceRecord.phase==="returned"||resourceRecord.phase==="threw"){if(typeof resourceRecord.interactionId!="string"||interactions.get(resourceRecord.interactionId)!==accessKey)return fail();interactions.delete(resourceRecord.interactionId)}else return fail()}}__name(validateLegacyExecutionRecordSnapshot,"validateLegacyExecutionRecordSnapshot");function validFailure(value){if(!value||typeof value!="object")return!1;const failure=value;return(failure.kind==="exception"||failure.kind==="error")&&typeof failure.contextId=="string"&&failure.contextId.length>0&&["setup","execute","receive","handling","control","observation"].includes(failure.phase)&&(failure.contract===void 0||typeof failure.contract=="string")}__name(validFailure,"validFailure");function validRelations(body,ownerContextId){const relations=new Map,eventSequences=new Set(body.processes.map(process=>process.eventSequence));let previous=0;for(const entry of body.relationChanges){if(!entry||!Number.isSafeInteger(entry.eventSequence)||entry.eventSequence<=previous||eventSequences.has(entry.eventSequence)||!Number.isFinite(entry.offsetMs)||entry.offsetMs<0||typeof entry.occurredAt!="string"||!Number.isFinite(Date.parse(entry.occurredAt))||!entry.identity||!entry.change)return!1;const identity=entry.identity;if(identity.parentContextId!==ownerContextId||typeof identity.childContextId!="string"||!identity.childContextId||identity.childContextId===ownerContextId||!Number.isSafeInteger(identity.parentRound)||identity.parentRound<0||identity.parentRound>2||identity.key!==void 0&&typeof identity.key!="string"||entry.childId!==void 0&&(typeof entry.childId!="string"||!entry.childId))return!1;const old=relations.get(identity.childContextId);if(old&&(old.identity.parentRound!==identity.parentRound||old.identity.key!==identity.key))return!1;const change=entry.change;if(change.kind==="attached"){if(old)return!1;relations.set(identity.childContextId,{identity,phase:"attached"})}else if(change.kind==="returned"){if(old?.phase!=="attached"||!change.result||!["succeeded","failed"].includes(change.result.status)||(change.result.status==="succeeded"?!Object.hasOwn(change.result,"output"):!validError(change.result.error)||change.result.failure!==void 0&&!validFailure(change.result.failure)))return!1;relations.set(identity.childContextId,{identity,phase:"returned",status:change.result.status})}else if(change.kind==="receiving"){if(old?.phase!=="returned")return!1;relations.set(identity.childContextId,{...old,phase:"receiving"})}else if(change.kind==="accepted"){if(old?.phase!=="receiving"||old.status!=="succeeded"||!Object.hasOwn(change,"output"))return!1;relations.set(identity.childContextId,{...old,phase:"accepted"})}else if(change.kind==="handled"){if(old?.phase!=="receiving"||old.status!=="failed"||!Object.hasOwn(change,"output"))return!1;relations.set(identity.childContextId,{...old,phase:"handled"})}else if(change.kind==="failed"){if(old?.phase!=="receiving"||!validError(change.error)||!["work","observation"].includes(change.source)||change.failure!==void 0&&!validFailure(change.failure))return!1;relations.set(identity.childContextId,{...old,phase:"failed"})}else return!1;eventSequences.add(entry.eventSequence),previous=entry.eventSequence}const times=[...body.processes,...body.relationChanges].sort((a,b)=>a.eventSequence-b.eventSequence);return times.every((entry,index)=>index===0||entry.offsetMs>=times[index-1].offsetMs)}__name(validRelations,"validRelations");function validError(value){return!!value&&typeof value=="object"&&typeof value.code=="string"&&typeof value.message=="string"}__name(validError,"validError");function validRuntimeCallBoundaries(boundaries,id,status,value,historical=!1){if(!historical&&boundaries.length<1||boundaries.length>2)return!1;for(const[index,boundary]of boundaries.entries())if(!boundary||!boundary.id||boundary.scopeId!==id||boundary.executionId!==void 0||boundary.callId!==id||boundary.parentId!==id||boundary.sequence!==index+1||!Number.isFinite(boundary.offsetMs)||boundary.offsetMs<(boundaries[index-1]?.offsetMs??0)||!Number.isFinite(Date.parse(boundary.occurredAt))||boundary.value?.scope!=="work"||boundary.value.type!==(index===0?"call":status==="succeeded"?"return":"throw"))return!1;return historical&&boundaries.length<2?validRecordedStatus(status,value):status==="running"?boundaries.length===1:boundaries.length===2&&(status==="succeeded"?hasOutput(value):Object.hasOwn(value,"error"))}__name(validRuntimeCallBoundaries,"validRuntimeCallBoundaries");function validateInvocationRecordValue(value,ownerContextId){const fail=__name(()=>{throw new Error("\u8C03\u7528\u8BB0\u5F55\u6B63\u6587\u65E0\u6548\u3002")},"fail"),body=value;if(!body||!Array.isArray(body.processes)||!Array.isArray(body.relationChanges)||typeof body!="object"||!Object.hasOwn(body,"input")||hasOutput(body)&&Object.hasOwn(body,"error")||Object.hasOwn(body,"output")&&Object.hasOwn(body,"resultOf")||Object.hasOwn(body,"error")&&(!body.error||typeof body.error.code!="string"||typeof body.error.message!="string")||body.failure&&(!Object.hasOwn(body,"error")||!validFailure(body.failure)))return fail();let previousRound=0,previousTime=0,previousSequence=0;for(const[index,process]of body.processes.entries()){if(!process||!Number.isSafeInteger(process.eventSequence)||process.eventSequence<=previousSequence||process.sequence!==index+1||!Number.isInteger(process.round)||process.round<previousRound||process.round>2||!Number.isFinite(process.offsetMs)||process.offsetMs<previousTime||typeof process.occurredAt!="string"||!(process.stage==="execute"?["start","return","throw"]:process.stage==="receive"?["return","throw","continue"]:process.stage==="handling"?["start","return","throw","continue","unhandled"]:process.stage==="control"?["stop"]:[]).includes(process.type)||process.round===0&&process.stage!=="control"||(process.stage==="execute"&&process.type==="start"||process.type==="continue")&&!Object.hasOwn(process,"input")||process.type==="return"&&Object.hasOwn(process,"output")===Object.hasOwn(process,"resultOf"))return fail();if("resultOf"in process)try{const target=outputProcess(body,process.resultOf,process.sequence);if(process.stage!=="receive"||target.stage!=="execute"||target.round!==process.round||target.sequence!==process.sequence-1)return fail()}catch{return fail()}if((process.type==="throw"||process.type==="stop"||process.stage==="handling"&&(process.type==="start"||process.type==="unhandled"))&&(!process.error||typeof process.error.code!="string"||typeof process.error.message!="string")||process.type==="continue"&&(typeof process.reason!="string"||!process.reason.trim())||"failure"in process&&process.failure&&!validFailure(process.failure))return fail();previousRound=process.round,previousTime=process.offsetMs,previousSequence=process.eventSequence}if(!validRelations(body,ownerContextId))return fail();if(Object.hasOwn(body,"resultOf"))try{readOutput(body)}catch{return fail()}}__name(validateInvocationRecordValue,"validateInvocationRecordValue");function validRecordedStatus(status,body){return status==="running"?!hasOutput(body)&&!Object.hasOwn(body,"error"):status==="succeeded"?hasOutput(body)&&!Object.hasOwn(body,"error"):status==="failed"&&Object.hasOwn(body,"error")&&!hasOutput(body)}__name(validRecordedStatus,"validRecordedStatus");export{validateExecutionRecordSnapshot,validateInvocationRecordValue,validateLegacyExecutionRecordSnapshot};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { InvocationFailureFact, RuntimeErrorValue } from '@weiliang0121/capix-contracts';
|
|
2
2
|
import type { Recorder } from '../recorder.js';
|
|
3
|
-
import type { ExecutionValue, LegacyExecutionRecordSnapshot } from '
|
|
3
|
+
import type { ExecutionValue, LegacyExecutionRecordSnapshot } from '../data/index.js';
|
|
4
4
|
import type { RecordBook } from '../book.js';
|
|
5
5
|
import { ExecutionRecord } from './record.js';
|
|
6
6
|
export declare class ExecutionRecordHelper {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExecutionRecord as ExecutionData, ExecutionValue } from '
|
|
1
|
+
import type { ExecutionRecord as ExecutionData, ExecutionValue } from '../data/index.js';
|
|
2
2
|
import { InvocationRecord } from '../invocation/record.js';
|
|
3
3
|
export declare class ExecutionRecord extends InvocationRecord<ExecutionValue> implements ExecutionData {
|
|
4
4
|
readonly contextId: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -28,3 +28,4 @@ export { snapshotValue } from './value/snapshot.js';
|
|
|
28
28
|
export type { RecordChangeSource } from './source.js';
|
|
29
29
|
export { RecordingError, writeRecord } from './error.js';
|
|
30
30
|
export { RecordResource, type RecordReader, type RecordCreator } from './resource.js';
|
|
31
|
+
export { transcriptRecord, memoryRecord, recordContentFact } from './content.js';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
-
import{CallableRecord}from"./callable/record.js";import{CallableRecordHelper}from"./callable/helper.js";import{BaseRecord}from"./record.js";import{CompositeRecord}from"./composite.js";import{InvocationRecord}from"./invocation/record.js";import{InvocationRecordHelper}from"./invocation/helper.js";import{RecordingRootRecord}from"./root/record.js";import{RecordingRootHelper}from"./root/helper.js";import{ExecutionRecord}from"./execution/record.js";import{ExecutionRecordHelper}from"./execution/helper.js";import{OperationRecord}from"./operation/record.js";import{OperationRecordHelper}from"./operation/helper.js";import{AttemptRecord}from"./attempt/record.js";import{AttemptRecordHelper}from"./attempt/helper.js";import{RecordBook}from"./book.js";import{InvocationBoundaryRecord}from"./invocation/boundary/record.js";import{InvocationBoundaryRecordHelper}from"./invocation/boundary/helper.js";import{MemoryRecord}from"./memory/record.js";import{MemoryRecordHelper}from"./memory/helper.js";import{observeMemory}from"./memory/observe.js";import{TranscriptRecord}from"./transcript/record.js";import{TranscriptRecordHelper}from"./transcript/helper.js";import{RecordTree}from"./tree/tree.js";import{ResourceRecord}from"./resource/record.js";import{RuntimeCallRecord}from"./runtime/record.js";import{Recorder}from"./recorder.js";import{snapshotValue}from"./value/snapshot.js";import{RecordingError,writeRecord}from"./error.js";import{RecordResource}from"./resource.js";export{AttemptRecord,AttemptRecordHelper,BaseRecord,CallableRecord,CallableRecordHelper,CompositeRecord,ExecutionRecord,ExecutionRecordHelper,InvocationBoundaryRecord,InvocationBoundaryRecordHelper,InvocationRecord,InvocationRecordHelper,MemoryRecord,MemoryRecordHelper,OperationRecord,OperationRecordHelper,RecordBook,RecordResource,RecordTree,Recorder,RecordingError,RecordingRootHelper,RecordingRootRecord,ResourceRecord,RuntimeCallRecord,TranscriptRecord,TranscriptRecordHelper,observeMemory,snapshotValue,writeRecord};
|
|
2
|
+
import{CallableRecord}from"./callable/record.js";import{CallableRecordHelper}from"./callable/helper.js";import{BaseRecord}from"./record.js";import{CompositeRecord}from"./composite.js";import{InvocationRecord}from"./invocation/record.js";import{InvocationRecordHelper}from"./invocation/helper.js";import{RecordingRootRecord}from"./root/record.js";import{RecordingRootHelper}from"./root/helper.js";import{ExecutionRecord}from"./execution/record.js";import{ExecutionRecordHelper}from"./execution/helper.js";import{OperationRecord}from"./operation/record.js";import{OperationRecordHelper}from"./operation/helper.js";import{AttemptRecord}from"./attempt/record.js";import{AttemptRecordHelper}from"./attempt/helper.js";import{RecordBook}from"./book.js";import{InvocationBoundaryRecord}from"./invocation/boundary/record.js";import{InvocationBoundaryRecordHelper}from"./invocation/boundary/helper.js";import{MemoryRecord}from"./memory/record.js";import{MemoryRecordHelper}from"./memory/helper.js";import{observeMemory}from"./memory/observe.js";import{TranscriptRecord}from"./transcript/record.js";import{TranscriptRecordHelper}from"./transcript/helper.js";import{RecordTree}from"./tree/tree.js";import{ResourceRecord}from"./resource/record.js";import{RuntimeCallRecord}from"./runtime/record.js";import{Recorder}from"./recorder.js";import{snapshotValue}from"./value/snapshot.js";import{RecordingError,writeRecord}from"./error.js";import{RecordResource}from"./resource.js";import{transcriptRecord,memoryRecord,recordContentFact}from"./content.js";export{AttemptRecord,AttemptRecordHelper,BaseRecord,CallableRecord,CallableRecordHelper,CompositeRecord,ExecutionRecord,ExecutionRecordHelper,InvocationBoundaryRecord,InvocationBoundaryRecordHelper,InvocationRecord,InvocationRecordHelper,MemoryRecord,MemoryRecordHelper,OperationRecord,OperationRecordHelper,RecordBook,RecordResource,RecordTree,Recorder,RecordingError,RecordingRootHelper,RecordingRootRecord,ResourceRecord,RuntimeCallRecord,TranscriptRecord,TranscriptRecordHelper,memoryRecord,observeMemory,recordContentFact,snapshotValue,transcriptRecord,writeRecord};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InvocationBoundaryValue } from '
|
|
1
|
+
import type { InvocationBoundaryValue } from '../../data/index.js';
|
|
2
2
|
import type { Recorder } from '../../recorder.js';
|
|
3
3
|
import type { RecordBook } from '../../book.js';
|
|
4
4
|
import { InvocationBoundaryRecord } from './record.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InvocationBoundaryRecord as BoundaryData, InvocationBoundaryValue } from '
|
|
1
|
+
import type { InvocationBoundaryRecord as BoundaryData, InvocationBoundaryValue } from '../../data/index.js';
|
|
2
2
|
import { BaseRecord } from '../../record.js';
|
|
3
3
|
export type InvocationBoundaryRecordOptions = Omit<BoundaryData, 'id' | 'value' | 'parentId' | 'scopeId'> & {
|
|
4
4
|
readonly scopeId?: string;
|
|
@@ -3,14 +3,14 @@ import type { RuntimeCallRecord } from '../runtime/record.js';
|
|
|
3
3
|
import type { ExecutionRecord } from '../execution/record.js';
|
|
4
4
|
import type { OperationRecord } from '../operation/record.js';
|
|
5
5
|
import type { AttemptRecord } from '../attempt/record.js';
|
|
6
|
-
import { type InvocationValue, type ProcessRecord, type RelationChangeRecord } from '
|
|
6
|
+
import { type InvocationValue, type ProcessRecord, type RelationChangeRecord } from '../data/index.js';
|
|
7
7
|
import type { RuntimeErrorValue, InvocationFailureFact } from '@weiliang0121/capix-contracts';
|
|
8
8
|
import { CompositeRecord } from '../composite.js';
|
|
9
9
|
import { restoreStatus } from '../restoration/access.js';
|
|
10
10
|
export type ConcreteInvocationRecord = CallableRecord | RuntimeCallRecord | ExecutionRecord | OperationRecord | AttemptRecord;
|
|
11
11
|
export declare class InvocationRecord<Value extends InvocationValue> extends CompositeRecord<Value> {
|
|
12
12
|
#private;
|
|
13
|
-
get status(): "
|
|
13
|
+
get status(): "succeeded" | "failed" | "running";
|
|
14
14
|
protected requireRunning(): void;
|
|
15
15
|
[restoreStatus](status: 'running' | 'succeeded' | 'failed'): void;
|
|
16
16
|
append(process: ProcessRecord): void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
-
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{outputProcess,finalOutputProcess}from"
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{outputProcess,finalOutputProcess}from"../data/index.js";import{CompositeRecord}from"../composite.js";import{isUndefined}from"es-toolkit/predicate";import{snapshotValue}from"../value/snapshot.js";import{restoreStatus}from"../restoration/access.js";class InvocationRecord extends CompositeRecord{static{__name(this,"InvocationRecord")}#status="running";get status(){return this.#status}requireRunning(){if(this.requireWritable(),this.#status!=="running")throw new Error("Record has already ended")}[restoreStatus](status){this.requireWritable(),this.#status=status}append(process){if(this.requireRunning(),process.sequence!==this.value.processes.length+1)throw new Error("Process sequence must advance in order");if("resultOf"in process){if(Object.hasOwn(process,"output"))throw new Error("Output and local result reference are mutually exclusive");const target=outputProcess(this.value,process.resultOf,process.sequence);if(process.stage!=="receive"||target.stage!=="execute"||target.round!==process.round||target.sequence!==process.sequence-1)throw new Error("Receive may only reuse its own execution result")}const captured=snapshotValue(process);this.replaceValue(Object.freeze({...this.value,processes:Object.freeze([...this.value.processes,captured])}))}appendRelation(relation){if(this.requireRunning(),!Number.isSafeInteger(relation.eventSequence)||relation.eventSequence<1)throw new Error("Relation fact requires an event sequence");const last=this.value.relationChanges.at(-1);if(last&&relation.eventSequence<=last.eventSequence)throw new Error("Relation fact sequence must advance");const captured=snapshotValue(relation);this.replaceValue(Object.freeze({...this.value,relationChanges:Object.freeze([...this.value.relationChanges,captured])}))}complete(output,resultOf){this.requireRunning(),isUndefined(resultOf)?this.replaceValue(Object.freeze({...this.value,output:snapshotValue(output)})):(finalOutputProcess(this.value,resultOf),this.replaceValue(Object.freeze({...this.value,resultOf}))),this.#status="succeeded"}fail(error,failure){this.requireRunning(),this.replaceValue(Object.freeze({...this.value,error:snapshotValue(error),...failure?{failure:snapshotValue(failure)}:{}})),this.#status="failed"}}export{InvocationRecord};
|
package/dist/memory/helper.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MemoryRecordValue } from '
|
|
1
|
+
import type { MemoryRecordValue } from '../data/index.js';
|
|
2
2
|
import type { RecordBook } from '../book.js';
|
|
3
3
|
import { MemoryRecord, type MemoryRecordOptions } from './record.js';
|
|
4
4
|
export declare class MemoryRecordHelper {
|
package/dist/memory/observe.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MemoryRecordContent, MemoryRecordObservation } from '../data/index.js';
|
|
2
2
|
import type { RecordBook } from '../book.js';
|
|
3
3
|
export declare function observeMemory(collection: {
|
|
4
|
-
readonly
|
|
4
|
+
readonly id: string;
|
|
5
|
+
values(): readonly {
|
|
5
6
|
readonly id: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
})[];
|
|
10
|
-
}, book: RecordBook): MemoryObservation;
|
|
7
|
+
readonly value: MemoryRecordContent;
|
|
8
|
+
}[];
|
|
9
|
+
}, book: RecordBook): MemoryRecordObservation;
|
package/dist/memory/observe.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
-
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{MemoryRecord}from"./record.js";function observeMemory(collection,book){const records=new Map;for(const record of book.values()){if(!(record instanceof MemoryRecord))continue;const own=records.get(record.memoryId);own?own.push(record):records.set(record.memoryId,[record])}return{items:collection.values().map(memory=>({id:memory.id,
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{MemoryRecord}from"./record.js";function observeMemory(collection,book){const records=new Map;for(const record of book.values()){if(!(record instanceof MemoryRecord)||record.memoriesId!==collection.id)continue;const own=records.get(record.memoryId);own?own.push(record):records.set(record.memoryId,[record])}return{items:collection.values().map(memory=>({id:memory.id,value:{content:memory.value.content},records:(records.get(memory.id)??[]).map(record=>record.toJSON())}))}}__name(observeMemory,"observeMemory");export{observeMemory};
|
package/dist/memory/record.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type MemoryRecord as MemoryRecordData, type MemoryRecordValue } from '../data/index.js';
|
|
2
2
|
import type { RecordChangeSource } from '../source.js';
|
|
3
3
|
import { BaseRecord } from '../record.js';
|
|
4
4
|
export interface MemoryRecordOptions {
|
package/dist/memory/record.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
-
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{isSafeInteger}from"es-toolkit/compat";import{isString,isUndefined}from"es-toolkit/predicate";import{pick,omitBy}from"es-toolkit/object";import{BaseRecord}from"../record.js";import{snapshotValue}from"../value/snapshot.js";class MemoryRecord extends BaseRecord{static{__name(this,"MemoryRecord")}kind="memory";memoryId;memoriesId;sequence;executionId;operationId;contextId;callId;constructor(options,value){if(super(snapshotValue(value),options.source?.callId),!isString(options.memoriesId)||!/\S/u.test(options.memoriesId)||!isSafeInteger(options.sequence)||options.sequence<1)throw new Error("Memory change requires a scope and a positive sequence");this.memoryId=options.memoryId,this.memoriesId=options.memoriesId,this.sequence=options.sequence,this.executionId=options.source?.executionId,this.operationId=options.source?.operationId,this.contextId=options.source?.contextId,this.callId=options.source?.callId,Object.freeze(this)}toJSON(){return{...super.toJSON(),...pick(this,["memoryId","memoriesId","sequence"]),...omitBy(pick(this,["executionId","operationId","contextId","callId"]),isUndefined)}}}export{MemoryRecord};
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{isSafeInteger}from"es-toolkit/compat";import{isString,isUndefined}from"es-toolkit/predicate";import{pick,omitBy}from"es-toolkit/object";import{validateMemoryRecordValue}from"../data/index.js";import{BaseRecord}from"../record.js";import{snapshotValue}from"../value/snapshot.js";class MemoryRecord extends BaseRecord{static{__name(this,"MemoryRecord")}kind="memory";memoryId;memoriesId;sequence;executionId;operationId;contextId;callId;constructor(options,value){if(super(snapshotValue(value),options.source?.callId),validateMemoryRecordValue(this.value),!isString(options.memoriesId)||!/\S/u.test(options.memoriesId)||!isSafeInteger(options.sequence)||options.sequence<1)throw new Error("Memory change requires a scope and a positive sequence");this.memoryId=options.memoryId,this.memoriesId=options.memoriesId,this.sequence=options.sequence,this.executionId=options.source?.executionId,this.operationId=options.source?.operationId,this.contextId=options.source?.contextId,this.callId=options.source?.callId,Object.freeze(this)}toJSON(){return{...super.toJSON(),...pick(this,["memoryId","memoriesId","sequence"]),...omitBy(pick(this,["executionId","operationId","contextId","callId"]),isUndefined)}}}export{MemoryRecord};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OperationRecord as OperationData, InvocationValue } from '
|
|
1
|
+
import type { OperationRecord as OperationData, InvocationValue } from '../data/index.js';
|
|
2
2
|
import { InvocationRecord } from '../invocation/record.js';
|
|
3
3
|
export type OperationRecordOptions = Omit<OperationData, 'id' | 'value' | 'status' | 'parentId' | 'childIds'>;
|
|
4
4
|
export declare class OperationRecord extends InvocationRecord<InvocationValue> implements OperationData {
|
package/dist/record.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RecordKind, BaseRecord as RecordData } from '
|
|
1
|
+
import type { RecordKind, BaseRecord as RecordData } from './data/index.js';
|
|
2
2
|
import { restoreContent, sealHistorical } from './restoration/access.js';
|
|
3
3
|
export declare abstract class BaseRecord<Value> implements RecordData<Value> {
|
|
4
4
|
#private;
|
package/dist/recorder.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RecordChangeEvent, RecordMutation } from '
|
|
1
|
+
import type { RecordChangeEvent, RecordMutation } from './data/index.js';
|
|
2
2
|
import type { ChangeCapture } from '@weiliang0121/capix-changes';
|
|
3
3
|
import { RecordBook } from './book.js';
|
|
4
4
|
import type { BaseRecord } from './record.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ResourceRecord as ResourceRecordData } from '
|
|
1
|
+
import type { ResourceRecord as ResourceRecordData } from '../data/index.js';
|
|
2
2
|
import { BaseRecord } from '../record.js';
|
|
3
3
|
export type ResourceRecordOptions = Omit<ResourceRecordData, 'id' | 'value'>;
|
|
4
4
|
export declare class ResourceRecord<Detail = unknown> extends BaseRecord<Detail> implements ResourceRecordData<Detail> {
|
package/dist/resource.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ResourceOffer } from '@weiliang0121/capix-resources';
|
|
2
|
-
import type { RecordEntry } from '
|
|
2
|
+
import type { RecordEntry } from './data/index.js';
|
|
3
3
|
import type { RecordBookState } from './book.js';
|
|
4
4
|
import type { Recorder } from './recorder.js';
|
|
5
5
|
export interface RecordReader {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type RecordEntry } from '
|
|
1
|
+
import { type RecordEntry } from '../data/index.js';
|
|
2
2
|
export declare function checkEntry(entry: RecordEntry): void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
-
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{hasOutput,validateInvocationRecordValue}from"
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{hasOutput,validateInvocationRecordValue,validateMemoryRecordValue}from"../data/index.js";import{isPlainObject}from"es-toolkit/predicate";function fail(){throw new Error("Invalid stored record")}__name(fail,"fail");function object(value){return isPlainObject(value)?value:fail()}__name(object,"object");function text(value){(typeof value!="string"||!value.trim())&&fail()}__name(text,"text");function optionalText(value){value!==void 0&&text(value)}__name(optionalText,"optionalText");function integer(value,minimum=0){(typeof value!="number"||!Number.isSafeInteger(value)||value<minimum)&&fail()}__name(integer,"integer");function time(value){text(value),Number.isFinite(Date.parse(value))||fail()}__name(time,"time");function children(value){(!Array.isArray(value)||new Set(value).size!==value.length)&&fail();for(const id of value)text(id)}__name(children,"children");function checkEntry(entry){const outer=object(entry);(Object.keys(outer).length!==2||!Object.hasOwn(outer,"kind")||!Object.hasOwn(outer,"data"))&&fail();const data=object(outer.data);if(text(data.id),optionalText(data.parentId),Object.hasOwn(data,"value")||fail(),["invocation","runtime","runtime-call","execution","operation","attempt"].includes(entry.kind)&&children(data.childIds),["invocation","runtime-call","execution","operation","attempt"].includes(entry.kind)){text(data.parentId),text(data.contextId),data.contextId===data.id&&fail(),validateInvocationRecordValue(data.value,data.contextId);const output=hasOutput(data.value),error=Object.hasOwn(data.value,"error");(data.status==="running"?output||error:data.status==="succeeded"?!output||error:data.status!=="failed"||!error||output)&&fail()}switch(entry.kind){case"invocation":["scene","group","node"].includes(data.structureKind)||fail();for(const name of["structureId","name","label","callee","role"])optionalText(data[name]);data.source!==void 0&&typeof data.source!="string"&&fail(),time(object(data.value).startedAt);break;case"runtime":time(object(data.value).createdAt);break;case"runtime-call":text(data.runtimeInstanceId),time(object(data.value).startedAt);break;case"execution":time(object(data.value).startedAt);break;case"operation":for(const name of["executionId","operationInstanceId","operation","label","caller","callee"])text(data[name]);typeof data.source!="string"&&fail(),optionalText(data.parentOperationId);break;case"attempt":for(const name of["operationId","name","label","caller","callee"])text(data[name]);typeof data.source!="string"&&fail();break;case"invocation-boundary":{text(data.scopeId),text(data.callId),optionalText(data.executionId),integer(data.sequence,1),time(data.occurredAt),(typeof data.offsetMs!="number"||!Number.isFinite(data.offsetMs)||data.offsetMs<0)&&fail();const value=object(data.value);(value.scope!=="work"||!["call","return","throw"].includes(value.type))&&fail();break}case"resource":for(const name of["parentId","access","supplyId"])text(data[name]);integer(data.sequence,1),time(data.occurredAt),["bound","available","unavailable","started","returned","threw"].includes(data.phase)||fail(),["started","returned","threw"].includes(data.phase)?text(data.interactionId):data.interactionId!==void 0&&fail();break;case"transcript":{text(data.transcriptId),integer(data.revision,1),time(data.occurredAt);const value=object(data.value);integer(value.start),integer(value.end),value.action==="append"?value.end<=value.start&&fail():value.action==="segment"?(integer(value.previousStart),(value.previousStart>=value.start||value.start>=value.end)&&fail()):fail(),checkContentSource(data);break}case"memory":{text(data.memoryId),text(data.memoriesId),integer(data.sequence,1),optionalText(data.operationId),checkContentSource(data),validateMemoryRecordValue(data.value);break}case"custom":Object.hasOwn(data,"childIds")&&children(data.childIds);break;default:fail()}}__name(checkEntry,"checkEntry");function checkContentSource(data){optionalText(data.callId),optionalText(data.contextId),optionalText(data.executionId),data.callId===void 0!=(data.contextId===void 0)&&fail()}__name(checkContentSource,"checkContentSource");export{checkEntry};
|
package/dist/restoration/tree.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
2
|
-
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{CallableRecord}from"../callable/record.js";import{CompositeRecord}from"../composite.js";import{InvocationRecord}from"../invocation/record.js";import{InvocationBoundaryRecord}from"../invocation/boundary/record.js";import{ResourceRecord}from"../resource/record.js";import{checkRelation}from"../tree/relation.js";function checkRestoredTree(book){const contexts=new Set,boundaries=new Map,resources=new Map;for(const record of book.values()){const parent=record.parentId===void 0?void 0:book.get(record.parentId);if(record.parentId!==void 0&&!(parent instanceof CompositeRecord))throw new Error("Stored record parent is missing or cannot contain children");if(parent instanceof CompositeRecord&&!parent.childIds.includes(record.id))throw new Error("Stored record parent does not reference its child");if(record instanceof CompositeRecord)for(const childId of record.childIds){const child=book.get(childId);if(!child||child.parentId!==record.id)throw new Error("Inconsistent stored child reference")}if(checkRelation(record,parent,book,"restore"),record instanceof InvocationRecord&&"contextId"in record){const contextId=record.contextId;if(contexts.has(contextId)||book.get(contextId))throw new Error("Stored invocation context identity conflicts");contexts.add(contextId);for(const relation of record.value.relationChanges){const child=relation.childId===void 0?void 0:book.get(relation.childId);if(child&&(child.parentId!==record.id||!("contextId"in child)||child.contextId!==relation.identity.childContextId))throw new Error("Stored child relation points to another invocation")}}if(record instanceof InvocationBoundaryRecord){const invocation=book.get(record.callId);if(invocation instanceof CallableRecord){let scope2=invocation;const parents=new Set([scope2.id]);let parent2=scope2.parentId?book.get(scope2.parentId):void 0;for(;parent2 instanceof CallableRecord;){if(parents.has(parent2.id))throw new Error("Stored callable ancestry contains a cycle");parents.add(parent2.id),scope2=parent2,parent2=scope2.parentId?book.get(scope2.parentId):void 0}if(record.scopeId!==scope2.id||record.executionId!==void 0)throw new Error("Stored callable boundary has an inconsistent timing scope")}else if(record.scopeId!==(record.executionId??record.callId))throw new Error("Stored boundary has an inconsistent timing scope");const scope=boundaries.get(record.scopeId)??{sequence:0,offsetMs:0,calls:new Map};if(record.sequence!==scope.sequence+1||record.offsetMs<scope.offsetMs)throw new Error("Stored boundary sequence does not advance");const prior=scope.calls.get(record.callId);if(record.value.type==="call"?prior!==void 0:prior!=="call")throw new Error("Stored boundary does not follow its call");const call=book.get(record.callId);if(record.value.type==="call"&&record.callId!==record.scopeId&&scope.calls.get(call.parentId)!=="call")throw new Error("Stored child boundary starts outside its parent work");if(record.value.type==="call"&&record.callId===record.scopeId&&record.sequence!==1)throw new Error("Stored work scope must start before its children");if(record.value.type!=="call"&&[...scope.calls].some(([id,state])=>state==="call"&&book.get(id)?.parentId===record.callId))throw new Error("Stored parent boundary ends before its active child");scope.sequence=record.sequence,scope.offsetMs=record.offsetMs,scope.calls.set(record.callId,record.value.type),boundaries.set(record.scopeId,scope)}if(record instanceof ResourceRecord){const scope=resources.get(record.parentId)??{sequence:0,accesses:new Map,interactions:new Map};if(record.sequence
|
|
2
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{CallableRecord}from"../callable/record.js";import{CompositeRecord}from"../composite.js";import{InvocationRecord}from"../invocation/record.js";import{InvocationBoundaryRecord}from"../invocation/boundary/record.js";import{ResourceRecord}from"../resource/record.js";import{checkRelation}from"../tree/relation.js";function checkRestoredTree(book){const contexts=new Set,boundaries=new Map,resources=new Map;for(const record of book.values()){const parent=record.parentId===void 0?void 0:book.get(record.parentId);if(record.parentId!==void 0&&!(parent instanceof CompositeRecord))throw new Error("Stored record parent is missing or cannot contain children");if(parent instanceof CompositeRecord&&!parent.childIds.includes(record.id))throw new Error("Stored record parent does not reference its child");if(record instanceof CompositeRecord)for(const childId of record.childIds){const child=book.get(childId);if(!child||child.parentId!==record.id)throw new Error("Inconsistent stored child reference")}if(checkRelation(record,parent,book,"restore"),record instanceof InvocationRecord&&"contextId"in record){const contextId=record.contextId;if(contexts.has(contextId)||book.get(contextId))throw new Error("Stored invocation context identity conflicts");contexts.add(contextId);for(const relation of record.value.relationChanges){const child=relation.childId===void 0?void 0:book.get(relation.childId);if(child&&(child.parentId!==record.id||!("contextId"in child)||child.contextId!==relation.identity.childContextId))throw new Error("Stored child relation points to another invocation")}}if(record instanceof InvocationBoundaryRecord){const invocation=book.get(record.callId);if(invocation instanceof CallableRecord){let scope2=invocation;const parents=new Set([scope2.id]);let parent2=scope2.parentId?book.get(scope2.parentId):void 0;for(;parent2 instanceof CallableRecord;){if(parents.has(parent2.id))throw new Error("Stored callable ancestry contains a cycle");parents.add(parent2.id),scope2=parent2,parent2=scope2.parentId?book.get(scope2.parentId):void 0}if(record.scopeId!==scope2.id||record.executionId!==void 0)throw new Error("Stored callable boundary has an inconsistent timing scope")}else if(record.scopeId!==(record.executionId??record.callId))throw new Error("Stored boundary has an inconsistent timing scope");const scope=boundaries.get(record.scopeId)??{sequence:0,offsetMs:0,calls:new Map};if(record.sequence!==scope.sequence+1||record.offsetMs<scope.offsetMs)throw new Error("Stored boundary sequence does not advance");const prior=scope.calls.get(record.callId);if(record.value.type==="call"?prior!==void 0:prior!=="call")throw new Error("Stored boundary does not follow its call");const call=book.get(record.callId);if(record.value.type==="call"&&record.callId!==record.scopeId&&scope.calls.get(call.parentId)!=="call")throw new Error("Stored child boundary starts outside its parent work");if(record.value.type==="call"&&record.callId===record.scopeId&&record.sequence!==1)throw new Error("Stored work scope must start before its children");if(record.value.type!=="call"&&[...scope.calls].some(([id,state])=>state==="call"&&book.get(id)?.parentId===record.callId))throw new Error("Stored parent boundary ends before its active child");scope.sequence=record.sequence,scope.offsetMs=record.offsetMs,scope.calls.set(record.callId,record.value.type),boundaries.set(record.scopeId,scope)}if(record instanceof ResourceRecord){const scope=resources.get(record.parentId)??{sequence:0,accesses:new Map,interactions:new Map};if(!Number.isSafeInteger(record.sequence)||record.sequence<=scope.sequence)throw new Error("Stored resource sequence does not advance");const key=JSON.stringify([record.supplyId,record.access]);if(record.phase==="bound"){if(scope.accesses.has(key))throw new Error("Stored resource access is already bound");scope.accesses.set(key,record.phase)}else if(record.phase==="available"||record.phase==="unavailable"){if(scope.accesses.get(key)!=="bound")throw new Error("Stored resource access is not bound");scope.accesses.set(key,record.phase)}else if(record.phase==="started"){if(scope.accesses.get(key)!=="available"||scope.interactions.has(record.interactionId))throw new Error("Stored resource interaction is not available");scope.interactions.set(record.interactionId,key)}else{if(scope.interactions.get(record.interactionId)!==key)throw new Error("Stored resource interaction has not started");scope.interactions.delete(record.interactionId)}scope.sequence=record.sequence,resources.set(record.parentId,scope)}}}__name(checkRestoredTree,"checkRestoredTree");export{checkRestoredTree};
|
package/dist/root/record.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RecordingRootRecord as RecordingRootData, RecordingRootValue } from '
|
|
1
|
+
import type { RecordingRootRecord as RecordingRootData, RecordingRootValue } from '../data/index.js';
|
|
2
2
|
import { CompositeRecord } from '../composite.js';
|
|
3
3
|
export declare class RecordingRootRecord extends CompositeRecord<RecordingRootValue> implements RecordingRootData {
|
|
4
4
|
readonly kind: "runtime";
|
package/dist/runtime/record.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RuntimeCallRecord as RuntimeCallData, RuntimeCallValue } from '
|
|
1
|
+
import type { RuntimeCallRecord as RuntimeCallData, RuntimeCallValue } from '../data/index.js';
|
|
2
2
|
import { InvocationRecord } from '../invocation/record.js';
|
|
3
3
|
export declare class RuntimeCallRecord extends InvocationRecord<RuntimeCallValue> implements RuntimeCallData {
|
|
4
4
|
readonly contextId: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TranscriptChange } from '
|
|
1
|
+
import type { TranscriptChange } from '../data/index.js';
|
|
2
2
|
import type { RecordClock } from '../recorder.js';
|
|
3
3
|
import { TranscriptRecord, type TranscriptRecordOptions } from './record.js';
|
|
4
4
|
export declare class TranscriptRecordHelper {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TranscriptChange, TranscriptRecord as RecordData } from '
|
|
1
|
+
import type { TranscriptChange, TranscriptRecord as RecordData } from '../data/index.js';
|
|
2
2
|
import type { RecordChangeSource } from '../source.js';
|
|
3
3
|
import { BaseRecord } from '../record.js';
|
|
4
4
|
export interface TranscriptRecordOptions {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weiliang0121/capix-records",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -11,14 +11,19 @@
|
|
|
11
11
|
"./construction": {
|
|
12
12
|
"types": "./dist/construction.d.ts",
|
|
13
13
|
"import": "./dist/construction.js"
|
|
14
|
+
},
|
|
15
|
+
"./data": {
|
|
16
|
+
"types": "./dist/data/index.d.ts",
|
|
17
|
+
"import": "./dist/data/index.js"
|
|
14
18
|
}
|
|
15
19
|
},
|
|
16
20
|
"dependencies": {
|
|
17
21
|
"es-toolkit": "1.52.0",
|
|
18
|
-
"@weiliang0121/capix-contracts": "0.
|
|
19
|
-
"@weiliang0121/capix-
|
|
20
|
-
"@weiliang0121/capix-
|
|
21
|
-
"@weiliang0121/capix-
|
|
22
|
+
"@weiliang0121/capix-contracts": "0.2.0",
|
|
23
|
+
"@weiliang0121/capix-changes": "0.2.0",
|
|
24
|
+
"@weiliang0121/capix-memory": "0.2.0",
|
|
25
|
+
"@weiliang0121/capix-resources": "0.2.0",
|
|
26
|
+
"@weiliang0121/capix-transcript": "0.2.0"
|
|
22
27
|
},
|
|
23
28
|
"description": "Optional recording entities and resource contracts for CAPiX.",
|
|
24
29
|
"license": "MIT",
|
|
@@ -26,7 +31,7 @@
|
|
|
26
31
|
"repository": {
|
|
27
32
|
"type": "git",
|
|
28
33
|
"url": "git+https://github.com/weiliang0121/capix.git",
|
|
29
|
-
"directory": "
|
|
34
|
+
"directory": "packages/records"
|
|
30
35
|
},
|
|
31
36
|
"engines": {
|
|
32
37
|
"node": ">=22.23.2"
|
|
@@ -45,6 +50,7 @@
|
|
|
45
50
|
},
|
|
46
51
|
"scripts": {
|
|
47
52
|
"build": "tsc -p tsconfig.json",
|
|
48
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
53
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
54
|
+
"test": "node ../../scripts/test/run.mjs --package ."
|
|
49
55
|
}
|
|
50
56
|
}
|