liminal 0.5.9 → 0.5.11

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/CHANGELOG.md +18 -0
  2. package/Context.ts +21 -24
  3. package/EventBase.ts +6 -0
  4. package/Fiber.ts +60 -47
  5. package/Handler.ts +2 -2
  6. package/L/L.ts +5 -3
  7. package/L/_common.ts +6 -0
  8. package/L/assistant.ts +6 -6
  9. package/L/catch.ts +15 -2
  10. package/L/emit.ts +3 -7
  11. package/L/{_infer.ts → infer.ts} +18 -14
  12. package/L/{_message.ts → message.ts} +3 -5
  13. package/L/model.ts +1 -3
  14. package/L/rune.ts +8 -26
  15. package/L/strand.ts +99 -0
  16. package/L/stream.ts +30 -0
  17. package/L/system.ts +2 -2
  18. package/L/user.ts +2 -2
  19. package/LEvent.ts +10 -3
  20. package/MessageRegistry.ts +4 -3
  21. package/Model.ts +13 -2
  22. package/ModelRegistry.ts +13 -8
  23. package/Tool.ts +17 -14
  24. package/ToolRegistry.ts +8 -3
  25. package/dist/Context.d.ts +10 -10
  26. package/dist/Context.js +16 -19
  27. package/dist/Context.js.map +1 -1
  28. package/dist/EventBase.d.ts +1 -0
  29. package/dist/EventBase.js +5 -0
  30. package/dist/EventBase.js.map +1 -1
  31. package/dist/Fiber.d.ts +19 -15
  32. package/dist/Fiber.js +36 -25
  33. package/dist/Fiber.js.map +1 -1
  34. package/dist/Handler.d.ts +2 -2
  35. package/dist/Handler.js +2 -2
  36. package/dist/Handler.js.map +1 -1
  37. package/dist/L/L.d.ts +5 -3
  38. package/dist/L/L.js +5 -3
  39. package/dist/L/L.js.map +1 -1
  40. package/dist/L/_common.d.ts +4 -0
  41. package/dist/L/_common.js +7 -0
  42. package/dist/L/_common.js.map +1 -0
  43. package/dist/L/assistant.js +6 -6
  44. package/dist/L/assistant.js.map +1 -1
  45. package/dist/L/catch.js +12 -2
  46. package/dist/L/catch.js.map +1 -1
  47. package/dist/L/emit.js +3 -7
  48. package/dist/L/emit.js.map +1 -1
  49. package/dist/L/infer.d.ts +7 -0
  50. package/dist/L/infer.js +29 -0
  51. package/dist/L/infer.js.map +1 -0
  52. package/dist/L/message.d.ts +6 -0
  53. package/dist/L/{_message.js → message.js} +3 -5
  54. package/dist/L/message.js.map +1 -0
  55. package/dist/L/model.js +1 -3
  56. package/dist/L/model.js.map +1 -1
  57. package/dist/L/rune.d.ts +1 -6
  58. package/dist/L/rune.js +5 -15
  59. package/dist/L/rune.js.map +1 -1
  60. package/dist/L/strand.d.ts +26 -0
  61. package/dist/L/strand.js +69 -0
  62. package/dist/L/strand.js.map +1 -0
  63. package/dist/L/stream.d.ts +5 -0
  64. package/dist/L/stream.js +27 -0
  65. package/dist/L/stream.js.map +1 -0
  66. package/dist/L/system.js +2 -2
  67. package/dist/L/system.js.map +1 -1
  68. package/dist/L/user.js +2 -2
  69. package/dist/L/user.js.map +1 -1
  70. package/dist/LEvent.d.ts +21 -1
  71. package/dist/LEvent.js +13 -2
  72. package/dist/LEvent.js.map +1 -1
  73. package/dist/MessageRegistry.d.ts +2 -2
  74. package/dist/MessageRegistry.js +2 -2
  75. package/dist/MessageRegistry.js.map +1 -1
  76. package/dist/Model.d.ts +12 -3
  77. package/dist/Model.js +3 -3
  78. package/dist/Model.js.map +1 -1
  79. package/dist/ModelRegistry.d.ts +3 -2
  80. package/dist/ModelRegistry.js +9 -8
  81. package/dist/ModelRegistry.js.map +1 -1
  82. package/dist/Tool.js +2 -13
  83. package/dist/Tool.js.map +1 -1
  84. package/dist/ToolRegistry.d.ts +3 -2
  85. package/dist/ToolRegistry.js +5 -2
  86. package/dist/ToolRegistry.js.map +1 -1
  87. package/dist/index.d.ts +0 -1
  88. package/dist/index.js +0 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/tsconfig.tsbuildinfo +1 -1
  91. package/index.ts +0 -1
  92. package/package.json +4 -4
  93. package/Agent.ts +0 -38
  94. package/L/branch.ts +0 -33
  95. package/dist/Agent.d.ts +0 -18
  96. package/dist/Agent.js +0 -20
  97. package/dist/Agent.js.map +0 -1
  98. package/dist/L/_infer.d.ts +0 -4
  99. package/dist/L/_infer.js +0 -28
  100. package/dist/L/_infer.js.map +0 -1
  101. package/dist/L/_message.d.ts +0 -6
  102. package/dist/L/_message.js.map +0 -1
  103. package/dist/L/branch.d.ts +0 -11
  104. package/dist/L/branch.js +0 -24
  105. package/dist/L/branch.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # liminal
2
2
 
3
+ ## 0.5.11
4
+
5
+ ### Patch Changes
6
+
7
+ - cf42ed2: Agent -> Strand. Making the API more uniform. Ie. Agent -> L.strand. L.branch -> L.strand.
8
+ - Updated dependencies [cf42ed2]
9
+ - liminal-schema@0.0.5
10
+ - liminal-util@0.0.6
11
+
12
+ ## 0.5.10
13
+
14
+ ### Patch Changes
15
+
16
+ - aef5564: Update Model interface to support streaming. Improve event-related functionality and emit fiber-related events.
17
+ - Updated dependencies [aef5564]
18
+ - liminal-schema@0.0.4
19
+ - liminal-util@0.0.5
20
+
3
21
  ## 0.5.9
4
22
 
5
23
  ### Patch Changes
package/Context.ts CHANGED
@@ -1,43 +1,40 @@
1
- import { assert } from "liminal-util"
2
1
  import { AsyncLocalStorage } from "node:async_hooks"
3
2
 
4
3
  const storage = new AsyncLocalStorage<Context>()
5
4
 
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
5
+ export class Context extends Map<ContextPart, unknown> {
6
+ static get(): Context | undefined {
7
+ return storage.getStore()
15
8
  }
16
9
 
17
- set<V>(context: ContextHandle<V>, value: V): this {
18
- super.set(context, value)
19
- return this
10
+ run<R>(f: () => R): R {
11
+ return storage.run(this, f)
20
12
  }
21
13
 
22
- run<R>(callback: () => R): R {
23
- return storage.run(this, callback)
24
- }
25
-
26
- clone(overrides?: Iterable<[ContextHandle, unknown]>): Context {
27
- const context = new Context(overrides)
14
+ fork(): Context {
15
+ const context = new Context()
28
16
  for (const [handle, value] of this.entries()) {
29
17
  if (!context.has(handle)) {
30
- context.set(handle, handle.clone?.(value) ?? value)
18
+ context.set(handle, handle.fork(value))
31
19
  }
32
20
  }
33
21
  return context
34
22
  }
35
23
  }
36
24
 
37
- export type ContextHandle<V = any> = {
38
- clone: ((value: V) => V) | undefined
25
+ export interface ContextPart<V = any> {
26
+ fork(parent?: V): V
27
+ get(): V | undefined
28
+ debug?: string
39
29
  }
40
30
 
41
- export function ContextHandle<V>(clone?: (value: V) => V): ContextHandle<V> {
42
- return { clone }
31
+ export function ContextPart<V>(fork: (parent?: V) => V, debug?: string): ContextPart<V> {
32
+ const self: ContextPart<V> = {
33
+ fork,
34
+ get() {
35
+ return Context.get()?.get(self) as never
36
+ },
37
+ ...debug && { debug },
38
+ }
39
+ return self
43
40
  }
package/EventBase.ts CHANGED
@@ -7,6 +7,12 @@ export interface EventBase<B extends symbol = symbol, K extends string = string>
7
7
 
8
8
  export function EventBase<B extends symbol, K extends string>(brand: B, type: K) {
9
9
  return class implements EventBase<B, K> {
10
+ static is<T>(this: new(...args: any) => T, value: unknown): value is T {
11
+ return typeof value === "object" && value !== null
12
+ && "brand" in value && value.brand === brand
13
+ && "type" in value && value.type === type
14
+ }
15
+
10
16
  readonly brand = brand
11
17
  readonly type = type
12
18
 
package/Fiber.ts CHANGED
@@ -1,69 +1,63 @@
1
1
  import { attachCustomInspect } from "liminal-util"
2
2
  import { Context } from "./Context.ts"
3
- import type { Rune } from "./Rune.ts"
3
+ import { type Handler, HandlerContext } from "./Handler.ts"
4
+ import { ToolRegistry, ToolRegistryContext } from "./index.ts"
5
+ import { FiberCreated, FiberRejected, FiberResolved, FiberStarted } from "./LEvent.ts"
6
+ import { MessageRegistry, MessageRegistryContext } from "./MessageRegistry.ts"
7
+ import { ModelRegistry, ModelRegistryContext } from "./ModelRegistry.ts"
8
+ import { type Rune, RuneKey } from "./Rune.ts"
4
9
  import { Runic } from "./Runic.ts"
5
10
 
6
- export type FiberStatus<T> = {
7
- type: "untouched"
8
- } | {
9
- type: "pending"
10
- self: AbortSignal
11
- promise: Promise<T>
12
- } | {
13
- type: "aborted"
14
- reason: unknown
15
- } | {
16
- type: "resolved"
17
- value: T
18
- } | {
19
- type: "rejected"
20
- exception: unknown
11
+ export interface FiberConfig {
12
+ parent?: Fiber
13
+ signal?: AbortSignal
14
+ context: Context
21
15
  }
22
16
 
23
17
  export class Fiber<T = any> {
24
- static nextIndex: number = 0
18
+ static *[Symbol.iterator](): Generator<Rune<never>, Fiber> {
19
+ return yield Object.assign((fiber: Fiber) => fiber, {
20
+ [RuneKey]: true,
21
+ debug: "current_fiber",
22
+ } as never)
23
+ }
25
24
 
26
- declare T: T
25
+ static nextIndex: number = 0
27
26
  readonly index: number = Fiber.nextIndex++
28
27
 
29
- #runic: Runic<Rune, T>
30
- declare readonly parent?: Fiber
31
- #context: Context = Context.ensure()
28
+ readonly #context: Context
29
+ readonly #runic: Runic<Rune, T>
30
+ readonly #handler: Handler | undefined = HandlerContext.get()
31
+ readonly #configSignal?: AbortSignal
32
32
 
33
- signal: AbortSignal
34
- either: AbortSignal
35
- abort: (reason?: any) => void
33
+ declare readonly parent?: Fiber
36
34
 
37
35
  status: FiberStatus<T> = { type: "untouched" }
36
+ controller: AbortController = new AbortController()
38
37
 
39
- constructor(runic: Runic<Rune, T>, parent?: Fiber) {
38
+ constructor(runic: Runic<Rune, T>, config: FiberConfig) {
40
39
  this.#runic = runic
41
- if (parent) {
42
- this.parent = parent
43
- }
44
- const controller = new AbortController()
45
- this.signal = controller.signal
46
- this.either = AbortSignal.any([
47
- ...this.parent?.signal ? [this.parent.signal] : [],
48
- this.signal,
49
- ])
50
- this.abort = controller.abort.bind(controller)
40
+ const { context, parent, signal } = config
41
+ this.#context = context
42
+ if (parent) this.parent = parent
43
+ if (signal) this.#configSignal = signal
44
+ this.handle(new FiberCreated())
51
45
  }
52
46
 
53
- fork<T>(runic: Runic<Rune, T>): Fiber<T> {
54
- return new Fiber(runic, this)
47
+ handle(event: any) {
48
+ this.#handler?.call(this, event)
55
49
  }
56
50
 
57
- resolution(this: Fiber<T>): Promise<T> {
58
- const { status, abort } = this
59
- switch (status.type) {
51
+ resolution(): Promise<T> {
52
+ switch (this.status.type) {
60
53
  case "untouched": {
61
54
  const { promise, resolve, reject } = Promise.withResolvers<T>()
62
55
  this.status = {
63
56
  type: "pending",
64
- self: this.signal,
57
+ self: this.controller.signal,
65
58
  promise,
66
59
  }
60
+ this.handle(new FiberStarted())
67
61
  const iterator = Runic.unwrap(this.#runic)
68
62
  let nextArg: unknown
69
63
  this.#context.run(async () => {
@@ -79,30 +73,32 @@ export class Fiber<T = any> {
79
73
  type: "resolved",
80
74
  value,
81
75
  }
82
- abort()
76
+ this.handle(new FiberResolved(value))
77
+ this.controller.abort()
83
78
  resolve(value)
84
79
  } catch (exception) {
85
80
  this.status = {
86
81
  type: "rejected",
87
82
  exception,
88
83
  }
89
- abort(exception)
84
+ this.handle(new FiberRejected(exception))
85
+ this.controller.abort()
90
86
  reject(exception)
91
87
  }
92
88
  })
93
89
  return promise
94
90
  }
95
91
  case "pending": {
96
- return status.promise
92
+ return this.status.promise
97
93
  }
98
94
  case "resolved": {
99
- return Promise.resolve(status.value)
95
+ return Promise.resolve(this.status.value)
100
96
  }
101
97
  case "rejected": {
102
- return Promise.reject(status.exception)
98
+ return Promise.reject(this.status.exception)
103
99
  }
104
100
  case "aborted": {
105
- return Promise.reject(status.reason)
101
+ return Promise.reject(this.status.reason)
106
102
  }
107
103
  }
108
104
  }
@@ -111,3 +107,20 @@ export class Fiber<T = any> {
111
107
  attachCustomInspect(this, ({ index, parent }) => ({ index, ...parent && { parent } }))
112
108
  }
113
109
  }
110
+
111
+ export type FiberStatus<T> = {
112
+ type: "untouched"
113
+ } | {
114
+ type: "pending"
115
+ self: AbortSignal
116
+ promise: Promise<T>
117
+ } | {
118
+ type: "aborted"
119
+ reason: unknown
120
+ } | {
121
+ type: "resolved"
122
+ value: T
123
+ } | {
124
+ type: "rejected"
125
+ exception: unknown
126
+ }
package/Handler.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { ContextHandle } from "./Context.ts"
1
+ import { ContextPart as ContextPart } from "./Context.ts"
2
2
  import type { Fiber } from "./Fiber.ts"
3
3
 
4
4
  export type Handler<E = any> = [(this: Fiber, event: E) => void][0]
5
5
 
6
- export const HandlerContext: ContextHandle<Handler | undefined> = ContextHandle()
6
+ export const HandlerContext: ContextPart<Handler | undefined> = ContextPart((parent) => parent, "handler")
package/L/L.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export * from "liminal-schema/factories"
2
- export * from "./_infer.ts"
3
- export * from "./_message.ts"
4
2
  export * from "./assistant.ts"
5
- export * from "./branch.ts"
6
3
  export * from "./catch.ts"
7
4
  export * from "./emit.ts"
5
+ export * from "./infer.ts"
6
+ export * from "./message.ts"
8
7
  export * from "./model.ts"
8
+ export * from "./rune.ts"
9
+ export * from "./strand.ts"
10
+ export * from "./stream.ts"
9
11
  export * from "./system.ts"
10
12
  export * from "./user.ts"
package/L/_common.ts ADDED
@@ -0,0 +1,6 @@
1
+ export class RequestCounter {
2
+ static count: number = 0
3
+ static next(): number {
4
+ return this.count++
5
+ }
6
+ }
package/L/assistant.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { type LType, toJSONSchema, validate } from "liminal-schema"
2
2
  import type { LEvent } from "../LEvent.ts"
3
3
  import type { Rune } from "../Rune.ts"
4
- import { _infer } from "./_infer.ts"
5
- import { _message } from "./_message.ts"
4
+ import { infer } from "./infer.ts"
5
+ import { message } from "./message.ts"
6
6
  import { rune } from "./rune.ts"
7
7
 
8
8
  export interface assistant extends Iterable<Rune<LEvent>, string> {
@@ -12,15 +12,15 @@ export interface assistant extends Iterable<Rune<LEvent>, string> {
12
12
  export const assistant: assistant = Object.assign(
13
13
  function*<T>(type: LType<T>): Generator<Rune<LEvent>, T> {
14
14
  const schema = toJSONSchema(type)
15
- const inference = yield* _infer(schema)
16
- yield* _message("assistant", [{ part: inference }])
15
+ const inference = yield* infer(schema)
16
+ yield* message("assistant", [{ part: inference }])
17
17
  const input = JSON.parse(inference)
18
18
  return yield* rune(() => validate(type, input), "validate_assistant_message")
19
19
  },
20
20
  {
21
21
  *[Symbol.iterator]() {
22
- const inference = yield* _infer()
23
- yield* _message("assistant", [{ part: inference }])
22
+ const inference = yield* infer()
23
+ yield* message("assistant", [{ part: inference }])
24
24
  return inference
25
25
  },
26
26
  },
package/L/catch.ts CHANGED
@@ -1,12 +1,25 @@
1
+ import { assert } from "liminal-util"
2
+ import { Context } from "../Context.ts"
3
+ import { Fiber } from "../Fiber.ts"
1
4
  import type { Rune } from "../Rune.ts"
2
5
  import type { Runic } from "../Runic.ts"
3
6
  import { rune } from "./rune.ts"
4
7
 
5
8
  export { catch_ as catch }
9
+
6
10
  function* catch_<Y extends Rune, T>(runic: Runic<Y, T>): Generator<Rune<Y>, CatchResult<T>> {
7
- return yield* rune(async (fiber) => {
11
+ return yield* rune(async (parent) => {
8
12
  try {
9
- return { resolved: await fiber.fork(runic).resolution() }
13
+ const context = Context.get()
14
+ assert(context)
15
+ return {
16
+ resolved: await context.fork().run(() =>
17
+ new Fiber(runic, {
18
+ context: context.fork(),
19
+ parent,
20
+ }).resolution()
21
+ ),
22
+ }
10
23
  } catch (exception: unknown) {
11
24
  return { rejected: exception }
12
25
  }
package/L/emit.ts CHANGED
@@ -1,14 +1,10 @@
1
1
  import type { EnsureNarrow } from "liminal-util"
2
- import { Context } from "../Context.ts"
3
- import { HandlerContext } from "../Handler.ts"
2
+ import { Fiber } from "../Fiber.ts"
4
3
  import type { Rune } from "../Rune.ts"
5
- import { rune } from "./rune.ts"
6
4
 
7
5
  export interface emit<E> extends Generator<Rune<E>, void> {}
8
6
 
9
7
  export function* emit<const E>(event: EnsureNarrow<E>): emit<E> {
10
- const context = Context.ensure()
11
- const handler = context.get(HandlerContext)
12
- const fiber = yield* rune
13
- handler?.call(fiber, event)
8
+ const self = yield* Fiber
9
+ self.handle(event)
14
10
  }
@@ -1,31 +1,35 @@
1
1
  import type { SchemaObject } from "liminal-schema"
2
2
  import { assert } from "liminal-util"
3
- import { Context } from "../Context.ts"
4
3
  import { InferenceRequested, Inferred, type LEvent } from "../LEvent.ts"
5
4
  import { MessageRegistryContext } from "../MessageRegistry.ts"
6
5
  import { ModelRegistryContext } from "../ModelRegistry.ts"
7
6
  import type { Rune } from "../Rune.ts"
7
+ import { RequestCounter } from "./_common.ts"
8
8
  import { emit } from "./emit.ts"
9
9
  import { rune } from "./rune.ts"
10
10
 
11
- export function* _infer(schema?: SchemaObject): Generator<Rune<LEvent>, string> {
12
- const context = Context.ensure()
13
- const modelRegistry = context.get(ModelRegistryContext)
11
+ export { infer_ as infer }
12
+
13
+ interface infer_ extends Generator<Rune<LEvent>, string> {}
14
+
15
+ function* infer_(schema?: SchemaObject): infer_ {
16
+ const modelRegistry = ModelRegistryContext.get()
14
17
  assert(modelRegistry)
15
18
  const model = modelRegistry.peek()
16
19
  assert(model)
17
- const requestId = InferenceCounter.next()
20
+ const requestId = RequestCounter.next()
18
21
  yield* emit(new InferenceRequested(requestId, schema))
19
- const messageRegistry = context.get(MessageRegistryContext)
22
+ const messageRegistry = MessageRegistryContext.get()
20
23
  assert(messageRegistry)
21
- const inference = yield* rune(() => model.resolve(messageRegistry.messages, schema), "infer")
24
+ const inference = yield* rune((fiber) =>
25
+ model
26
+ .seal({
27
+ messages: messageRegistry.messages,
28
+ schema,
29
+ signal: fiber.controller.signal,
30
+ })
31
+ .resolve(), "infer")
22
32
  yield* emit(new Inferred(requestId, inference))
23
33
  return inference
24
34
  }
25
-
26
- class InferenceCounter {
27
- static count: number = 0
28
- static next(): number {
29
- return this.count++
30
- }
31
- }
35
+ Object.defineProperty(infer_, "name", { value: "infer" })
@@ -1,16 +1,14 @@
1
1
  import { assert } from "liminal-util"
2
- import { Context } from "../Context.ts"
3
2
  import { type LEvent, MessageAppended } from "../LEvent.ts"
4
3
  import type { ContentPart, Message, MessageRole } from "../Message.ts"
5
4
  import { MessageRegistryContext } from "../MessageRegistry.ts"
6
5
  import type { Rune } from "../Rune.ts"
7
6
  import { emit } from "./emit.ts"
8
7
 
9
- export interface _message extends Generator<Rune<LEvent>, void> {}
8
+ export interface message extends Generator<Rune<LEvent>, void> {}
10
9
 
11
- export function* _message(role: MessageRole, content: Array<ContentPart>): _message {
12
- const context = Context.ensure()
13
- const messageRegistry = context.get(MessageRegistryContext)
10
+ export function* message(role: MessageRole, content: Array<ContentPart>): message {
11
+ const messageRegistry = MessageRegistryContext.get()
14
12
  assert(messageRegistry)
15
13
  const message: Message = { role, content }
16
14
  yield* emit(new MessageAppended(message))
package/L/model.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { assert } from "liminal-util"
2
- import { Context } from "../Context.ts"
3
2
  import { ModelRegistered } from "../LEvent.ts"
4
3
  import type { Model } from "../Model.ts"
5
4
  import { ModelRegistryContext } from "../ModelRegistry.ts"
@@ -9,8 +8,7 @@ import { emit } from "./emit.ts"
9
8
  export interface model extends Generator<Rune<ModelRegistered>, void> {}
10
9
 
11
10
  export function* model(model: Model): model {
12
- const context = Context.ensure()
13
- const registry = context.get(ModelRegistryContext)
11
+ const registry = ModelRegistryContext.get()
14
12
  assert(registry)
15
13
  registry.register(model)
16
14
  yield* emit(new ModelRegistered(model))
package/L/rune.ts CHANGED
@@ -1,30 +1,12 @@
1
1
  import { Fiber } from "../Fiber.ts"
2
2
  import { type Rune, RuneKey } from "../Rune.ts"
3
3
 
4
- export interface rune extends Iterable<Rune<never>, Fiber> {
5
- <R>(source: (fiber: Fiber) => R, debug?: string): Iterable<Rune<never>, Awaited<R>> & {
6
- <E>(): Generator<Rune<E>, Awaited<R>>
7
- }
4
+ export function* rune<R>(
5
+ source: (fiber: Fiber) => R,
6
+ debug?: string,
7
+ ): Generator<Rune<never>, Awaited<R>> {
8
+ return yield Object.assign(source, {
9
+ [RuneKey]: true,
10
+ debug,
11
+ }) as never
8
12
  }
9
- export const rune: rune = Object.assign(
10
- function<R>(source: (fiber: Fiber) => R, debug?: string) {
11
- return Object.assign(
12
- function*<E>(): Generator<Rune<E>, Awaited<R>> {
13
- return yield Object.assign(source, { [RuneKey]: true, debug } as never)
14
- },
15
- {
16
- *[Symbol.iterator](): Generator<Rune<never>, Awaited<R>> {
17
- return yield Object.assign(source, { [RuneKey]: true, debug } as never)
18
- },
19
- },
20
- )
21
- },
22
- {
23
- *[Symbol.iterator](): Generator<Rune<never>, Fiber> {
24
- return yield Object.assign((fiber: Fiber) => fiber, {
25
- [RuneKey]: true,
26
- debug: "get_current_fiber",
27
- } as never)
28
- },
29
- },
30
- )
package/L/strand.ts ADDED
@@ -0,0 +1,99 @@
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"
7
+ import type { Runic } from "../Runic.ts"
8
+ import { ToolRegistry, ToolRegistryContext } from "../ToolRegistry.ts"
9
+ import { rune } from "./rune.ts"
10
+
11
+ export interface StrandConfig<T = any, E = any> {
12
+ handler?: ((this: Fiber<T>, event: E) => void) | undefined
13
+ models?: ModelRegistry | undefined
14
+ messages?: MessageRegistry | undefined
15
+ tools?: ToolRegistry | undefined
16
+ signal?: AbortSignal | undefined
17
+ }
18
+
19
+ export interface strand<Y extends Rune, T> extends Iterable<Y, T>, PromiseLike<T> {}
20
+
21
+ export function strand<X extends Runic>(
22
+ runic: X,
23
+ config?: StrandConfig<Runic.T<X>, Rune.E<Runic.Y<X>>>,
24
+ ): strand<Runic.Y<X>, Runic.T<X>>
25
+ export function strand<XA extends Array<Runic>>(
26
+ runics: XA,
27
+ config?: StrandConfig<{ [I in keyof XA]: Runic.T<XA[I]> }, Rune.E<Runic.Y<XA[number]>>>,
28
+ ): strand<Runic.Y<XA[number]> | Rune<never>, { [I in keyof XA]: Runic.T<XA[I]> }>
29
+ export function strand<XR extends Record<keyof any, Runic>>(
30
+ runics: XR,
31
+ config?: StrandConfig<{ [K in keyof XR]: Runic.T<XR[K]> }, Rune.E<Runic.Y<XR[keyof XR]>>>,
32
+ ): strand<Runic.Y<XR[keyof XR]> | Rune<never>, { [K in keyof XR]: Runic.T<XR[K]> }>
33
+ export function strand(
34
+ value: Runic | Array<Runic> | Record<keyof any, Runic>,
35
+ config?: StrandConfig,
36
+ ): strand<Rune, any> {
37
+ return {
38
+ *[Symbol.iterator](): Generator<Rune, any> {
39
+ const parent = yield* Fiber
40
+ if (Array.isArray(value)) {
41
+ const fibers = value.map((runic) =>
42
+ new Fiber(runic, {
43
+ parent,
44
+ context: makeContext(),
45
+ })
46
+ )
47
+ return yield* rune(() => Promise.all(fibers.map((fiber) => fiber.resolution())), "strand")
48
+ } else if (typeof value === "object") {
49
+ const fibers = Object.values(value).map((runic) =>
50
+ new Fiber(runic, {
51
+ parent,
52
+ context: makeContext(),
53
+ })
54
+ )
55
+ return yield* rune(async () => {
56
+ const keys = Object.keys(value)
57
+ return await Promise
58
+ .all(fibers.map((fiber) => fiber.resolution()))
59
+ .then((resolved) => resolved.map((value, i) => [keys[i], value]))
60
+ .then(Object.fromEntries)
61
+ }, "strand")
62
+ }
63
+ const self = new Fiber(typeof value === "function" ? value() : value, {
64
+ parent,
65
+ context: makeContext(),
66
+ })
67
+ return yield* rune(() => self.resolution(), "strand")
68
+ },
69
+ then(onfulfilled, onrejected) {
70
+ return new Fiber(this, { context: makeContext() }).resolution().then(onfulfilled, onrejected)
71
+ },
72
+ }
73
+
74
+ function makeContext() {
75
+ let context = Context.get()?.fork()
76
+ if (!context) {
77
+ context = new Context([
78
+ [ModelRegistryContext, new ModelRegistry()],
79
+ [MessageRegistryContext, new MessageRegistry()],
80
+ [ToolRegistryContext, new ToolRegistry()],
81
+ ])
82
+ }
83
+ if (config) {
84
+ if ("handler" in config) {
85
+ context.set(HandlerContext, config.handler)
86
+ }
87
+ if ("models" in config) {
88
+ context.set(ModelRegistryContext, config.models?.clone() ?? new ModelRegistry())
89
+ }
90
+ if ("messages" in config) {
91
+ context.set(MessageRegistryContext, config.messages?.clone() ?? new MessageRegistry())
92
+ }
93
+ if ("tools" in config) {
94
+ context.set(ToolRegistryContext, config.tools?.clone() ?? new ToolRegistry())
95
+ }
96
+ }
97
+ return context
98
+ }
99
+ }
package/L/stream.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { assert } from "liminal-util"
2
+ import { InferenceRequested, type LEvent } from "../LEvent.ts"
3
+ import { MessageRegistryContext } from "../MessageRegistry.ts"
4
+ import { ModelRegistryContext } from "../ModelRegistry.ts"
5
+ import { type Rune } from "../Rune.ts"
6
+ import { RequestCounter } from "./_common.ts"
7
+ import { emit } from "./emit.ts"
8
+ import { rune } from "./rune.ts"
9
+
10
+ export interface stream extends Iterable<Rune<LEvent>, ReadableStream<string>> {}
11
+
12
+ export const stream: stream = {
13
+ *[Symbol.iterator](): Generator<Rune<LEvent>, ReadableStream<string>> {
14
+ const modelRegistry = ModelRegistryContext.get()
15
+ assert(modelRegistry)
16
+ const model = modelRegistry.peek()
17
+ assert(model)
18
+ const requestId = RequestCounter.next()
19
+ yield* emit(new InferenceRequested(requestId))
20
+ const messageRegistry = MessageRegistryContext.get()
21
+ assert(messageRegistry)
22
+ return yield* rune((fiber) =>
23
+ model
24
+ .seal({
25
+ messages: messageRegistry.messages,
26
+ signal: fiber.controller.signal,
27
+ })
28
+ .stream(), "stream")
29
+ },
30
+ }
package/L/system.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { isTemplateStringsArray } from "liminal-util"
2
2
  import type { LEvent } from "../LEvent.ts"
3
3
  import type { Rune } from "../Rune.ts"
4
- import { _message } from "./_message.ts"
4
+ import { message } from "./message.ts"
5
5
 
6
6
  export interface system extends Generator<Rune<LEvent>, void> {}
7
7
 
@@ -9,5 +9,5 @@ export function system(template: TemplateStringsArray, ...substitutions: Array<s
9
9
  export function system(value: string): system
10
10
  export function system(e0: TemplateStringsArray | string, ...rest: Array<string>): system {
11
11
  const part = isTemplateStringsArray(e0) ? String.raw(e0, ...rest) : e0
12
- return _message("system", [{ part }])
12
+ return message("system", [{ part }])
13
13
  }