liminal 0.5.5 → 0.5.7

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 (105) hide show
  1. package/Agent.ts +18 -9
  2. package/CHANGELOG.md +14 -0
  3. package/Context.ts +36 -28
  4. package/EventBase.ts +2 -11
  5. package/Fiber.ts +46 -0
  6. package/Handler.ts +6 -0
  7. package/L/L.ts +0 -1
  8. package/L/_infer.ts +14 -20
  9. package/L/_message.ts +5 -2
  10. package/L/branch.ts +10 -18
  11. package/L/emit.ts +6 -8
  12. package/L/model.ts +10 -4
  13. package/L/rune.ts +2 -1
  14. package/LEvent.ts +15 -1
  15. package/MessageRegistry.ts +21 -0
  16. package/{state/ModelRegistry.ts → ModelRegistry.ts} +19 -12
  17. package/Rune.ts +3 -1
  18. package/Runic.ts +11 -3
  19. package/dist/Agent.d.ts +11 -3
  20. package/dist/Agent.js +10 -8
  21. package/dist/Agent.js.map +1 -1
  22. package/dist/Context.d.ts +11 -9
  23. package/dist/Context.js +29 -25
  24. package/dist/Context.js.map +1 -1
  25. package/dist/EventBase.js +2 -11
  26. package/dist/EventBase.js.map +1 -1
  27. package/dist/Fiber.d.ts +12 -0
  28. package/dist/Fiber.js +44 -0
  29. package/dist/Fiber.js.map +1 -0
  30. package/dist/Handler.d.ts +4 -1
  31. package/dist/Handler.js +2 -1
  32. package/dist/Handler.js.map +1 -1
  33. package/dist/L/L.d.ts +0 -1
  34. package/dist/L/L.js +0 -1
  35. package/dist/L/L.js.map +1 -1
  36. package/dist/L/_infer.js +15 -17
  37. package/dist/L/_infer.js.map +1 -1
  38. package/dist/L/_message.js +5 -2
  39. package/dist/L/_message.js.map +1 -1
  40. package/dist/L/branch.js +10 -18
  41. package/dist/L/branch.js.map +1 -1
  42. package/dist/L/emit.js +6 -8
  43. package/dist/L/emit.js.map +1 -1
  44. package/dist/L/model.d.ts +2 -1
  45. package/dist/L/model.js +9 -3
  46. package/dist/L/model.js.map +1 -1
  47. package/dist/L/rune.d.ts +2 -1
  48. package/dist/L/rune.js +1 -0
  49. package/dist/L/rune.js.map +1 -1
  50. package/dist/LEvent.d.ts +12 -1
  51. package/dist/LEvent.js +7 -0
  52. package/dist/LEvent.js.map +1 -1
  53. package/dist/MessageRegistry.d.ts +9 -0
  54. package/dist/MessageRegistry.js +15 -0
  55. package/dist/MessageRegistry.js.map +1 -0
  56. package/dist/{state/ModelRegistry.d.ts → ModelRegistry.d.ts} +4 -2
  57. package/dist/{state/ModelRegistry.js → ModelRegistry.js} +12 -6
  58. package/dist/ModelRegistry.js.map +1 -0
  59. package/dist/Rune.d.ts +2 -1
  60. package/dist/Rune.js.map +1 -1
  61. package/dist/Runic.d.ts +3 -3
  62. package/dist/Runic.js.map +1 -1
  63. package/dist/index.d.ts +4 -3
  64. package/dist/index.js +4 -3
  65. package/dist/index.js.map +1 -1
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/index.ts +4 -3
  68. package/package.json +2 -2
  69. package/Globals.ts +0 -10
  70. package/L/fork.ts +0 -20
  71. package/L/namespace.ts +0 -11
  72. package/dist/Globals.d.ts +0 -6
  73. package/dist/Globals.js +0 -2
  74. package/dist/Globals.js.map +0 -1
  75. package/dist/L/fork.d.ts +0 -1
  76. package/dist/L/fork.js +0 -20
  77. package/dist/L/fork.js.map +0 -1
  78. package/dist/L/namespace.d.ts +0 -1
  79. package/dist/L/namespace.js +0 -12
  80. package/dist/L/namespace.js.map +0 -1
  81. package/dist/run.d.ts +0 -4
  82. package/dist/run.js +0 -35
  83. package/dist/run.js.map +0 -1
  84. package/dist/state/Fiber.d.ts +0 -9
  85. package/dist/state/Fiber.js +0 -14
  86. package/dist/state/Fiber.js.map +0 -1
  87. package/dist/state/Globals.d.ts +0 -9
  88. package/dist/state/Globals.js +0 -10
  89. package/dist/state/Globals.js.map +0 -1
  90. package/dist/state/MessageRegistry.d.ts +0 -7
  91. package/dist/state/MessageRegistry.js +0 -14
  92. package/dist/state/MessageRegistry.js.map +0 -1
  93. package/dist/state/ModelConfig.d.ts +0 -31
  94. package/dist/state/ModelConfig.js +0 -17
  95. package/dist/state/ModelConfig.js.map +0 -1
  96. package/dist/state/ModelRegistry.js.map +0 -1
  97. package/dist/state/StateMap.d.ts +0 -1
  98. package/dist/state/StateMap.js +0 -2
  99. package/dist/state/StateMap.js.map +0 -1
  100. package/run.ts +0 -37
  101. package/state/Fiber.ts +0 -13
  102. package/state/Globals.ts +0 -12
  103. package/state/MessageRegistry.ts +0 -17
  104. package/state/ModelConfig.ts +0 -47
  105. package/state/StateMap.ts +0 -0
package/Agent.ts CHANGED
@@ -1,9 +1,17 @@
1
1
  import { Context } from "./Context.ts"
2
- import { run } from "./run.ts"
3
- import type { Rune, RuneKey } from "./Rune.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"
5
- import { Fiber } from "./state/Fiber.ts"
6
- import { Globals } from "./state/Globals.ts"
8
+
9
+ export interface AgentConfig<E> {
10
+ handler?: ((this: Fiber, event: E) => void) | undefined
11
+ models?: ModelRegistry
12
+ messages?: MessageRegistry
13
+ signal?: AbortSignal | undefined
14
+ }
7
15
 
8
16
  export interface Agent<out T, out E> extends PromiseLike<T> {
9
17
  T: T
@@ -12,15 +20,16 @@ export interface Agent<out T, out E> extends PromiseLike<T> {
12
20
 
13
21
  export function Agent<Y extends Rune, T>(
14
22
  runic: Runic<Y, T>,
15
- globals?: Partial<Globals<Y[RuneKey]>>,
23
+ config?: AgentConfig<Rune.E<Y>>,
16
24
  ): Agent<T, Rune.E<Y>> {
17
25
  return {
18
26
  then(onfulfilled, onrejected) {
19
- const context = new Context([
20
- [Globals.make, Globals.make(globals)],
21
- [Fiber.make, Fiber.make()],
27
+ const rootCtx = new Context([
28
+ [HandlerContext, config?.handler],
29
+ [ModelRegistryContext, config?.models ?? new ModelRegistry()],
30
+ [MessageRegistryContext, config?.messages ?? new MessageRegistry()],
22
31
  ])
23
- return Context.storage.run(context, () => run(runic).then(onfulfilled, onrejected))
32
+ return rootCtx.run(() => new Fiber(runic).resolve().then(onfulfilled, onrejected))
24
33
  },
25
34
  } satisfies Omit<Agent<T, Rune.E<Y>>, "E" | "T"> as never
26
35
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # liminal
2
2
 
3
+ ## 0.5.7
4
+
5
+ ### Patch Changes
6
+
7
+ - a56f121: Re-flatten events. Make fiber info available in event handler via this.
8
+ - Updated dependencies [a56f121]
9
+ - liminal-util@0.0.3
10
+
11
+ ## 0.5.6
12
+
13
+ ### Patch Changes
14
+
15
+ - f79205e: Include fiber information in the event type supplied to user-specified handlers. Continue reworking runtime implementation.
16
+
3
17
  ## 0.5.5
4
18
 
5
19
  ### Patch Changes
package/Context.ts CHANGED
@@ -1,44 +1,52 @@
1
1
  import { assert } from "liminal-util"
2
2
  import { AsyncLocalStorage } from "node:async_hooks"
3
3
 
4
- export class Context extends Map<StateFactory, unknown> {
5
- static storage: AsyncLocalStorage<Context> = new AsyncLocalStorage<Context>()
6
-
7
- static make(context?: Context): Context {
8
- const instance = new Context()
9
- if (context) {
10
- for (const [key, value] of context.entries()) {
11
- instance.set(key, key(value))
12
- }
13
- }
14
- return instance
15
- }
4
+ const storage = new AsyncLocalStorage<Context>()
16
5
 
17
- static unwrap(): Context {
18
- const context = this.storage.getStore()
6
+ export class Context extends Map<ContextHandle, unknown> {
7
+ static ensure(): Context {
8
+ const context = storage.getStore()
19
9
  assert(context)
20
10
  return context
21
11
  }
22
12
 
23
- static get<T>(factory: StateFactory<T>): T | undefined {
24
- return this.unwrap().get(factory) as never
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
25
24
  }
26
25
 
27
- static getAssert<T>(factory: StateFactory<T>): T {
28
- const value = this.get(factory)
29
- assert(value)
30
- return value
26
+ set<V>(context: ContextHandle<V>, value: V): this {
27
+ super.set(context, value)
28
+ return this
31
29
  }
32
30
 
33
- static getOrInit<T>(factory: StateFactory<T>): T {
34
- let context = this.unwrap()
35
- let instance = context.get(factory)
36
- if (!instance) {
37
- instance = factory()
38
- context.set(factory, instance)
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
+ }
39
41
  }
40
- return instance as never
42
+ return context
41
43
  }
42
44
  }
43
45
 
44
- export type StateFactory<T = any> = (instance?: T) => T
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,4 +1,4 @@
1
- import { inspect, type InspectOptions } from "node:util"
1
+ import { attachCustomInspect } from "liminal-util"
2
2
 
3
3
  export interface EventBase<B extends symbol = symbol, K extends string = string> {
4
4
  readonly brand: B
@@ -10,17 +10,8 @@ export function EventBase<B extends symbol, K extends string>(brand: B, type: K)
10
10
  readonly brand = brand
11
11
  readonly type = type
12
12
 
13
- // Allows us to circumvent a false positive ts error related to private symbols.
14
- // https://github.com/microsoft/TypeScript/issues/58496
15
13
  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
- })
14
+ attachCustomInspect(this, ({ brand: _0, type: _1, ...rest }) => rest)
24
15
  }
25
16
  }
26
17
  }
package/Fiber.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { attachCustomInspect } from "liminal-util"
2
+ import { Context } from "./Context.ts"
3
+ import type { Rune } from "./Rune.ts"
4
+ import { Runic } from "./Runic.ts"
5
+
6
+ let nextIndex = 0
7
+
8
+ export class Fiber<T = any> {
9
+ readonly index = nextIndex++
10
+ declare readonly parent?: Fiber
11
+ context = Context.ensure()
12
+ pending: Promise<T> | undefined
13
+ constructor(readonly runic: Runic<Rune, T>, parent?: Fiber) {
14
+ if (parent) {
15
+ this.parent = parent
16
+ }
17
+ }
18
+
19
+ resolve(this: Fiber<T>): Promise<T> {
20
+ if (!this.pending) {
21
+ const { promise, resolve, reject } = Promise.withResolvers<T>()
22
+ this.pending = promise
23
+ const iterator = Runic.unwrap(this.runic)
24
+ let nextArg: unknown
25
+ this.context.run(async () => {
26
+ try {
27
+ let current = await iterator.next()
28
+ while (!current.done) {
29
+ const rune = current.value
30
+ nextArg = await rune(this)
31
+ current = await iterator.next(nextArg)
32
+ }
33
+ const { value } = current
34
+ resolve(value)
35
+ } catch (error) {
36
+ reject(error)
37
+ }
38
+ })
39
+ }
40
+ return this.pending
41
+ }
42
+
43
+ static {
44
+ attachCustomInspect(this, ({ index, parent }) => ({ index, ...parent && { parent } }))
45
+ }
46
+ }
package/Handler.ts CHANGED
@@ -0,0 +1,6 @@
1
+ import { ContextHandle } from "./Context.ts"
2
+ import type { Fiber } from "./Fiber.ts"
3
+
4
+ export type Handler<E = any> = [(this: Fiber, event: E) => void][0]
5
+
6
+ export const HandlerContext: ContextHandle<Handler | undefined> = ContextHandle()
package/L/L.ts CHANGED
@@ -4,7 +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
7
  export * from "./model.ts"
9
8
  export * from "./system.ts"
10
9
  export * from "./user.ts"
package/L/_infer.ts CHANGED
@@ -1,39 +1,33 @@
1
1
  import type { SchemaObject } from "liminal-schema"
2
2
  import { assert } from "liminal-util"
3
- import { Context } from "../Context.ts"
3
+ import { Context, ContextHandle } from "../Context.ts"
4
4
  import { InferenceRequested, Inferred, type LEvent } from "../LEvent.ts"
5
+ import { MessageRegistryContext } from "../MessageRegistry.ts"
6
+ import { ModelRegistryContext } from "../ModelRegistry.ts"
5
7
  import type { Rune } from "../Rune.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 modelRegistry = Context.getOrInit(ModelRegistry.make)
12
+ const context = Context.ensure()
13
+ const modelRegistry = context.get(ModelRegistryContext)
14
+ assert(modelRegistry)
13
15
  const model = modelRegistry.peek()
14
16
  assert(model)
15
- const messageRegistry = Context.getOrInit(MessageRegistry.make)
16
- const counter = Context.getOrInit(InferenceRequestCounter)
17
- const requestId = counter.next()
17
+ const requestId = context.getOrInit(InferenceRequestCounterContext, () => new InferenceRequestCounter()).next()
18
18
  yield* emit(new InferenceRequested(requestId, schema))
19
+ const messageRegistry = context.get(MessageRegistryContext)
20
+ assert(messageRegistry)
19
21
  const inference = yield* rune(() => model.resolve(messageRegistry.messages, schema))
20
22
  yield* emit(new Inferred(requestId, inference))
21
23
  return inference
22
24
  }
23
25
 
24
- function InferenceRequestCounter(instance?: Counter) {
25
- return {
26
- count: instance?.count ?? 0,
27
- next() {
28
- return this.count++
29
- },
30
- clone() {
31
- return InferenceRequestCounter(this)
32
- },
26
+ class InferenceRequestCounter {
27
+ count: number = 0
28
+ next(): number {
29
+ return this.count++
33
30
  }
34
31
  }
35
32
 
36
- interface Counter {
37
- count: number
38
- next(): number
39
- }
33
+ const InferenceRequestCounterContext: ContextHandle<InferenceRequestCounter> = ContextHandle()
package/L/_message.ts CHANGED
@@ -1,14 +1,17 @@
1
+ import { assert } from "liminal-util"
1
2
  import { Context } from "../Context.ts"
2
3
  import { type LEvent, MessageAppended } from "../LEvent.ts"
3
4
  import type { ContentPart, Message, MessageRole } from "../Message.ts"
5
+ import { MessageRegistryContext } from "../MessageRegistry.ts"
4
6
  import type { Rune } from "../Rune.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 messageRegistry = Context.getOrInit(MessageRegistry.make)
12
+ const context = Context.ensure()
13
+ const messageRegistry = context.get(MessageRegistryContext)
14
+ assert(messageRegistry)
12
15
  const message: Message = { role, content }
13
16
  yield* emit(new MessageAppended(message))
14
17
  messageRegistry.append(message)
package/L/branch.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { Context } from "../Context.ts"
2
- import { run } from "../run.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 { Fiber } from "../state/Fiber.ts"
6
5
  import { rune } from "./rune.ts"
7
6
 
8
7
  export interface branch<Y extends Rune, T> extends Generator<Y, T> {}
@@ -15,23 +14,16 @@ export function branch<XR extends Record<keyof any, Runic>>(
15
14
  runics: XR,
16
15
  ): branch<Runic.Y<XR[keyof XR]> | Rune<never>, { [K in keyof XR]: Runic.T<XR[K]> }>
17
16
  export function* branch(value: Runic | Array<Runic> | Record<keyof any, Runic>): branch<Rune, any> {
18
- const parent = Context.get(Fiber.make)
17
+ const context = Context.ensure()
18
+ const parent = yield* rune((fiber) => fiber)
19
19
  if (Array.isArray(value)) {
20
- const runners = value.map((runic) => {
21
- const context = Context.make(Context.unwrap())
22
- context.set(Fiber.make, new Fiber(parent))
23
- return () => run(runic, context)
24
- })
25
- return yield* rune(() => Promise.all(runners.map((runner) => runner())))
20
+ const fibers = value.map((runic) => context.clone().run(() => new Fiber(runic, parent)))
21
+ return yield* rune(() => Promise.all(fibers.map((fiber) => fiber.resolve())))
26
22
  } else if (typeof value === "object") {
27
- const runners = Object.entries(value).map(([key, runic]) => {
28
- const context = Context.make(Context.unwrap())
29
- context.set(Fiber.make, new Fiber(parent))
30
- return async () => [key, await run(runic, context)]
31
- })
32
- 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(() => new Fiber(runic, parent)))
25
+ return yield* rune(() => Promise.all(fibers.map((fiber) => fiber.resolve())).then(Object.fromEntries))
33
26
  }
34
- const context = Context.make(Context.unwrap())
35
- context.set(Fiber.make, new Fiber(parent))
36
- return yield* rune(() => run(typeof value === "function" ? value() : value, context))
27
+ const fiber = context.clone().run(() => new Fiber(typeof value === "function" ? value() : value, parent))
28
+ return yield* rune(() => fiber.resolve())
37
29
  }
package/L/emit.ts CHANGED
@@ -1,16 +1,14 @@
1
1
  import type { EnsureNarrow } from "liminal-util"
2
2
  import { Context } from "../Context.ts"
3
+ import { HandlerContext } from "../Handler.ts"
3
4
  import type { Rune } from "../Rune.ts"
4
- import { Fiber } from "../state/Fiber.ts"
5
- import { Globals } from "../state/Globals.ts"
5
+ import { rune } from "./rune.ts"
6
6
 
7
7
  export interface emit<E> extends Generator<Rune<E>, void> {}
8
8
 
9
9
  export function* emit<const E>(event: EnsureNarrow<E>): emit<E> {
10
- const globals = Context.getAssert(Globals.make)
11
- const fiber = Context.getAssert(Fiber.make)
12
- globals.handler?.(event, {
13
- fiber: fiber.index,
14
- timestamp: Date.now(),
15
- })
10
+ const context = Context.ensure()
11
+ const handler = context.get(HandlerContext)
12
+ const fiber = yield* rune((fiber) => fiber)
13
+ handler?.call(fiber, event)
16
14
  }
package/L/model.ts CHANGED
@@ -1,11 +1,17 @@
1
+ import { assert } from "liminal-util"
1
2
  import { Context } from "../Context.ts"
3
+ import { ModelRegistered } from "../LEvent.ts"
2
4
  import type { Model } from "../Model.ts"
5
+ import { ModelRegistryContext } from "../ModelRegistry.ts"
3
6
  import type { Rune } from "../Rune.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 modelRegistry = Context.getOrInit(ModelRegistry.make)
10
- 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))
11
17
  }
package/L/rune.ts CHANGED
@@ -1,10 +1,11 @@
1
+ import { Fiber } from "../Fiber.ts"
1
2
  import { type Rune, RuneKey } from "../Rune.ts"
2
3
 
3
4
  export interface rune<T> extends Iterable<Rune<never>, T> {
4
5
  <E>(): Generator<Rune<E>, T>
5
6
  }
6
7
 
7
- export function rune<R>(source: () => R): rune<Awaited<R>> {
8
+ export function rune<R>(source: (fiber: Fiber) => R): rune<Awaited<R>> {
8
9
  return Object.assign(
9
10
  function*<E>(): Generator<Rune<E>, Awaited<R>> {
10
11
  return yield Object.assign(source, { [RuneKey]: {} as never })
package/LEvent.ts CHANGED
@@ -1,12 +1,26 @@
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
 
18
+ export class ModelRegistered extends EventBase(LEventTag, "model_registered") {
19
+ constructor(readonly model: Model) {
20
+ super()
21
+ }
22
+ }
23
+
10
24
  export class InferenceRequested extends EventBase(LEventTag, "inference_requested") {
11
25
  declare schema?: SchemaObject
12
26
  constructor(
@@ -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,21 +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)
6
+ declare head?: ModelRegistryNode | undefined
7
+ declare tail?: ModelRegistryNode | undefined
8
+
9
+ constructor(models?: Array<Model>) {
10
+ if (models) {
11
+ for (const model of models) {
12
+ this.register(model)
10
13
  }
11
14
  }
12
- return instance
13
15
  }
14
16
 
15
- declare head?: ModelRegistryNode | undefined
16
- declare tail?: ModelRegistryNode | undefined
17
-
18
- peek(): Model | undefined {
17
+ peek() {
19
18
  return this.tail?.model
20
19
  }
21
20
 
@@ -33,7 +32,7 @@ export class ModelRegistry {
33
32
  return node
34
33
  }
35
34
 
36
- remove(node: ModelRegistryNode): void {
35
+ remove(node: ModelRegistryNode) {
37
36
  if (node.prev) {
38
37
  node.prev.next = node.next
39
38
  }
@@ -55,3 +54,11 @@ export interface ModelRegistryNode {
55
54
  model: Model
56
55
  next?: ModelRegistryNode | undefined
57
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,5 +1,7 @@
1
+ import type { Fiber } from "./Fiber.ts"
2
+
1
3
  export interface Rune<out E = any> {
2
- (): any
4
+ (fiber: Fiber): any
3
5
  [RuneKey]: E
4
6
  }
5
7
 
package/Runic.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  import type { Rune } from "./Rune.ts"
2
2
 
3
3
  export type RuneIterator<Y extends Rune = Rune, T = any> = Iterator<Y, T> | AsyncIterator<Y, T>
4
- export type RuneIterable<Y extends Rune, T> = Iterable<Y, T> | AsyncIterable<Y, T>
4
+ export type RuneIterable<Y extends Rune = Rune, T = any> = Iterable<Y, T> | AsyncIterable<Y, T>
5
5
  export type Runic<Y extends Rune = Rune, T = any> = RuneIterable<Y, T> | (() => RuneIterable<Y, T>)
6
+
6
7
  export namespace Runic {
7
- export type Y<R extends Runic> = R extends Runic<infer Y> ? Y : never
8
- export type T<R extends Runic> = R extends Runic<Rune, infer T> ? T : never
8
+ export type Y<X extends Runic> = X extends RuneIterable<infer Y> ? Y
9
+ : X extends () => RuneIterable<infer Y> ? Y
10
+ : X extends RuneIterator<infer Y> ? Y
11
+ : never
12
+
13
+ export type T<X extends Runic> = X extends RuneIterable<Rune, infer T> ? T
14
+ : X extends () => RuneIterable<Rune, infer T> ? T
15
+ : X extends RuneIterator<Rune, infer T> ? T
16
+ : never
9
17
 
10
18
  export function unwrap<Y extends Rune, T>(runic: Runic<Y, T>): RuneIterator<Y, T> {
11
19
  if (Symbol.iterator in runic) {
package/dist/Agent.d.ts CHANGED
@@ -1,8 +1,16 @@
1
- import type { Rune, RuneKey } from "./Rune.ts";
1
+ import { Fiber } from "./Fiber.ts";
2
+ import { MessageRegistry } from "./MessageRegistry.ts";
3
+ import { ModelRegistry } from "./ModelRegistry.ts";
4
+ import type { Rune } from "./Rune.ts";
2
5
  import type { Runic } from "./Runic.ts";
3
- import { Globals } from "./state/Globals.ts";
6
+ export interface AgentConfig<E> {
7
+ handler?: ((this: Fiber, event: E) => void) | undefined;
8
+ models?: ModelRegistry;
9
+ messages?: MessageRegistry;
10
+ signal?: AbortSignal | undefined;
11
+ }
4
12
  export interface Agent<out T, out E> extends PromiseLike<T> {
5
13
  T: T;
6
14
  E: E;
7
15
  }
8
- export declare function Agent<Y extends Rune, T>(runic: Runic<Y, T>, globals?: Partial<Globals<Y[RuneKey]>>): Agent<T, Rune.E<Y>>;
16
+ export declare function Agent<Y extends Rune, T>(runic: Runic<Y, T>, config?: AgentConfig<Rune.E<Y>>): Agent<T, Rune.E<Y>>;
package/dist/Agent.js CHANGED
@@ -1,15 +1,17 @@
1
1
  import { Context } from "./Context.js";
2
- import { run } from "./run.js";
3
- import { Fiber } from "./state/Fiber.js";
4
- import { Globals } from "./state/Globals.js";
5
- export function Agent(runic, globals) {
2
+ import { Fiber } from "./Fiber.js";
3
+ import { HandlerContext } from "./Handler.js";
4
+ import { MessageRegistry, MessageRegistryContext } from "./MessageRegistry.js";
5
+ import { ModelRegistry, ModelRegistryContext } from "./ModelRegistry.js";
6
+ export function Agent(runic, config) {
6
7
  return {
7
8
  then(onfulfilled, onrejected) {
8
- const context = new Context([
9
- [Globals.make, Globals.make(globals)],
10
- [Fiber.make, Fiber.make()],
9
+ const rootCtx = new Context([
10
+ [HandlerContext, config?.handler],
11
+ [ModelRegistryContext, config?.models ?? new ModelRegistry()],
12
+ [MessageRegistryContext, config?.messages ?? new MessageRegistry()],
11
13
  ]);
12
- return Context.storage.run(context, () => run(runic).then(onfulfilled, onrejected));
14
+ return rootCtx.run(() => new Fiber(runic).resolve().then(onfulfilled, onrejected));
13
15
  },
14
16
  };
15
17
  }
package/dist/Agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Agent.js","sourceRoot":"","sources":["../Agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG9B,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAO5C,MAAM,UAAU,KAAK,CACnB,KAAkB,EAClB,OAAsC;IAEtC,OAAO;QACL,IAAI,CAAC,WAAW,EAAE,UAAU;YAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;gBAC1B,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;aAC3B,CAAC,CAAA;YACF,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAA;QACrF,CAAC;KACsD,CAAA;AAC3D,CAAC"}
1
+ {"version":3,"file":"Agent.js","sourceRoot":"","sources":["../Agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAgBxE,MAAM,UAAU,KAAK,CACnB,KAAkB,EAClB,MAA+B;IAE/B,OAAO;QACL,IAAI,CAAC,WAAW,EAAE,UAAU;YAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;gBAC1B,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC;gBACjC,CAAC,oBAAoB,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;gBAC7D,CAAC,sBAAsB,EAAE,MAAM,EAAE,QAAQ,IAAI,IAAI,eAAe,EAAE,CAAC;aACpE,CAAC,CAAA;YACF,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAA;QACpF,CAAC;KACsD,CAAA;AAC3D,CAAC"}
package/dist/Context.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- export declare class Context extends Map<StateFactory, unknown> {
3
- static storage: AsyncLocalStorage<Context>;
4
- static make(context?: Context): Context;
5
- static unwrap(): Context;
6
- static get<T>(factory: StateFactory<T>): T | undefined;
7
- static getAssert<T>(factory: StateFactory<T>): T;
8
- static getOrInit<T>(factory: StateFactory<T>): T;
1
+ export declare class Context extends Map<ContextHandle, unknown> {
2
+ static ensure(): Context;
3
+ get<V>(context: ContextHandle<V>): V | undefined;
4
+ getOrInit<V>(context: ContextHandle<V>, init: () => V): V;
5
+ set<V>(context: ContextHandle<V>, value: V): this;
6
+ run<R>(callback: () => R): R;
7
+ clone(overrides?: Iterable<[ContextHandle, unknown]>): Context;
9
8
  }
10
- export type StateFactory<T = any> = (instance?: T) => T;
9
+ export type ContextHandle<V = any> = {
10
+ clone?: ((value: V) => V) | undefined;
11
+ };
12
+ export declare function ContextHandle<V>(clone?: (value: V) => V): ContextHandle<V>;