liminal 0.5.4 → 0.5.6

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.
Files changed (117) hide show
  1. package/Agent.ts +24 -16
  2. package/CHANGELOG.md +12 -0
  3. package/Context.ts +52 -0
  4. package/EventBase.ts +21 -8
  5. package/Fiber.ts +44 -57
  6. package/Handler.ts +6 -0
  7. package/L/L.ts +0 -3
  8. package/L/_infer.ts +14 -21
  9. package/L/_message.ts +6 -4
  10. package/L/branch.ts +15 -33
  11. package/L/emit.ts +10 -2
  12. package/L/model.ts +11 -6
  13. package/L/rune.ts +2 -2
  14. package/LEvent.ts +25 -21
  15. package/MessageRegistry.ts +21 -0
  16. package/{state/ModelRegistry.ts → ModelRegistry.ts} +17 -18
  17. package/Rune.ts +2 -2
  18. package/Runic.ts +11 -3
  19. package/RuntimeEvent.ts +6 -0
  20. package/dist/Agent.d.ts +11 -7
  21. package/dist/Agent.js +11 -8
  22. package/dist/Agent.js.map +1 -1
  23. package/dist/Context.d.ts +12 -0
  24. package/dist/Context.js +41 -0
  25. package/dist/Context.js.map +1 -0
  26. package/dist/EventBase.d.ts +7 -4
  27. package/dist/EventBase.js +17 -11
  28. package/dist/EventBase.js.map +1 -1
  29. package/dist/Fiber.d.ts +7 -19
  30. package/dist/Fiber.js +38 -34
  31. package/dist/Fiber.js.map +1 -1
  32. package/dist/Handler.d.ts +4 -1
  33. package/dist/Handler.js +2 -1
  34. package/dist/Handler.js.map +1 -1
  35. package/dist/L/L.d.ts +0 -3
  36. package/dist/L/L.js +0 -3
  37. package/dist/L/L.js.map +1 -1
  38. package/dist/L/_infer.js +15 -18
  39. package/dist/L/_infer.js.map +1 -1
  40. package/dist/L/_message.js +6 -4
  41. package/dist/L/_message.js.map +1 -1
  42. package/dist/L/branch.js +13 -32
  43. package/dist/L/branch.js.map +1 -1
  44. package/dist/L/emit.js +10 -2
  45. package/dist/L/emit.js.map +1 -1
  46. package/dist/L/model.d.ts +2 -1
  47. package/dist/L/model.js +10 -5
  48. package/dist/L/model.js.map +1 -1
  49. package/dist/L/rune.d.ts +2 -2
  50. package/dist/L/rune.js +1 -0
  51. package/dist/L/rune.js.map +1 -1
  52. package/dist/LEvent.d.ts +55 -10
  53. package/dist/LEvent.js +17 -16
  54. package/dist/LEvent.js.map +1 -1
  55. package/dist/MessageRegistry.d.ts +9 -0
  56. package/dist/MessageRegistry.js +15 -0
  57. package/dist/MessageRegistry.js.map +1 -0
  58. package/dist/{state/ModelRegistry.d.ts → ModelRegistry.d.ts} +4 -3
  59. package/dist/{state/ModelRegistry.js → ModelRegistry.js} +12 -13
  60. package/dist/ModelRegistry.js.map +1 -0
  61. package/dist/Rune.d.ts +2 -2
  62. package/dist/Runic.d.ts +3 -3
  63. package/dist/Runic.js.map +1 -1
  64. package/dist/RuntimeEvent.d.ts +5 -0
  65. package/dist/RuntimeEvent.js +2 -0
  66. package/dist/RuntimeEvent.js.map +1 -0
  67. package/dist/index.d.ts +3 -4
  68. package/dist/index.js +3 -4
  69. package/dist/index.js.map +1 -1
  70. package/dist/tsconfig.tsbuildinfo +1 -1
  71. package/index.ts +3 -4
  72. package/package.json +1 -1
  73. package/Globals.ts +0 -10
  74. package/L/all.ts +0 -11
  75. package/L/fork.ts +0 -20
  76. package/L/join.ts +0 -9
  77. package/L/namespace.ts +0 -11
  78. package/L/self.ts +0 -13
  79. package/dist/Globals.d.ts +0 -6
  80. package/dist/Globals.js +0 -2
  81. package/dist/Globals.js.map +0 -1
  82. package/dist/L/all.d.ts +0 -7
  83. package/dist/L/all.js +0 -5
  84. package/dist/L/all.js.map +0 -1
  85. package/dist/L/fork.d.ts +0 -1
  86. package/dist/L/fork.js +0 -20
  87. package/dist/L/fork.js.map +0 -1
  88. package/dist/L/join.d.ts +0 -5
  89. package/dist/L/join.js +0 -5
  90. package/dist/L/join.js.map +0 -1
  91. package/dist/L/namespace.d.ts +0 -1
  92. package/dist/L/namespace.js +0 -12
  93. package/dist/L/namespace.js.map +0 -1
  94. package/dist/L/self.d.ts +0 -6
  95. package/dist/L/self.js +0 -7
  96. package/dist/L/self.js.map +0 -1
  97. package/dist/run.d.ts +0 -3
  98. package/dist/run.js +0 -35
  99. package/dist/run.js.map +0 -1
  100. package/dist/state/Context.d.ts +0 -8
  101. package/dist/state/Context.js +0 -17
  102. package/dist/state/Context.js.map +0 -1
  103. package/dist/state/MessageRegistry.d.ts +0 -8
  104. package/dist/state/MessageRegistry.js +0 -17
  105. package/dist/state/MessageRegistry.js.map +0 -1
  106. package/dist/state/ModelConfig.d.ts +0 -49
  107. package/dist/state/ModelConfig.js +0 -18
  108. package/dist/state/ModelConfig.js.map +0 -1
  109. package/dist/state/ModelRegistry.js.map +0 -1
  110. package/dist/state/StateMap.d.ts +0 -8
  111. package/dist/state/StateMap.js +0 -18
  112. package/dist/state/StateMap.js.map +0 -1
  113. package/run.ts +0 -39
  114. package/state/Context.ts +0 -19
  115. package/state/MessageRegistry.ts +0 -21
  116. package/state/ModelConfig.ts +0 -49
  117. package/state/StateMap.ts +0 -24
package/Agent.ts CHANGED
@@ -1,28 +1,36 @@
1
- import type { FiberConfig, FiberInfo } from "./Fiber.ts"
2
- import { run } from "./run.ts"
3
- import type { Rune, RuneKey } from "./Rune.ts"
1
+ import { Context } from "./Context.ts"
2
+ import { Fiber } from "./Fiber.ts"
3
+ import { HandlerContext } from "./Handler.ts"
4
+ import { MessageRegistry, MessageRegistryContext } from "./MessageRegistry.ts"
5
+ import { ModelRegistry, ModelRegistryContext } from "./ModelRegistry.ts"
6
+ import type { Rune } from "./Rune.ts"
4
7
  import type { Runic } from "./Runic.ts"
8
+ import type { RuntimeEvent } from "./RuntimeEvent.ts"
9
+
10
+ export interface AgentConfig<E> {
11
+ handler?: ((event: RuntimeEvent<E>) => void) | undefined
12
+ models?: ModelRegistry
13
+ messages?: MessageRegistry
14
+ signal?: AbortSignal | undefined
15
+ }
5
16
 
6
17
  export interface Agent<out T, out E> extends PromiseLike<T> {
7
18
  T: T
8
19
  E: E
9
20
  }
10
21
 
11
- export function Agent<Y extends Rune, T>(runic: Runic<Y, T>, config?: AgentConfig<Y, T>): Agent<T, Rune.E<Y>> {
22
+ export function Agent<Y extends Rune, T>(
23
+ runic: Runic<Y, T>,
24
+ config?: AgentConfig<Rune.E<Y>>,
25
+ ): Agent<T, Rune.E<Y>> {
12
26
  return {
13
27
  then(onfulfilled, onrejected) {
14
- return run(runic, {
15
- T: null!,
16
- globals: {
17
- handler: config?.handler ?? (() => {}),
18
- },
19
- signal: config?.signal,
20
- }).then(onfulfilled, onrejected)
28
+ const rootCtx = new Context([
29
+ [HandlerContext, config?.handler],
30
+ [ModelRegistryContext, config?.models ?? new ModelRegistry()],
31
+ [MessageRegistryContext, config?.messages ?? new MessageRegistry()],
32
+ ])
33
+ return rootCtx.run(() => Fiber(runic).resolve().then(onfulfilled, onrejected))
21
34
  },
22
35
  } satisfies Omit<Agent<T, Rune.E<Y>>, "E" | "T"> as never
23
36
  }
24
-
25
- export interface AgentConfig<Y extends Rune, _T> {
26
- handler: (event: Y[RuneKey], info: FiberInfo) => void
27
- signal?: AbortSignal
28
- }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # liminal
2
2
 
3
+ ## 0.5.6
4
+
5
+ ### Patch Changes
6
+
7
+ - f79205e: Include fiber information in the event type supplied to user-specified handlers. Continue reworking runtime implementation.
8
+
9
+ ## 0.5.5
10
+
11
+ ### Patch Changes
12
+
13
+ - 43afd27: Fixing misc. bugs and refactoring context management.
14
+
3
15
  ## 0.5.4
4
16
 
5
17
  ### Patch Changes
package/Context.ts ADDED
@@ -0,0 +1,52 @@
1
+ import { assert } from "liminal-util"
2
+ import { AsyncLocalStorage } from "node:async_hooks"
3
+
4
+ const storage = new AsyncLocalStorage<Context>()
5
+
6
+ export class Context extends Map<ContextHandle, unknown> {
7
+ static ensure(): Context {
8
+ const context = storage.getStore()
9
+ assert(context)
10
+ return context
11
+ }
12
+
13
+ get<V>(context: ContextHandle<V>): V | undefined {
14
+ return super.get(context) as never
15
+ }
16
+
17
+ getOrInit<V>(context: ContextHandle<V>, init: () => V): V {
18
+ if (this.has(context)) {
19
+ return this.get(context) as V
20
+ }
21
+ const instance = init()
22
+ this.set(context, instance)
23
+ return instance
24
+ }
25
+
26
+ set<V>(context: ContextHandle<V>, value: V): this {
27
+ super.set(context, value)
28
+ return this
29
+ }
30
+
31
+ run<R>(callback: () => R): R {
32
+ return storage.run(this, callback)
33
+ }
34
+
35
+ clone(overrides?: Iterable<[ContextHandle, unknown]>): Context {
36
+ const context = new Context(overrides)
37
+ for (const [handle, value] of this.entries()) {
38
+ if (!context.has(handle)) {
39
+ context.set(handle, handle.clone?.(value) ?? value)
40
+ }
41
+ }
42
+ return context
43
+ }
44
+ }
45
+
46
+ export type ContextHandle<V = any> = {
47
+ clone?: ((value: V) => V) | undefined
48
+ }
49
+
50
+ export function ContextHandle<V>(clone?: (value: V) => V): ContextHandle<V> {
51
+ return { clone }
52
+ }
package/EventBase.ts CHANGED
@@ -1,13 +1,26 @@
1
1
  import { inspect, type InspectOptions } from "node:util"
2
2
 
3
- export abstract class EventBase<B extends symbol, K extends string> {
4
- constructor(
5
- readonly brand: B,
6
- readonly type: K,
7
- ) {}
3
+ export interface EventBase<B extends symbol = symbol, K extends string = string> {
4
+ readonly brand: B
5
+ readonly type: K
6
+ }
7
+
8
+ export function EventBase<B extends symbol, K extends string>(brand: B, type: K) {
9
+ return class implements EventBase<B, K> {
10
+ readonly brand = brand
11
+ readonly type = type
8
12
 
9
- [inspect.custom](depth: number, options: InspectOptions) {
10
- const { brand: _0, type: _1, ...rest } = this
11
- return `${this.constructor.name} ` + inspect(rest, { ...options, depth })
13
+ // Allows us to circumvent a false positive ts error related to private symbols.
14
+ // https://github.com/microsoft/TypeScript/issues/58496
15
+ static {
16
+ Object.defineProperties(this.prototype, {
17
+ [inspect.custom]: {
18
+ value(depth: number, options: InspectOptions) {
19
+ const { brand: _0, type: _1, ...rest } = this
20
+ return `${this.constructor.name} ` + inspect(rest, { ...options, depth })
21
+ },
22
+ },
23
+ })
24
+ }
12
25
  }
13
26
  }
package/Fiber.ts CHANGED
@@ -1,67 +1,54 @@
1
- import { assert } from "liminal-util"
2
- import type { Globals } from "./Globals.ts"
3
- import { FiberCreated, FiberResolved, FiberStarted } from "./LEvent.ts"
1
+ import { Context } from "./Context.ts"
4
2
  import type { Rune } from "./Rune.ts"
5
3
  import { Runic } from "./Runic.ts"
6
- import type { StateMap } from "./state/StateMap.ts"
7
-
8
- export interface Fiber<out T = any> {
9
- T: T
10
- runic: Runic<Rune, T>
11
- globals: Globals
12
- parent: Fiber<any> | undefined
13
- fiberId: number
14
- handler<E>(event: E): void
15
- run(): Promise<T>
16
- }
17
4
 
18
5
  export interface FiberInfo {
19
- fiber: number
20
- timestamp: number
6
+ readonly index: number
7
+ readonly parent?: FiberInfo
21
8
  }
22
9
 
23
- let nextFiberId = 0
10
+ let nextIndex = 0
24
11
 
25
- export interface FiberConfig<T = any> {
26
- T: T
27
- signal?: AbortSignal | undefined
28
- globals: Globals
29
- state?: StateMap | undefined
12
+ export interface Fiber<T = any> {
13
+ parent?: Fiber | undefined
14
+ info: FiberInfo
15
+ resolve(): Promise<T>
30
16
  }
31
17
 
32
- export function handler<E>(fiberConfig: FiberConfig, event: E): void {
33
- fiberConfig.globals.handler(event, {
34
- // fiber: fiberConfig.fiberId,
35
- timestamp: Date.now(),
36
- })
18
+ export function Fiber<T = any>(runic: Runic<Rune, T>, parent?: Fiber): Fiber<T> {
19
+ let index = nextIndex++
20
+ let pending: Promise<T> | undefined
21
+ const context = Context.ensure()
22
+ return {
23
+ parent,
24
+ info: {
25
+ index,
26
+ ...parent && { parent: parent.info },
27
+ },
28
+ resolve,
29
+ }
30
+
31
+ function resolve(this: Fiber<T>): Promise<T> {
32
+ if (!pending) {
33
+ const { promise, resolve, reject } = Promise.withResolvers<T>()
34
+ pending = promise
35
+ const iterator = Runic.unwrap(runic)
36
+ let nextArg: unknown
37
+ context.run(async () => {
38
+ try {
39
+ let current = await iterator.next()
40
+ while (!current.done) {
41
+ const rune = current.value
42
+ nextArg = await rune(this)
43
+ current = await iterator.next(nextArg)
44
+ }
45
+ const { value } = current
46
+ resolve(value)
47
+ } catch (error) {
48
+ reject(error)
49
+ }
50
+ })
51
+ }
52
+ return pending
53
+ }
37
54
  }
38
-
39
- // export interface FiberConfig<T> {
40
- // parent?: Fiber<any>
41
- // globals: Globals
42
- // runic: Runic<Rune, T>
43
- // signal?: AbortSignal | undefined
44
- // }
45
-
46
- // export function Fiber<T>(config: FiberConfig<T>): Fiber<T> {
47
- // const fiber = {
48
- // runic: config.runic,
49
- // globals: config.globals,
50
- // parent: config.parent,
51
- // fiberId: nextFiberId++,
52
- // handler,
53
- // run,
54
- // } satisfies Omit<Fiber<T>, "T"> as Fiber<T>
55
-
56
- // fiber.handler(new FiberCreated())
57
- // return fiber
58
-
59
- // async function run(this: Fiber<T>): Promise<T> {
60
- // fiber.handler(new FiberStarted())
61
- // const iterator = Runic.unwrap(this.runic)
62
- // const result = await iterator.next()
63
- // assert(result.done)
64
- // fiber.handler(new FiberResolved(result.value))
65
- // return result.value
66
- // }
67
- // }
package/Handler.ts CHANGED
@@ -0,0 +1,6 @@
1
+ import { ContextHandle } from "./Context.ts"
2
+ import type { RuntimeEvent } from "./RuntimeEvent.ts"
3
+
4
+ export type Handler<E = any> = [(event: RuntimeEvent<E>) => void][0]
5
+
6
+ export const HandlerContext: ContextHandle<Handler | undefined> = ContextHandle()
package/L/L.ts CHANGED
@@ -4,9 +4,6 @@ export * from "./_message.ts"
4
4
  export * from "./assistant.ts"
5
5
  export * from "./branch.ts"
6
6
  export * from "./emit.ts"
7
- export * from "./fork.ts"
8
- export * from "./join.ts"
9
7
  export * from "./model.ts"
10
- export * from "./self.ts"
11
8
  export * from "./system.ts"
12
9
  export * from "./user.ts"
package/L/_infer.ts CHANGED
@@ -1,40 +1,33 @@
1
1
  import type { SchemaObject } from "liminal-schema"
2
2
  import { assert } from "liminal-util"
3
+ import { Context, ContextHandle } from "../Context.ts"
3
4
  import { InferenceRequested, Inferred, type LEvent } from "../LEvent.ts"
5
+ import { MessageRegistryContext } from "../MessageRegistry.ts"
6
+ import { ModelRegistryContext } from "../ModelRegistry.ts"
4
7
  import type { Rune } from "../Rune.ts"
5
- import { context } from "../state/Context.ts"
6
- import { MessageRegistry } from "../state/MessageRegistry.ts"
7
- import { ModelRegistry } from "../state/ModelRegistry.ts"
8
8
  import { emit } from "./emit.ts"
9
9
  import { rune } from "./rune.ts"
10
10
 
11
11
  export function* _infer(schema?: SchemaObject): Generator<Rune<LEvent>, string> {
12
- const state = context.get()
13
- const modelRegistry = state.getOrInit(ModelRegistry.make)
12
+ const context = Context.ensure()
13
+ const modelRegistry = context.get(ModelRegistryContext)
14
+ assert(modelRegistry)
14
15
  const model = modelRegistry.peek()
15
- const messageRegistry = state.getOrInit(MessageRegistry.make)
16
- const counter = state.getOrInit(InferenceRequestCounter)
17
16
  assert(model)
18
- const requestId = counter.next()
17
+ const requestId = context.getOrInit(InferenceRequestCounterContext, () => new InferenceRequestCounter()).next()
19
18
  yield* emit(new InferenceRequested(requestId, schema))
19
+ const messageRegistry = context.get(MessageRegistryContext)
20
+ assert(messageRegistry)
20
21
  const inference = yield* rune(() => model.resolve(messageRegistry.messages, schema))
21
22
  yield* emit(new Inferred(requestId, inference))
22
23
  return inference
23
24
  }
24
25
 
25
- function InferenceRequestCounter(instance?: Counter) {
26
- return {
27
- count: instance?.count ?? 0,
28
- next() {
29
- return this.count++
30
- },
31
- clone() {
32
- return InferenceRequestCounter(this)
33
- },
26
+ class InferenceRequestCounter {
27
+ count: number = 0
28
+ next(): number {
29
+ return this.count++
34
30
  }
35
31
  }
36
32
 
37
- interface Counter {
38
- count: number
39
- next(): number
40
- }
33
+ const InferenceRequestCounterContext: ContextHandle<InferenceRequestCounter> = ContextHandle()
package/L/_message.ts CHANGED
@@ -1,15 +1,17 @@
1
+ import { assert } from "liminal-util"
2
+ import { Context } from "../Context.ts"
1
3
  import { type LEvent, MessageAppended } from "../LEvent.ts"
2
4
  import type { ContentPart, Message, MessageRole } from "../Message.ts"
5
+ import { MessageRegistryContext } from "../MessageRegistry.ts"
3
6
  import type { Rune } from "../Rune.ts"
4
- import { context } from "../state/Context.ts"
5
- import { MessageRegistry } from "../state/MessageRegistry.ts"
6
7
  import { emit } from "./emit.ts"
7
8
 
8
9
  export interface _message extends Generator<Rune<LEvent>, void> {}
9
10
 
10
11
  export function* _message(role: MessageRole, content: Array<ContentPart>): _message {
11
- const state = context.get()
12
- const messageRegistry = state.getOrInit(MessageRegistry.make)
12
+ const context = Context.ensure()
13
+ const messageRegistry = context.get(MessageRegistryContext)
14
+ assert(messageRegistry)
13
15
  const message: Message = { role, content }
14
16
  yield* emit(new MessageAppended(message))
15
17
  messageRegistry.append(message)
package/L/branch.ts CHANGED
@@ -1,10 +1,8 @@
1
- import type { FiberConfig } from "../Fiber.ts"
2
- import { run } from "../run.ts"
1
+ import { Context } from "../Context.ts"
2
+ import { Fiber } from "../Fiber.ts"
3
3
  import { type Rune } from "../Rune.ts"
4
4
  import type { Runic } from "../Runic.ts"
5
- import { context } from "../state/Context.ts"
6
5
  import { rune } from "./rune.ts"
7
- import { self } from "./self.ts"
8
6
 
9
7
  export interface branch<Y extends Rune, T> extends Generator<Y, T> {}
10
8
 
@@ -16,36 +14,20 @@ export function branch<XR extends Record<keyof any, Runic>>(
16
14
  runics: XR,
17
15
  ): branch<Runic.Y<XR[keyof XR]> | Rune<never>, { [K in keyof XR]: Runic.T<XR[K]> }>
18
16
  export function* branch(value: Runic | Array<Runic> | Record<keyof any, Runic>): branch<Rune, any> {
19
- const parent = yield* self
20
- const { globals } = parent
17
+ const context = Context.ensure()
18
+ const parent = yield* rune((fiber) => fiber)
21
19
  if (Array.isArray(value)) {
22
- const runners = value.map((runic) => {
23
- const state = context.get()
24
- const fiberConfig: FiberConfig = {
25
- T: null!,
26
- globals,
27
- state,
28
- }
29
- return () => run(runic, fiberConfig)
30
- })
31
- return yield* rune(() => Promise.all(runners.map((runner) => runner())))
20
+ const fibers = value.map((runic) => context.clone().run(() => Fiber(runic, parent)))
21
+ return yield* rune(() => Promise.all(fibers.map(({ resolve }) => resolve())))
32
22
  } else if (typeof value === "object") {
33
- const runners = Object.entries(value).map(([key, runic]) => {
34
- const state = context.get()
35
- const fiberConfig: FiberConfig = {
36
- T: null!,
37
- globals,
38
- state,
39
- }
40
- return async () => [key, await run(runic, fiberConfig)]
41
- })
42
- return yield* rune(() => Promise.all(runners.map((runner) => runner())).then(Object.fromEntries))
23
+ const entries = Object.entries(value)
24
+ const fibers = entries.map(([_key, runic]) => context.clone().run(() => Fiber(runic, parent)))
25
+ return yield* rune(() =>
26
+ Promise
27
+ .all(fibers.map(({ resolve }, i) => resolve().then((value) => [entries[i]![0], value])))
28
+ .then(Object.fromEntries)
29
+ )
43
30
  }
44
- const state = context.get()
45
- const fiberConfig: FiberConfig = {
46
- T: null!,
47
- globals,
48
- state,
49
- }
50
- return yield* rune(() => run(typeof value === "function" ? value() : value, fiberConfig))
31
+ const fiber = context.clone().run(() => Fiber(typeof value === "function" ? value() : value, parent))
32
+ return yield* rune(() => fiber.resolve())
51
33
  }
package/L/emit.ts CHANGED
@@ -1,10 +1,18 @@
1
1
  import type { EnsureNarrow } from "liminal-util"
2
- import { handler } from "../Fiber.ts"
2
+ import { Context } from "../Context.ts"
3
+ import { HandlerContext } from "../Handler.ts"
3
4
  import type { Rune } from "../Rune.ts"
4
5
  import { rune } from "./rune.ts"
5
6
 
6
7
  export interface emit<E> extends Generator<Rune<E>, void> {}
7
8
 
8
9
  export function* emit<const E>(event: EnsureNarrow<E>): emit<E> {
9
- yield* rune((fiberConfig) => handler(fiberConfig, event))<E>()
10
+ const context = Context.ensure()
11
+ const handler = context.get(HandlerContext)
12
+ const fiber = yield* rune((fiber) => fiber)
13
+ handler?.({
14
+ ...fiber.info,
15
+ ...fiber.parent && { parent: fiber.parent.info },
16
+ event,
17
+ })
10
18
  }
package/L/model.ts CHANGED
@@ -1,12 +1,17 @@
1
+ import { assert } from "liminal-util"
2
+ import { Context } from "../Context.ts"
3
+ import { ModelRegistered } from "../LEvent.ts"
1
4
  import type { Model } from "../Model.ts"
5
+ import { ModelRegistryContext } from "../ModelRegistry.ts"
2
6
  import type { Rune } from "../Rune.ts"
3
- import { context } from "../state/Context.ts"
4
- import { ModelRegistry } from "../state/ModelRegistry.ts"
7
+ import { emit } from "./emit.ts"
5
8
 
6
- export interface model extends Generator<Rune<never>, void> {}
9
+ export interface model extends Generator<Rune<ModelRegistered>, void> {}
7
10
 
8
11
  export function* model(model: Model): model {
9
- const state = context.get()
10
- const modelRegistry = state.getOrInit(ModelRegistry.make)
11
- modelRegistry.register(model)
12
+ const context = Context.ensure()
13
+ const registry = context.get(ModelRegistryContext)
14
+ assert(registry)
15
+ registry.register(model)
16
+ yield* emit(new ModelRegistered(model))
12
17
  }
package/L/rune.ts CHANGED
@@ -1,11 +1,11 @@
1
- import type { FiberConfig } from "../Fiber.ts"
1
+ import { Fiber } from "../Fiber.ts"
2
2
  import { type Rune, RuneKey } from "../Rune.ts"
3
3
 
4
4
  export interface rune<T> extends Iterable<Rune<never>, T> {
5
5
  <E>(): Generator<Rune<E>, T>
6
6
  }
7
7
 
8
- export function rune<R>(source: (fiberConfig: FiberConfig) => R): rune<Awaited<R>> {
8
+ export function rune<R>(source: (fiber: Fiber) => R): rune<Awaited<R>> {
9
9
  return Object.assign(
10
10
  function*<E>(): Generator<Rune<E>, Awaited<R>> {
11
11
  return yield Object.assign(source, { [RuneKey]: {} as never })
package/LEvent.ts CHANGED
@@ -1,55 +1,59 @@
1
1
  import type { SchemaObject } from "liminal-schema"
2
2
  import { EventBase } from "./EventBase.ts"
3
3
  import type { Message } from "./Message.ts"
4
+ import type { Model } from "./Model.ts"
4
5
 
5
- export type LEvent = InferenceRequested | Inferred | MessageAppended | FiberCreated | FiberStarted | FiberResolved
6
+ export type LEvent =
7
+ | FiberCreated
8
+ | FiberResolved
9
+ | FiberStarted
10
+ | InferenceRequested
11
+ | Inferred
12
+ | MessageAppended
13
+ | ModelRegistered
6
14
 
7
15
  export const LEventTag: unique symbol = Symbol.for("liminal/LEvent")
8
16
  export type LEventTag = typeof LEventTag
9
17
 
10
- export class InferenceRequested extends EventBase<LEventTag, "inference_requested"> {
18
+ export class ModelRegistered extends EventBase(LEventTag, "model_registered") {
19
+ constructor(readonly model: Model) {
20
+ super()
21
+ }
22
+ }
23
+
24
+ export class InferenceRequested extends EventBase(LEventTag, "inference_requested") {
11
25
  declare schema?: SchemaObject
12
26
  constructor(
13
27
  readonly requestId: number,
14
28
  schema?: SchemaObject | undefined,
15
29
  ) {
16
- super(LEventTag, "inference_requested")
30
+ super()
17
31
  if (schema) {
18
32
  this.schema = schema
19
33
  }
20
34
  }
21
35
  }
22
36
 
23
- export class Inferred extends EventBase<LEventTag, "inferred"> {
37
+ export class Inferred extends EventBase(LEventTag, "inferred") {
24
38
  constructor(
25
39
  readonly requestId: number,
26
40
  readonly inference: string,
27
41
  ) {
28
- super(LEventTag, "inferred")
42
+ super()
29
43
  }
30
44
  }
31
45
 
32
- export class MessageAppended extends EventBase<LEventTag, "message_appended"> {
46
+ export class MessageAppended extends EventBase(LEventTag, "message_appended") {
33
47
  constructor(readonly message: Message) {
34
- super(LEventTag, "message_appended")
35
- }
36
- }
37
-
38
- export class FiberCreated extends EventBase<LEventTag, "fiber_created"> {
39
- constructor() {
40
- super(LEventTag, "fiber_created")
41
- }
42
- }
43
-
44
- export class FiberStarted extends EventBase<LEventTag, "fiber_started"> {
45
- constructor() {
46
- super(LEventTag, "fiber_started")
48
+ super()
47
49
  }
48
50
  }
49
51
 
50
- export class FiberResolved extends EventBase<LEventTag, "fiber_resolved"> {
52
+ export class FiberCreated extends EventBase(LEventTag, "fiber_created") {}
53
+ export class FiberStarted extends EventBase(LEventTag, "fiber_started") {}
54
+ export class FiberResolved extends EventBase(LEventTag, "fiber_resolved") {
51
55
  constructor(readonly value: any) {
52
- super(LEventTag, "fiber_resolved")
56
+ super()
53
57
  }
54
58
  }
55
59
 
@@ -0,0 +1,21 @@
1
+ import { ContextHandle } from "./Context.ts"
2
+ import type { Message } from "./Message.ts"
3
+
4
+ export class MessageRegistry {
5
+ messages: Array<Message>
6
+ constructor(messages?: Array<Message>) {
7
+ this.messages = messages ?? []
8
+ }
9
+
10
+ append(message: Message): void {
11
+ this.messages.push(message)
12
+ }
13
+
14
+ clone(): MessageRegistry {
15
+ return new MessageRegistry([...this.messages])
16
+ }
17
+ }
18
+
19
+ export const MessageRegistryContext: ContextHandle<MessageRegistry> = ContextHandle(({ messages }) =>
20
+ new MessageRegistry([...messages])
21
+ )
@@ -1,29 +1,20 @@
1
- import type { Model } from "../Model.ts"
1
+ import { ContextHandle } from "./Context.ts"
2
+ import type { Model } from "./Model.ts"
2
3
 
3
4
  /** An intrusive list for storing `Model`s. */
4
5
  export class ModelRegistry {
5
- static make(modelRegistry?: ModelRegistry) {
6
- const instance = new ModelRegistry()
7
- if (modelRegistry) {
8
- for (let node = modelRegistry.head; node; node = node.next) {
9
- instance.register(node.model)
10
- }
11
- }
12
- return instance
13
- }
14
-
15
6
  declare head?: ModelRegistryNode | undefined
16
7
  declare tail?: ModelRegistryNode | undefined
17
8
 
18
- clone(): ModelRegistry {
19
- const clone = new ModelRegistry()
20
- for (let node = this?.head; node; node = node.next) {
21
- clone.register(node.model)
9
+ constructor(models?: Array<Model>) {
10
+ if (models) {
11
+ for (const model of models) {
12
+ this.register(model)
13
+ }
22
14
  }
23
- return clone
24
15
  }
25
16
 
26
- peek(): Model | undefined {
17
+ peek() {
27
18
  return this.tail?.model
28
19
  }
29
20
 
@@ -41,7 +32,7 @@ export class ModelRegistry {
41
32
  return node
42
33
  }
43
34
 
44
- remove(node: ModelRegistryNode): void {
35
+ remove(node: ModelRegistryNode) {
45
36
  if (node.prev) {
46
37
  node.prev.next = node.next
47
38
  }
@@ -63,3 +54,11 @@ export interface ModelRegistryNode {
63
54
  model: Model
64
55
  next?: ModelRegistryNode | undefined
65
56
  }
57
+
58
+ export const ModelRegistryContext: ContextHandle<ModelRegistry> = ContextHandle(({ head }) => {
59
+ const instance = new ModelRegistry()
60
+ for (let node = head; node; node = node.next) {
61
+ instance.register(node.model)
62
+ }
63
+ return instance
64
+ })
package/Rune.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { FiberConfig } from "./Fiber.ts"
1
+ import type { Fiber } from "./Fiber.ts"
2
2
 
3
3
  export interface Rune<out E = any> {
4
- (fiber: FiberConfig): any
4
+ (fiber: Fiber): any
5
5
  [RuneKey]: E
6
6
  }
7
7