@weiliang0121/capix-runtime 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +20 -2
- package/dist/binding/access.d.ts +24 -0
- package/dist/binding/access.js +2 -0
- package/dist/binding/callable.d.ts +14 -0
- package/dist/binding/callable.js +2 -0
- package/dist/binding/calls.d.ts +41 -0
- package/dist/binding/calls.js +2 -0
- package/dist/binding/checkpoint-list.d.ts +1 -0
- package/dist/binding/checkpoint-list.js +2 -0
- package/dist/binding/checkpoint.d.ts +9 -0
- package/dist/binding/checkpoint.js +2 -0
- package/dist/binding/children/binding.d.ts +34 -0
- package/dist/binding/children/binding.js +2 -0
- package/dist/binding/children/bound.d.ts +19 -0
- package/dist/binding/children/bound.js +2 -0
- package/dist/binding/children/builder.d.ts +18 -0
- package/dist/binding/children/builder.js +2 -0
- package/dist/binding/children/references.d.ts +29 -0
- package/dist/binding/children/references.js +2 -0
- package/dist/binding/contract.d.ts +27 -0
- package/dist/binding/contract.js +1 -0
- package/dist/binding/declarations.d.ts +18 -0
- package/dist/binding/declarations.js +2 -0
- package/dist/binding/hooks.d.ts +32 -0
- package/dist/binding/hooks.js +2 -0
- package/dist/binding/observation.d.ts +27 -0
- package/dist/binding/observation.js +2 -0
- package/dist/binding/receptions.d.ts +9 -0
- package/dist/binding/receptions.js +2 -0
- package/dist/binding/resources.d.ts +18 -0
- package/dist/binding/resources.js +2 -0
- package/dist/binding/snapshot.d.ts +16 -0
- package/dist/binding/snapshot.js +2 -0
- package/dist/binding/work.d.ts +20 -0
- package/dist/binding/work.js +2 -0
- package/dist/construction/calls.d.ts +21 -0
- package/dist/construction/calls.js +2 -0
- package/dist/construction/capabilities.d.ts +11 -0
- package/dist/construction/capabilities.js +2 -0
- package/dist/construction/feedback.d.ts +15 -0
- package/dist/construction/feedback.js +2 -0
- package/dist/construction/invocation.d.ts +38 -0
- package/dist/construction/invocation.js +2 -0
- package/dist/construction.d.ts +25 -0
- package/dist/construction.js +2 -0
- package/dist/definition/observation.d.ts +18 -0
- package/dist/definition/observation.js +2 -0
- package/dist/entry.d.ts +32 -0
- package/dist/entry.js +2 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +2 -0
- package/dist/initializer.d.ts +7 -0
- package/dist/initializer.js +2 -0
- package/dist/legacy/binding.d.ts +14 -0
- package/dist/legacy/binding.js +2 -0
- package/dist/legacy/driver.d.ts +20 -0
- package/dist/legacy/driver.js +2 -0
- package/dist/legacy/sources.d.ts +41 -0
- package/dist/legacy/sources.js +2 -0
- package/dist/observation/driver.d.ts +24 -0
- package/dist/observation/driver.js +1 -0
- package/dist/recording.d.ts +3 -0
- package/dist/recording.js +2 -0
- package/dist/records/observation/declaration.d.ts +18 -0
- package/dist/records/observation/declaration.js +2 -0
- package/dist/records/observation/installation.d.ts +37 -0
- package/dist/records/observation/installation.js +2 -0
- package/dist/records/observation/invocation.d.ts +34 -0
- package/dist/records/observation/invocation.js +2 -0
- package/dist/records/observation/mapping.d.ts +7 -0
- package/dist/records/observation/mapping.js +2 -0
- package/dist/resource/installation.d.ts +9 -0
- package/dist/resource/installation.js +2 -0
- package/dist/resource/resources.d.ts +37 -0
- package/dist/resource/resources.js +2 -0
- package/dist/runner/cancellation.d.ts +9 -0
- package/dist/runner/cancellation.js +2 -0
- package/dist/runner/feedback.d.ts +20 -0
- package/dist/runner/feedback.js +2 -0
- package/dist/runner/observation-contract.d.ts +137 -0
- package/dist/runner/observation-contract.js +1 -0
- package/dist/runner/observation-projection.d.ts +7 -0
- package/dist/runner/observation-projection.js +2 -0
- package/dist/runner/observation.d.ts +14 -0
- package/dist/runner/observation.js +2 -0
- package/dist/runner/output.d.ts +14 -0
- package/dist/runner/output.js +2 -0
- package/dist/runner.d.ts +37 -0
- package/dist/runner.js +2 -0
- package/dist/structure/builder.d.ts +12 -0
- package/dist/structure/builder.js +2 -0
- package/dist/structure/construction.d.ts +22 -0
- package/dist/structure/construction.js +2 -0
- package/dist/structure/install.d.ts +5 -0
- package/dist/structure/install.js +2 -0
- package/package.json +57 -3
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AnyCallable, ResolvedCallable } from '../binding/declarations.js';
|
|
2
|
+
import type { Interactions } from '@weiliang0121/capix-interaction';
|
|
3
|
+
import { ResourceSupply } from '@weiliang0121/capix-resources';
|
|
4
|
+
import type { ResourcePlan } from './resources.js';
|
|
5
|
+
export declare class ResourceInstallation<Options> {
|
|
6
|
+
private readonly scopes;
|
|
7
|
+
constructor(root: ResolvedCallable, plan: ResourcePlan<Options>, interactions?: Interactions);
|
|
8
|
+
open(structure: AnyCallable, input: unknown, options: Options, inherited?: ResourceSupply): ResourceSupply;
|
|
9
|
+
}
|
|
@@ -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{resourceRequests,checkResourceProviders,ResourceSupply}from"@weiliang0121/capix-resources";class ResourceInstallation{static{__name(this,"ResourceInstallation")}scopes=new Map;constructor(root,plan,interactions){const captureScopes=new Map(plan.scopes.map(scope=>[scope.structure,scope])),visit=__name((resolved,inherited)=>{const scope=captureScopes.get(resolved.definition),requested=resourceRequests(resolved.supply),needed=new Set(requested.map(request=>request.offer)),local=(scope?.registrations??[]).filter(entry=>needed.has(entry.offer)).map(entry=>entry.bind(interactions)),localOffers=new Set(local.map(entry=>entry.offer)),fixed=resolved===root?plan.registrations.filter(entry=>needed.has(entry.offer)&&!localOffers.has(entry.offer)).map(entry=>entry.bind(interactions)):[],available=[...(resolved===root?fixed:inherited).filter(entry=>!localOffers.has(entry.offer)),...local];checkResourceProviders(requested,available),this.scopes.set(resolved.definition,Object.freeze({supply:resolved.supply,fixed,local,capture:local.length?scope?.capture:void 0}));for(const member of resolved.members)visit(member,available)},"visit");visit(root,[])}open(structure,input,options,inherited){const scope=this.scopes.get(structure);if(!scope)throw new Error("Callable resource scope is not installed");const base=inherited??ResourceSupply.capture(scope.fixed,void 0),snapshot=scope.capture?.(input,options);return base.overlay(ResourceSupply.capture(scope.local,snapshot)).select(scope.supply)}}export{ResourceInstallation};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AnyCallable } from '../binding/declarations.js';
|
|
2
|
+
import type { ChildResourceBinding } from '../binding/resources.js';
|
|
3
|
+
import { type ChildCallable } from '@weiliang0121/capix-structure';
|
|
4
|
+
import type { CallableInput, Stable } from '@weiliang0121/capix-contracts';
|
|
5
|
+
import type { InteractionContract } from '@weiliang0121/capix-interaction';
|
|
6
|
+
import type { InteractionChannel, Interactions } from '@weiliang0121/capix-interaction';
|
|
7
|
+
import { ResourceOffer, type ResourceIdentity, type ResourceProvider, type ResourceRefinement, Resource } from '@weiliang0121/capix-resources';
|
|
8
|
+
export interface ResourceRegistration {
|
|
9
|
+
readonly offer: ResourceIdentity;
|
|
10
|
+
bind(interactions?: Interactions): ResourceProvider<unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface ResourceCaptureScope<Options> {
|
|
13
|
+
readonly structure: AnyCallable;
|
|
14
|
+
readonly capture: (input: unknown, options: Options) => unknown;
|
|
15
|
+
readonly registrations: readonly ResourceRegistration[];
|
|
16
|
+
}
|
|
17
|
+
export interface ResourcePlan<Options> {
|
|
18
|
+
readonly registrations: readonly ResourceRegistration[];
|
|
19
|
+
readonly scopes: readonly ResourceCaptureScope<Options>[];
|
|
20
|
+
readonly refinements: readonly ChildResourceBinding[];
|
|
21
|
+
}
|
|
22
|
+
type Synchronous<Value> = Value & (Value extends PromiseLike<unknown> ? never : unknown);
|
|
23
|
+
export declare class CapturedResources<Snapshot> {
|
|
24
|
+
private readonly registrations;
|
|
25
|
+
constructor(registrations: ResourceRegistration[]);
|
|
26
|
+
register<Source, Value, Captured, Selection>(offer: ResourceOffer<Source, Value, Captured, Selection>, select: (snapshot: Snapshot) => Synchronous<NoInfer<Source>>): this;
|
|
27
|
+
}
|
|
28
|
+
export declare class Resources<Options extends object = {}> {
|
|
29
|
+
#private;
|
|
30
|
+
register<Source, Value, Captured, Selection>(resource: Resource<NoInfer<Source>>, offer: ResourceOffer<Source, Value, Captured, Selection>): this;
|
|
31
|
+
register<Source, Value, Captured, Selection>(offer: ResourceOffer<Source, Value, Captured, Selection>, supply: NoInfer<Source>): this;
|
|
32
|
+
capture<Structure extends AnyCallable, Snapshot>(structure: Structure, capture: (input: Stable<CallableInput<Structure>>, options: Options) => Synchronous<Snapshot>): CapturedResources<Snapshot>;
|
|
33
|
+
refine<Structure extends ChildCallable>(structure: Structure, ...rules: readonly ResourceRefinement<NoInfer<Stable<CallableInput<Structure>>>>[]): this;
|
|
34
|
+
registerInteraction<Request, Reply, Delta, Value, Captured, Selection>(offer: ResourceOffer<InteractionChannel<Request, Reply, Delta>, Value, Captured, Selection>, contract: InteractionContract<NoInfer<Request>, NoInfer<Reply>, NoInfer<Delta>>): this;
|
|
35
|
+
snapshot(root: AnyCallable): ResourcePlan<Options>;
|
|
36
|
+
}
|
|
37
|
+
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});import{Callable}from"@weiliang0121/capix-structure";import{ResourceOffer,Resource}from"@weiliang0121/capix-resources";class CapturedResources{static{__name(this,"CapturedResources")}registrations;constructor(registrations){this.registrations=registrations}register(offer,select){const provider=offer.provide(snapshot=>synchronous(select(snapshot),"Resource selection"));return addRegistration(this.registrations,Object.freeze({offer:provider.offer,bind:__name(()=>provider,"bind")})),this}}class Resources{static{__name(this,"Resources")}#registrations=[];#scopes=new Map;#refinements=new Map;register(resourceOrOffer,offerOrSupply){const resource=resourceOrOffer instanceof Resource?resourceOrOffer:void 0,offer=resource?offerOrSupply:resourceOrOffer;if(!(offer instanceof ResourceOffer))throw new TypeError("Resource registration requires an access offer");const supply=resource?resource.origin:offerOrSupply,provider=offer.provide(()=>supply);return addRegistration(this.#registrations,Object.freeze({offer:provider.offer,bind:__name(()=>provider,"bind")})),this}capture(structure,capture){if(requireCallable(structure),this.#scopes.has(structure))throw new Error("Duplicate resource capture scope");const registrations=[];return this.#scopes.set(structure,{capture:__name((input,options)=>synchronous(capture(input,options),"Resource capture"),"capture"),registrations}),new CapturedResources(registrations)}refine(structure,...rules){if(requireCallable(structure),structure.kind!=="group"&&structure.kind!=="node")throw new Error("Resource refinement requires a child structure");const previous=this.#refinements.get(structure)??[];return this.#refinements.set(structure,[...previous,...rules]),this}registerInteraction(offer,contract){const identity=offer.request().offer;return addRegistration(this.#registrations,Object.freeze({offer:identity,bind:__name(interactions=>{if(!interactions)throw new Error(`Resource requires Interactions: ${identity.name}`);const channel=interactions.bind(contract);return offer.provide(()=>channel)},"bind")})),this}snapshot(root){const members=new Set,visit=__name(current=>{if(!members.has(current)&&(members.add(current),current.kind!=="node"))for(const member of current.members)visit(member)},"visit");return visit(root),Object.freeze({registrations:Object.freeze([...this.#registrations]),scopes:Object.freeze([...this.#scopes].filter(([structure])=>members.has(structure)).map(([structure,scope])=>Object.freeze({structure,capture:scope.capture,registrations:Object.freeze([...scope.registrations])}))),refinements:Object.freeze([...this.#refinements].filter(([structure])=>members.has(structure)).map(([definition,refinements])=>Object.freeze({definition,refinements:Object.freeze([...refinements])})))})}}function requireCallable(structure){if(!(structure instanceof Callable))throw new TypeError("Resource scope requires a callable structure")}__name(requireCallable,"requireCallable");function addRegistration(registrations,registration){if(registrations.some(entry=>entry.offer===registration.offer))throw new Error(`Duplicate resource registration: ${registration.offer.name}`);registrations.push(registration)}__name(addRegistration,"addRegistration");function synchronous(value,label){if(value!==null&&(typeof value=="object"||typeof value=="function")&&typeof value.then=="function")throw Promise.resolve(value).catch(()=>{}),new TypeError(`${label} must be synchronous`);return value}__name(synchronous,"synchronous");export{CapturedResources,Resources};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class RunnerCancellation {
|
|
2
|
+
#private;
|
|
3
|
+
private readonly external?;
|
|
4
|
+
constructor(external?: AbortSignal | undefined);
|
|
5
|
+
get signal(): AbortSignal;
|
|
6
|
+
cancel(reason?: unknown): boolean;
|
|
7
|
+
deliveryError(error: unknown): unknown;
|
|
8
|
+
dispose(): void;
|
|
9
|
+
}
|
|
@@ -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{InvocationCancelled,isInvocationCancelled}from"@weiliang0121/capix-invocation";class RunnerCancellation{static{__name(this,"RunnerCancellation")}external;#controller=new AbortController;#origin;#externalAborted=__name(()=>{this.#controller.signal.aborted||(this.#origin="external",this.#controller.abort(this.external?.reason))},"#externalAborted");constructor(external){if(this.external=external,external){if(!(external instanceof AbortSignal))throw new TypeError("Runner signal must be an AbortSignal");external.aborted?this.#externalAborted():external.addEventListener("abort",this.#externalAborted,{once:!0})}}get signal(){return this.#controller.signal}cancel(reason){return!this.signal.aborted&&this.external?.aborted&&this.#externalAborted(),this.signal.aborted?!1:(this.#origin="runner",this.#controller.abort(reason),!0)}deliveryError(error){return this.#origin==="external"&&this.external&&isInvocationCancelled(error,this.signal)?new InvocationCancelled(this.external,{cause:error}):error}dispose(){this.external?.removeEventListener("abort",this.#externalAborted)}}export{RunnerCancellation};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ProgressReceiver } from '@weiliang0121/capix-changes';
|
|
2
|
+
import type { InvocationIdentity } from '@weiliang0121/capix-contracts';
|
|
3
|
+
import type { Clock } from '@weiliang0121/capix-invocation';
|
|
4
|
+
import type { CallableFeedback } from '../construction/feedback.js';
|
|
5
|
+
import type { EntryChange } from '../entry.js';
|
|
6
|
+
import { RunnerObservationSubscriptions } from './observation.js';
|
|
7
|
+
export declare class RunnerEntryFeedback {
|
|
8
|
+
#private;
|
|
9
|
+
private readonly runnerId;
|
|
10
|
+
private readonly subscriptions;
|
|
11
|
+
private readonly clock;
|
|
12
|
+
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
|
13
|
+
readonly created: ProgressReceiver<InvocationIdentity>;
|
|
14
|
+
constructor(runnerId: string, subscriptions: RunnerObservationSubscriptions, clock: Clock);
|
|
15
|
+
requested(mode: 'run' | 'resume', requestedContextId?: string): void;
|
|
16
|
+
entry(change: EntryChange): void;
|
|
17
|
+
settled(status: 'succeeded' | 'failed' | 'cancelled', error?: unknown): void;
|
|
18
|
+
receivers(signal: AbortSignal): CallableFeedback;
|
|
19
|
+
private publishEntry;
|
|
20
|
+
}
|
|
@@ -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{randomUUID}from"node:crypto";import{ProgressChannel}from"@weiliang0121/capix-changes";import"./observation.js";import{projectInvocation,projectResource,projectBusiness,projectCheckpoint,projectDiagnostic}from"./observation-projection.js";class RunnerEntryFeedback{static{__name(this,"RunnerEntryFeedback")}runnerId;subscriptions;clock;id=randomUUID();#sequence=0;#entries;created;constructor(runnerId,subscriptions,clock){this.runnerId=runnerId,this.subscriptions=subscriptions,this.clock=clock,this.#entries=new ProgressChannel({receive:__name(change=>this.publishEntry(change),"receive")}),this.created=Object.freeze({receive:__name(identity=>{this.#entries.publish({kind:"attached",identity})},"receive")})}requested(mode,requestedContextId){this.#entries.publish({kind:"requested",mode,...requestedContextId!==void 0?{requestedContextId}:{}})}entry(change){change.kind!=="established"&&this.#entries.publish(change)}settled(status,error){this.#entries.publish({kind:"settled",status,error})}receivers(signal){return Object.freeze({invocation:{receive:__name(fact=>{this.subscriptions.active&&this.subscriptions.publish({runnerId:this.runnerId,entryId:this.id,source:"invocation",fact:projectInvocation(fact,signal)})},"receive")},resource:{receive:__name(fact=>{this.subscriptions.active&&this.subscriptions.publish({runnerId:this.runnerId,entryId:this.id,source:"resource",fact:projectResource(fact)})},"receive")},business:{receive:__name(fact=>{this.subscriptions.active&&this.subscriptions.publish({runnerId:this.runnerId,entryId:this.id,source:"business",fact:projectBusiness(fact)})},"receive")},checkpoint:{receive:__name(fact=>{this.subscriptions.active&&this.subscriptions.publish({runnerId:this.runnerId,entryId:this.id,source:"checkpoint",fact:projectCheckpoint(fact,signal)})},"receive")}})}publishEntry(change){const sequence=++this.#sequence;if(!this.subscriptions.active)return;const time={sequence,occurredAt:this.clock.now()};let fact;change.kind==="requested"?fact=Object.freeze({...time,...change}):change.kind==="attached"?fact=Object.freeze({...time,kind:"attached",identity:Object.freeze({...change.identity})}):change.kind==="settled"?fact=Object.freeze({...time,kind:"settled",status:change.status,...change.status!=="succeeded"?{diagnostic:projectDiagnostic(change.error)}:{}}):change.kind==="entry-failed"?fact=Object.freeze({...time,kind:"entry-failed",diagnostic:projectDiagnostic(change.error)}):change.kind==="rejected"?fact=Object.freeze({...time,kind:"rejected",reason:change.reason,diagnostic:projectDiagnostic(change.error)}):fact=Object.freeze({...time,kind:change.kind}),this.subscriptions.publish({runnerId:this.runnerId,entryId:this.id,source:"entry",fact})}}export{RunnerEntryFeedback};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { InvocationIdentity } from '@weiliang0121/capix-contracts';
|
|
2
|
+
import type { InvocationProgress } from '@weiliang0121/capix-invocation';
|
|
3
|
+
export interface RunnerDiagnostic {
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly message: string;
|
|
6
|
+
}
|
|
7
|
+
export type RunnerEntryFact = Readonly<{
|
|
8
|
+
sequence: number;
|
|
9
|
+
occurredAt: string;
|
|
10
|
+
} & ({
|
|
11
|
+
kind: 'requested';
|
|
12
|
+
mode: 'run' | 'resume';
|
|
13
|
+
requestedContextId?: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'acquired' | 'released';
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'rejected';
|
|
18
|
+
reason: 'busy';
|
|
19
|
+
diagnostic: RunnerDiagnostic;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'entry-failed';
|
|
22
|
+
diagnostic: RunnerDiagnostic;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'attached';
|
|
25
|
+
identity: InvocationIdentity;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'settled';
|
|
28
|
+
status: 'succeeded' | 'failed' | 'cancelled';
|
|
29
|
+
diagnostic?: RunnerDiagnostic;
|
|
30
|
+
})>;
|
|
31
|
+
export interface RunnerResourceFact {
|
|
32
|
+
readonly contextId: string;
|
|
33
|
+
readonly offerId: string;
|
|
34
|
+
readonly access: string;
|
|
35
|
+
readonly supplyId: string;
|
|
36
|
+
readonly sequence: number;
|
|
37
|
+
readonly occurredAt: string;
|
|
38
|
+
readonly phase: 'bound' | 'available' | 'unavailable' | 'started' | 'returned' | 'threw';
|
|
39
|
+
readonly interactionId?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface RunnerBusinessFact {
|
|
42
|
+
readonly identity: InvocationIdentity;
|
|
43
|
+
readonly sequence: number;
|
|
44
|
+
readonly occurredAt: string;
|
|
45
|
+
readonly event: string;
|
|
46
|
+
}
|
|
47
|
+
export type RunnerCheckpointChild = Readonly<{
|
|
48
|
+
identity: InvocationIdentity;
|
|
49
|
+
round: number;
|
|
50
|
+
order: number;
|
|
51
|
+
key?: string;
|
|
52
|
+
} & ({
|
|
53
|
+
state: 'waiting';
|
|
54
|
+
} | {
|
|
55
|
+
state: 'returned';
|
|
56
|
+
reception: 'pending' | 'receiving' | 'accepted' | 'failed';
|
|
57
|
+
} | {
|
|
58
|
+
state: 'failed';
|
|
59
|
+
reception?: 'handled';
|
|
60
|
+
})>;
|
|
61
|
+
export interface RunnerTranscriptFact {
|
|
62
|
+
readonly transcriptId: string;
|
|
63
|
+
readonly revision: number;
|
|
64
|
+
readonly change: 'messages-appended' | 'segment-started';
|
|
65
|
+
readonly start: number;
|
|
66
|
+
readonly end: number;
|
|
67
|
+
}
|
|
68
|
+
export interface RunnerMemoryFact {
|
|
69
|
+
readonly memoriesId: string;
|
|
70
|
+
readonly sequence: number;
|
|
71
|
+
readonly action: 'create' | 'update';
|
|
72
|
+
readonly memoryId: string;
|
|
73
|
+
}
|
|
74
|
+
export type RunnerCheckpointFact = Readonly<{
|
|
75
|
+
activityId: string;
|
|
76
|
+
contextId: string;
|
|
77
|
+
owner: InvocationIdentity;
|
|
78
|
+
recovering: boolean;
|
|
79
|
+
sequence: number;
|
|
80
|
+
occurredAt: string;
|
|
81
|
+
} & ({
|
|
82
|
+
kind: 'captured' | 'saved' | 'checking' | 'continued';
|
|
83
|
+
checkpointId: string;
|
|
84
|
+
point: string;
|
|
85
|
+
} | {
|
|
86
|
+
kind: 'installed';
|
|
87
|
+
checkpointId: string;
|
|
88
|
+
point: string;
|
|
89
|
+
baseline: Readonly<{
|
|
90
|
+
round: number;
|
|
91
|
+
nextChildOrder: number;
|
|
92
|
+
childCount: number;
|
|
93
|
+
}>;
|
|
94
|
+
} | {
|
|
95
|
+
kind: 'child-restored';
|
|
96
|
+
child: RunnerCheckpointChild;
|
|
97
|
+
mode: 'continuation' | 'delivery';
|
|
98
|
+
} | {
|
|
99
|
+
kind: 'activity';
|
|
100
|
+
fact: InvocationProgress;
|
|
101
|
+
} | {
|
|
102
|
+
kind: 'resource';
|
|
103
|
+
fact: RunnerResourceFact;
|
|
104
|
+
} | {
|
|
105
|
+
kind: 'transcript';
|
|
106
|
+
fact: RunnerTranscriptFact;
|
|
107
|
+
} | {
|
|
108
|
+
kind: 'memory';
|
|
109
|
+
fact: RunnerMemoryFact;
|
|
110
|
+
} | {
|
|
111
|
+
kind: 'failed';
|
|
112
|
+
stage: 'capture' | 'save' | 'restore' | 'finish';
|
|
113
|
+
diagnostic: RunnerDiagnostic;
|
|
114
|
+
childContextId?: string;
|
|
115
|
+
} | {
|
|
116
|
+
kind: 'finishing' | 'finished';
|
|
117
|
+
status: 'succeeded' | 'failed' | 'cancelled';
|
|
118
|
+
})>;
|
|
119
|
+
export type RunnerObservationEvent = Readonly<{
|
|
120
|
+
runnerId: string;
|
|
121
|
+
entryId: string;
|
|
122
|
+
} & ({
|
|
123
|
+
source: 'entry';
|
|
124
|
+
fact: RunnerEntryFact;
|
|
125
|
+
} | {
|
|
126
|
+
source: 'invocation';
|
|
127
|
+
fact: InvocationProgress;
|
|
128
|
+
} | {
|
|
129
|
+
source: 'resource';
|
|
130
|
+
fact: RunnerResourceFact;
|
|
131
|
+
} | {
|
|
132
|
+
source: 'checkpoint';
|
|
133
|
+
fact: RunnerCheckpointFact;
|
|
134
|
+
} | {
|
|
135
|
+
source: 'business';
|
|
136
|
+
fact: RunnerBusinessFact;
|
|
137
|
+
})>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type InvocationFact, type InvocationProgress, type ResourceObservation, type BusinessObservation, type CheckpointFact } from '@weiliang0121/capix-invocation';
|
|
2
|
+
import type { RunnerDiagnostic, RunnerResourceFact, RunnerBusinessFact, RunnerCheckpointFact } from './observation-contract.js';
|
|
3
|
+
export declare function projectInvocation(fact: InvocationFact, signal: AbortSignal): InvocationProgress;
|
|
4
|
+
export declare function projectResource(fact: ResourceObservation): RunnerResourceFact;
|
|
5
|
+
export declare function projectBusiness(fact: BusinessObservation): RunnerBusinessFact;
|
|
6
|
+
export declare function projectDiagnostic(error: unknown): RunnerDiagnostic;
|
|
7
|
+
export declare function projectCheckpoint(fact: CheckpointFact, signal: AbortSignal): RunnerCheckpointFact;
|
|
@@ -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{RuntimeErrorHelper}from"@weiliang0121/capix-diagnostics";import{invocationProgress}from"@weiliang0121/capix-invocation";function projectInvocation(fact,signal){return invocationProgress(fact,signal)}__name(projectInvocation,"projectInvocation");function projectResource(fact){return Object.freeze({contextId:fact.contextId,offerId:fact.offerId,access:fact.access,supplyId:fact.supplyId,sequence:fact.sequence,occurredAt:fact.occurredAt,phase:fact.phase,...fact.interactionId!==void 0?{interactionId:fact.interactionId}:{}})}__name(projectResource,"projectResource");function projectBusiness(fact){return Object.freeze({identity:projectIdentity(fact.identity),sequence:fact.sequence,occurredAt:fact.occurredAt,event:fact.event.event})}__name(projectBusiness,"projectBusiness");function projectDiagnostic(error){try{const diagnostic=RuntimeErrorHelper.format(error);return Object.freeze({code:diagnostic.code.slice(0,128),message:diagnostic.message.slice(0,512)})}catch{return Object.freeze({code:"OBSERVATION_DIAGNOSTIC_FAILED",message:"The failure could not be described."})}}__name(projectDiagnostic,"projectDiagnostic");function projectCheckpoint(fact,signal){const base={activityId:fact.activityId,contextId:fact.contextId,owner:projectIdentity(fact.owner),recovering:fact.recovering,sequence:fact.sequence,occurredAt:fact.occurredAt};switch(fact.kind){case"captured":case"saved":case"checking":case"continued":return Object.freeze({...base,kind:fact.kind,checkpointId:fact.checkpointId,point:fact.point});case"installed":return Object.freeze({...base,kind:fact.kind,checkpointId:fact.checkpointId,point:fact.point,baseline:Object.freeze({round:fact.frame.round,nextChildOrder:fact.frame.nextChildOrder,childCount:fact.frame.children.length})});case"child-restored":return Object.freeze({...base,kind:fact.kind,child:projectChild(fact.child),mode:fact.mode});case"activity":return Object.freeze({...base,kind:fact.kind,fact:projectInvocation(fact.fact,signal)});case"resource":return Object.freeze({...base,kind:fact.kind,fact:projectResource(fact.fact)});case"transcript":{const change=fact.fact.change,content=Object.freeze({transcriptId:fact.fact.transcriptId,revision:fact.fact.revision,change:change.kind,start:change.start,end:change.kind==="messages-appended"?change.start+change.messages.length:change.end});return Object.freeze({...base,kind:fact.kind,fact:content})}case"memory":return Object.freeze({...base,kind:fact.kind,fact:Object.freeze({memoriesId:fact.fact.memoriesId,sequence:fact.fact.sequence,action:fact.fact.change.action,memoryId:fact.fact.change.memoryId})});case"failed":return Object.freeze({...base,kind:fact.kind,stage:fact.stage,diagnostic:projectDiagnostic(fact.error),...fact.childContextId!==void 0?{childContextId:fact.childContextId}:{}});case"finishing":case"finished":return Object.freeze({...base,kind:fact.kind,status:fact.status})}}__name(projectCheckpoint,"projectCheckpoint");function projectIdentity(identity){return Object.freeze({contextId:identity.contextId,kind:identity.kind,...identity.parentContextId!==void 0?{parentContextId:identity.parentContextId}:{}})}__name(projectIdentity,"projectIdentity");function projectChild(child){const base={identity:projectIdentity(child.identity),round:child.round,order:child.order,...child.key!==void 0?{key:child.key}:{}};return child.state.kind==="waiting"?Object.freeze({...base,state:child.state.kind}):child.state.kind==="returned"?Object.freeze({...base,state:child.state.kind,reception:child.state.reception.kind}):Object.freeze({...base,state:child.state.kind,...child.state.reception?{reception:child.state.reception.kind}:{}})}__name(projectChild,"projectChild");export{projectBusiness,projectCheckpoint,projectDiagnostic,projectInvocation,projectResource};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ProgressReceiver } from '@weiliang0121/capix-changes';
|
|
2
|
+
import type { RunnerObservationEvent } from './observation-contract.js';
|
|
3
|
+
export type { RunnerDiagnostic, RunnerEntryFact, RunnerResourceFact, RunnerBusinessFact, RunnerCheckpointChild, RunnerCheckpointFact, RunnerObservationEvent } from './observation-contract.js';
|
|
4
|
+
export type RunnerObservationReceiver = ProgressReceiver<RunnerObservationEvent>;
|
|
5
|
+
export interface RunnerObservation {
|
|
6
|
+
subscribe(receiver: RunnerObservationReceiver): () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare class RunnerObservationSubscriptions {
|
|
9
|
+
#private;
|
|
10
|
+
readonly port: RunnerObservation;
|
|
11
|
+
get active(): boolean;
|
|
12
|
+
publish(event: RunnerObservationEvent): undefined;
|
|
13
|
+
private subscribe;
|
|
14
|
+
}
|
|
@@ -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{ProgressChannel}from"@weiliang0121/capix-changes";class RunnerObservationSubscriptions{static{__name(this,"RunnerObservationSubscriptions")}#subscribers=new Set;port=Object.freeze({subscribe:__name(receiver=>this.subscribe(receiver),"subscribe")});get active(){return this.#subscribers.size>0}publish(event){const fixed=Object.freeze({...event});for(const channel of[...this.#subscribers])this.#subscribers.has(channel)&&(channel.publish(fixed),channel.failure&&this.#subscribers.delete(channel))}subscribe(receiver){if(!receiver||typeof receiver.receive!="function"||receiver.failed!==void 0&&typeof receiver.failed!="function")throw new TypeError("Observation subscription requires a synchronous receiver");const channel=new ProgressChannel({receive:receiver.receive.bind(receiver),failed:receiver.failed?.bind(receiver)});return this.#subscribers.add(channel),()=>{this.#subscribers.delete(channel)}}}export{RunnerObservationSubscriptions};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InvocationOutputEvent, InvocationOutputReceiver, ProgressReceiver } from '@weiliang0121/capix-contracts';
|
|
2
|
+
export type RunnerOutputEvent<Result, Delta = never> = InvocationOutputEvent<Result, Delta> & Readonly<{
|
|
3
|
+
entryId: string;
|
|
4
|
+
}>;
|
|
5
|
+
export interface RunnerOutput<Result, Delta = never> {
|
|
6
|
+
subscribe(receiver: ProgressReceiver<RunnerOutputEvent<Result, Delta>>): () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare class RunnerOutputSubscriptions<Result, Delta> {
|
|
9
|
+
#private;
|
|
10
|
+
readonly port: RunnerOutput<Result, Delta>;
|
|
11
|
+
forEntry(entryId: string): InvocationOutputReceiver<Result, Delta>;
|
|
12
|
+
private subscribe;
|
|
13
|
+
private publish;
|
|
14
|
+
}
|
|
@@ -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{ProgressChannel}from"@weiliang0121/capix-changes";class RunnerOutputSubscriptions{static{__name(this,"RunnerOutputSubscriptions")}#subscribers=new Set;port=Object.freeze({subscribe:__name(receiver=>this.subscribe(receiver),"subscribe")});forEntry(entryId){return Object.freeze({receive:__name(event=>this.publish(event,entryId),"receive")})}subscribe(receiver){if(!receiver||typeof receiver.receive!="function"||receiver.failed!==void 0&&typeof receiver.failed!="function")throw new TypeError("Output subscription requires a synchronous receiver");const channel=new ProgressChannel({receive:receiver.receive.bind(receiver),failed:receiver.failed?.bind(receiver)});return this.#subscribers.add(channel),()=>{this.#subscribers.delete(channel)}}publish(event,entryId){if(!this.#subscribers.size)return;const output=Object.freeze({...event,entryId});for(const channel of[...this.#subscribers])this.#subscribers.has(channel)&&(channel.publish(output),channel.failure&&this.#subscribers.delete(channel))}}export{RunnerOutputSubscriptions};
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type InvocationControls } from '@weiliang0121/capix-invocation';
|
|
2
|
+
import type { CallableHookBinding } from './binding/hooks.js';
|
|
3
|
+
import { type InvocationCapabilities } from './construction/capabilities.js';
|
|
4
|
+
import type { CallableInput, CallableOutput, CallableDelta, Stable } from '@weiliang0121/capix-contracts';
|
|
5
|
+
import type { CheckpointStore } from '@weiliang0121/capix-checkpoint';
|
|
6
|
+
import { Resources } from './resource/resources.js';
|
|
7
|
+
import { Interactions } from '@weiliang0121/capix-interaction';
|
|
8
|
+
import type { AnyCallable } from './binding/declarations.js';
|
|
9
|
+
import { type RunnerOutput } from './runner/output.js';
|
|
10
|
+
import { type RunnerObservation } from './runner/observation.js';
|
|
11
|
+
export type { RunnerOutput, RunnerOutputEvent } from './runner/output.js';
|
|
12
|
+
export type { RunnerObservation, RunnerObservationReceiver } from './runner/observation.js';
|
|
13
|
+
export type * from './runner/observation-contract.js';
|
|
14
|
+
export interface RunnerOptions<Options extends object = {}> extends InvocationCapabilities {
|
|
15
|
+
readonly hooks?: readonly CallableHookBinding<Options>[];
|
|
16
|
+
readonly validate?: (options: Options) => undefined;
|
|
17
|
+
}
|
|
18
|
+
export type RunnerArguments<Options extends object> = {} extends Options ? [options?: Options & InvocationControls] : [options: Options & InvocationControls];
|
|
19
|
+
export declare class Runner<Structure extends Extract<AnyCallable, {
|
|
20
|
+
readonly kind: 'scene';
|
|
21
|
+
}>, Options extends object = {}> {
|
|
22
|
+
#private;
|
|
23
|
+
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
|
24
|
+
constructor(scene: Structure, resources: Resources<Options>, interactions?: Interactions, options?: RunnerOptions<NoInfer<Options>>);
|
|
25
|
+
get scene(): Structure;
|
|
26
|
+
get checkpointStore(): CheckpointStore | undefined;
|
|
27
|
+
get isRunning(): boolean;
|
|
28
|
+
get output(): RunnerOutput<CallableOutput<Structure>, CallableDelta<Structure>>;
|
|
29
|
+
get observation(): RunnerObservation;
|
|
30
|
+
cancel(reason?: unknown): boolean;
|
|
31
|
+
build(): this;
|
|
32
|
+
run(input: NoInfer<CallableInput<Structure> | Stable<CallableInput<Structure>>>, ...args: RunnerArguments<Options>): Promise<Stable<CallableOutput<Structure>>>;
|
|
33
|
+
resume(contextId: string, ...args: RunnerArguments<Options>): Promise<Stable<CallableOutput<Structure>>>;
|
|
34
|
+
private perform;
|
|
35
|
+
private snapshotOptions;
|
|
36
|
+
private publish;
|
|
37
|
+
}
|
package/dist/runner.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{randomUUID}from"node:crypto";import{isUndefined}from"es-toolkit/predicate";import{Clock,isInvocationCancelled}from"@weiliang0121/capix-invocation";import{bindDriverObservation}from"./binding/observation.js";import{CallableBuilder}from"./structure/builder.js";import{runEntry}from"./entry.js";import{snapshotInvocationCapabilities}from"./construction/capabilities.js";import{Scene}from"@weiliang0121/capix-structure";import{Resources}from"./resource/resources.js";import{Interactions}from"@weiliang0121/capix-interaction";import{RunnerOutputSubscriptions}from"./runner/output.js";import{RunnerCancellation}from"./runner/cancellation.js";import{RunnerObservationSubscriptions}from"./runner/observation.js";import{RunnerEntryFeedback}from"./runner/feedback.js";class Runner{static{__name(this,"Runner")}id=randomUUID();#scene;#resources;#interactions;#options;#builder;#clock;#checkpoints;#observation;#built;#building=!1;#entry={running:!1};#outputs=new RunnerOutputSubscriptions;#observations=new RunnerObservationSubscriptions;#cancellation;#sequence=0;constructor(scene,resources,interactions,options={}){if(!(scene instanceof Scene))throw new TypeError("Runner requires a Scene");if(!(resources instanceof Resources))throw new TypeError("Runner requires Resources");if(interactions!==void 0&&!(interactions instanceof Interactions))throw new TypeError("Runner interactions must be an Interactions instance");this.#scene=scene,this.#resources=resources,this.#interactions=interactions,this.#options=Object.freeze({hooks:options.hooks?Object.freeze([...options.hooks]):void 0,validate:options.validate?.bind(options)}),this.#clock=options.clock??new Clock;const capabilities=snapshotInvocationCapabilities({...options,clock:this.#clock});this.#checkpoints=capabilities.checkpoints,this.#builder=new CallableBuilder(capabilities),this.#observation=bindDriverObservation(this.id,capabilities.observations),this.publish({kind:"established"})}get scene(){return this.#scene}get checkpointStore(){return this.#checkpoints?.store}get isRunning(){return this.#entry.running}get output(){return this.#outputs.port}get observation(){return this.#observations.port}cancel(reason){return this.#entry.running?this.#cancellation?.cancel(reason)??!1:!1}build(){if(this.#built)throw new Error("Runner has already been built");if(this.#building)throw new Error("Runner build is already in progress");this.#building=!0;try{return this.#built=this.#builder.build(this.#scene,this.#resources,this.#interactions,this.#options),this}finally{this.#building=!1}}run(input,...args){return this.perform({input},args[0]??{})}resume(contextId,...args){return this.perform({contextId},args[0]??{})}async perform(request,options){const feedback=new RunnerEntryFeedback(this.id,this.#observations,this.#clock),mode="contextId"in request?"resume":"run",requestedContextId="contextId"in request?request.contextId:void 0;let requested=!1,cancellation,externalSignal;try{const fixedOptions=this.snapshotOptions(options);requested=!0,feedback.requested(mode,requestedContextId);const structure=this.#built;if(!structure)throw new Error("Runner must be built before running");let result;return this.#entry.running?result=await runEntry(this.#entry,structure,request,fixedOptions,change=>this.publish(change,feedback)):(externalSignal=fixedOptions.signal,cancellation=new RunnerCancellation(externalSignal),this.#cancellation=cancellation,result=await runEntry(this.#entry,structure,request,fixedOptions,change=>this.publish(change,feedback),{signal:cancellation.signal,output:this.#outputs.forEntry(feedback.id),feedback:feedback.receivers(cancellation.signal),created:feedback.created})),feedback.settled("succeeded"),result}catch(error){requested||feedback.requested(mode,requestedContextId);const delivered=cancellation?cancellation.deliveryError(error):error,cancelled=cancellation&&(isInvocationCancelled(delivered,cancellation.signal)||externalSignal&&isInvocationCancelled(delivered,externalSignal));throw feedback.settled(cancelled?"cancelled":"failed",delivered),delivered}finally{cancellation?.dispose(),this.#cancellation===cancellation&&(this.#cancellation=void 0)}}snapshotOptions(options){return Object.freeze({...options})}publish(change,feedback){feedback?.entry(change);const fault=this.#observation.publish(Object.freeze({...change,driverId:this.id,sequence:++this.#sequence,occurredAt:this.#clock.now()}));if(!isUndefined(fault))throw fault}}export{Runner};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Resources } from '../resource/resources.js';
|
|
2
|
+
import type { CallableCallsOptions } from '../binding/calls.js';
|
|
3
|
+
import type { Interactions } from '@weiliang0121/capix-interaction';
|
|
4
|
+
import type { AnyCallable } from '../binding/declarations.js';
|
|
5
|
+
import { type InvocationCapabilities } from '../construction/capabilities.js';
|
|
6
|
+
import type { BuiltCallable } from './construction.js';
|
|
7
|
+
export declare class CallableBuilder {
|
|
8
|
+
private readonly binder;
|
|
9
|
+
private readonly capabilities;
|
|
10
|
+
constructor(capabilities?: InvocationCapabilities);
|
|
11
|
+
build<Structure extends AnyCallable, Options extends object>(structure: Structure, resources: Resources<Options>, interactions?: Interactions, options?: CallableCallsOptions<Options>): BuiltCallable<Structure, Options>;
|
|
12
|
+
}
|
|
@@ -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{CallableBinder}from"../binding/callable.js";import{snapshotInvocationCapabilities}from"../construction/capabilities.js";import{installCallable}from"./install.js";class CallableBuilder{static{__name(this,"CallableBuilder")}binder;capabilities;constructor(capabilities={}){this.capabilities=snapshotInvocationCapabilities(capabilities),this.binder=new CallableBinder(this.capabilities)}build(structure,resources,interactions,options={}){return installCallable(structure,this.capabilities,()=>this.binder.bind(structure,resources,interactions,options))}}export{CallableBuilder};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AnyCallable } from '../binding/declarations.js';
|
|
2
|
+
import type { CallableBinding } from '../binding/contract.js';
|
|
3
|
+
import type { CallInstallation } from '../binding/calls.js';
|
|
4
|
+
import type { CallableInvocationBuilder } from '../construction/invocation.js';
|
|
5
|
+
declare const builtOptions: unique symbol;
|
|
6
|
+
export type BuiltCallable<Structure extends AnyCallable, Options = unknown> = Structure & {
|
|
7
|
+
readonly [builtOptions]: (options: Options) => Options;
|
|
8
|
+
};
|
|
9
|
+
export type AnyBuiltCallable = AnyCallable & {
|
|
10
|
+
readonly [builtOptions]: (options: never) => unknown;
|
|
11
|
+
};
|
|
12
|
+
export type BuiltOptions<Structure> = Structure extends {
|
|
13
|
+
readonly [builtOptions]: (options: infer Options) => unknown;
|
|
14
|
+
} ? Options : never;
|
|
15
|
+
export interface CallableConstruction {
|
|
16
|
+
readonly binding: CallableBinding<any, any, object>;
|
|
17
|
+
readonly calls: CallInstallation<any>;
|
|
18
|
+
readonly invocations: CallableInvocationBuilder;
|
|
19
|
+
}
|
|
20
|
+
export declare function callableConstruction(structure: AnyCallable): CallableConstruction;
|
|
21
|
+
export declare function installCallableConstruction(structure: AnyCallable, value: CallableConstruction): void;
|
|
22
|
+
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});const construction=Symbol("callable-construction");function callableConstruction(structure){if(!Object.hasOwn(structure,construction))throw new Error("Callable structure has not been built");return structure[construction]}__name(callableConstruction,"callableConstruction");function installCallableConstruction(structure,value){Object.defineProperty(structure,construction,{value:Object.freeze(value)})}__name(installCallableConstruction,"installCallableConstruction");export{callableConstruction,installCallableConstruction};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AnyCallable } from '../binding/declarations.js';
|
|
2
|
+
import { type BuiltCallable } from './construction.js';
|
|
3
|
+
import type { CallableBuildPlan } from '../binding/callable.js';
|
|
4
|
+
import type { InvocationCapabilities } from '../construction/capabilities.js';
|
|
5
|
+
export declare function installCallable<Structure extends AnyCallable, Options>(structure: Structure, capabilities: InvocationCapabilities, resolve: () => CallableBuildPlan<Structure, Options>): BuiltCallable<Structure, Options>;
|
|
@@ -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{types}from"node:util";import{BoundChildren}from"../binding/children/bound.js";import{InvocationWorkBinding}from"../binding/work.js";import{Callable}from"@weiliang0121/capix-structure";import{CallableInvocationBuilder}from"../construction/invocation.js";import{assertStructureConfigurable,beginStructureBuild,endStructureBuild,lockStructureConfiguration,structureParent}from"@weiliang0121/capix-structure/construction";import{installCallableConstruction}from"./construction.js";function installCallable(structure,capabilities,resolve){const tree=checkTree(structure),reserved=new Set(tree),original=tree.map(structure2=>({structure:structure2,descriptors:Object.getOwnPropertyDescriptors(structure2)}));for(const current of tree)beginStructureBuild(current);try{const{root,calls}=resolve(),invocations=new CallableInvocationBuilder(capabilities),prepared=[],prepare=__name(node=>{if(!reserved.delete(node.definition))throw new Error("Callable membership changed while building");for(const member of node.members)if(structureParent(member.definition)!==node.definition)throw new Error("Callable membership changed while building");const children=new BoundChildren(node.members,node.declaration.names),composite=node.declaration.members!==void 0,work=new InvocationWorkBinding(node.declaration,children,composite),binding=Object.freeze({definition:node.definition,declaration:node.declaration,observations:node.observations,children,composite,deps:node.deps,supply:node.supply,refinements:node.refinements,work}),fields={};for(const[key,value]of Object.entries(node.declaration)){if(key==="kind"||key==="members"||key==="names")continue;const existing=Object.getOwnPropertyDescriptor(node.definition,key);if(existing&&!existing.configurable)throw new Error(`Callable configuration field cannot be fixed: ${key}`);fields[key]={value,enumerable:!0,writable:!1,configurable:!1}}for(const key of["id","kind",...composite?["members","names"]:[]]){const existing=Object.getOwnPropertyDescriptor(node.definition,key),value=key==="id"?node.definition.id:key==="kind"?node.declaration.kind:key==="members"?node.declaration.members:node.declaration.names,fixed=existing&&"value"in existing&&!existing.writable&&existing.value===value;if(existing&&!existing.configurable&&!fixed)throw new Error(`Callable structure field cannot be fixed: ${key}`);(!existing||existing.configurable)&&(fields[key]={value,enumerable:!0,writable:!1,configurable:!1})}prepared.push({structure:node.definition,construction:{binding,calls,invocations},fields});for(const member of node.members)prepare(member)},"prepare");if(prepare(root),reserved.size)throw new Error("Callable membership changed while building");for(const{structure:structure2,descriptors}of original){if(!Object.isExtensible(structure2))throw new Error("Callable structure changed while building");for(const key of configurationFields){const before=descriptors[key],after=Object.getOwnPropertyDescriptor(structure2,key);if(!sameDescriptor(before,after))throw new Error(`Callable configuration changed while building: ${key}`)}}for(const item of prepared)Object.defineProperties(item.structure,item.fields),installCallableConstruction(item.structure,item.construction),lockStructureConfiguration(item.structure);return structure}finally{for(const current of tree)endStructureBuild(current)}}__name(installCallable,"installCallable");function checkTree(root){const seen=new Set,visit=__name((structure,parent)=>{if(types.isProxy(structure))throw new TypeError("Callable structures cannot be proxies");if(!(structure instanceof Callable))throw new TypeError("Callable structure must be a Scene, Group or Node");if(assertStructureConfigurable(structure),!Object.isExtensible(structure))throw new Error("Callable structure must allow construction before build");if(structureParent(structure)!==parent)throw new Error("Callable structure has another parent or unregistered membership");if(seen.has(structure))throw new Error("Callable structure occurs more than once");if(seen.add(structure),structure.kind!=="node"){if(!structure.members)throw new TypeError("Composite structures must provide their members");for(const member of structure.members)visit(member,structure)}},"visit");return visit(root),[...seen]}__name(checkTree,"checkTree");const configurationFields=["id","kind","members","names","name","label","source","output","deps","run","checkpoint"];function sameDescriptor(before,after){return!before||!after?before===after:before.value===after.value&&before.get===after.get&&before.set===after.set&&before.writable===after.writable&&before.enumerable===after.enumerable&&before.configurable===after.configurable}__name(sameDescriptor,"sameDescriptor");export{installCallable};
|
package/package.json
CHANGED
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weiliang0121/capix-runtime",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./construction": {
|
|
12
|
+
"types": "./dist/construction.d.ts",
|
|
13
|
+
"import": "./dist/construction.js"
|
|
14
|
+
},
|
|
15
|
+
"./recording": {
|
|
16
|
+
"types": "./dist/recording.d.ts",
|
|
17
|
+
"import": "./dist/recording.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"es-toolkit": "1.52.0",
|
|
22
|
+
"@weiliang0121/capix-protocol": "0.1.0",
|
|
23
|
+
"@weiliang0121/capix-structure": "0.1.0",
|
|
24
|
+
"@weiliang0121/capix-resources": "0.1.0",
|
|
25
|
+
"@weiliang0121/capix-changes": "0.1.0",
|
|
26
|
+
"@weiliang0121/capix-contracts": "0.1.0",
|
|
27
|
+
"@weiliang0121/capix-records": "0.1.0",
|
|
28
|
+
"@weiliang0121/capix-checkpoint": "0.1.0",
|
|
29
|
+
"@weiliang0121/capix-invocation": "0.1.0",
|
|
30
|
+
"@weiliang0121/capix-diagnostics": "0.1.0",
|
|
31
|
+
"@weiliang0121/capix-interaction": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"description": "Structure binding, resource assembly, and Runner for CAPiX.",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"author": "wei.liang (https://github.com/weiliang0121)",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/weiliang0121/capix.git",
|
|
39
|
+
"directory": "server/runtime"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=22.23.2"
|
|
43
|
+
},
|
|
44
|
+
"main": "./dist/index.js",
|
|
45
|
+
"types": "./dist/index.d.ts",
|
|
46
|
+
"files": [
|
|
47
|
+
"dist/**/*.js",
|
|
48
|
+
"dist/**/*.d.ts",
|
|
49
|
+
"LICENSE",
|
|
50
|
+
"README.md"
|
|
51
|
+
],
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public",
|
|
54
|
+
"registry": "https://registry.npmjs.org"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc -p tsconfig.json",
|
|
58
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
59
|
+
}
|
|
6
60
|
}
|