liminal 0.5.10 → 0.5.12

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