liminal 0.5.14 → 0.5.16

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 (107) hide show
  1. package/{Model.ts → Adapter.ts} +5 -5
  2. package/AdapterRegistry.ts +78 -0
  3. package/CHANGELOG.md +12 -0
  4. package/Config.ts +2 -2
  5. package/Context.ts +24 -7
  6. package/Definition.ts +16 -0
  7. package/L/L.ts +1 -2
  8. package/L/all.ts +4 -0
  9. package/L/assistant.ts +4 -0
  10. package/L/catch.ts +4 -0
  11. package/L/continuation.ts +3 -2
  12. package/L/emit.ts +6 -2
  13. package/L/focus.ts +17 -0
  14. package/L/infer.ts +18 -14
  15. package/L/message.ts +4 -0
  16. package/L/reflect.ts +2 -1
  17. package/L/run.ts +4 -3
  18. package/L/strand.ts +6 -2
  19. package/L/stream.ts +4 -5
  20. package/LEvent.ts +5 -5
  21. package/Rune.ts +36 -7
  22. package/Strand.ts +37 -6
  23. package/dist/{Model.d.ts → Adapter.d.ts} +5 -5
  24. package/dist/Adapter.js +13 -0
  25. package/dist/Adapter.js.map +1 -0
  26. package/dist/AdapterRegistry.d.ts +27 -0
  27. package/dist/AdapterRegistry.js +62 -0
  28. package/dist/AdapterRegistry.js.map +1 -0
  29. package/dist/Config.d.ts +2 -2
  30. package/dist/Config.js +1 -1
  31. package/dist/Config.js.map +1 -1
  32. package/dist/Context.d.ts +21 -2
  33. package/dist/Context.js +9 -4
  34. package/dist/Context.js.map +1 -1
  35. package/dist/Definition.d.ts +14 -0
  36. package/dist/Definition.js +11 -0
  37. package/dist/Definition.js.map +1 -1
  38. package/dist/L/L.d.ts +1 -2
  39. package/dist/L/L.js +1 -2
  40. package/dist/L/L.js.map +1 -1
  41. package/dist/L/all.d.ts +4 -0
  42. package/dist/L/all.js.map +1 -1
  43. package/dist/L/assistant.d.ts +4 -0
  44. package/dist/L/assistant.js.map +1 -1
  45. package/dist/L/catch.d.ts +4 -0
  46. package/dist/L/catch.js +4 -0
  47. package/dist/L/catch.js.map +1 -1
  48. package/dist/L/continuation.d.ts +1 -0
  49. package/dist/L/continuation.js +3 -2
  50. package/dist/L/continuation.js.map +1 -1
  51. package/dist/L/emit.d.ts +4 -0
  52. package/dist/L/emit.js +6 -2
  53. package/dist/L/emit.js.map +1 -1
  54. package/dist/L/focus.d.ts +8 -0
  55. package/dist/L/focus.js +14 -0
  56. package/dist/L/focus.js.map +1 -0
  57. package/dist/L/infer.d.ts +4 -0
  58. package/dist/L/infer.js +11 -9
  59. package/dist/L/infer.js.map +1 -1
  60. package/dist/L/message.d.ts +4 -0
  61. package/dist/L/message.js +4 -0
  62. package/dist/L/message.js.map +1 -1
  63. package/dist/L/reflect.d.ts +1 -0
  64. package/dist/L/reflect.js +2 -1
  65. package/dist/L/reflect.js.map +1 -1
  66. package/dist/L/run.d.ts +3 -2
  67. package/dist/L/run.js +2 -2
  68. package/dist/L/run.js.map +1 -1
  69. package/dist/L/strand.d.ts +4 -0
  70. package/dist/L/strand.js +6 -2
  71. package/dist/L/strand.js.map +1 -1
  72. package/dist/L/stream.d.ts +1 -0
  73. package/dist/L/stream.js +4 -5
  74. package/dist/L/stream.js.map +1 -1
  75. package/dist/LEvent.d.ts +7 -7
  76. package/dist/LEvent.js +4 -4
  77. package/dist/LEvent.js.map +1 -1
  78. package/dist/Rune.d.ts +29 -8
  79. package/dist/Rune.js +2 -0
  80. package/dist/Rune.js.map +1 -1
  81. package/dist/Strand.d.ts +24 -0
  82. package/dist/Strand.js +27 -4
  83. package/dist/Strand.js.map +1 -1
  84. package/dist/index.d.ts +2 -2
  85. package/dist/index.js +2 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/tsconfig.tsbuildinfo +1 -1
  88. package/dist/util/JSONValue.d.ts +1 -1
  89. package/dist/util/JSONValue.js +21 -9
  90. package/dist/util/JSONValue.js.map +1 -1
  91. package/index.ts +2 -2
  92. package/package.json +1 -1
  93. package/util/JSONValue.ts +23 -8
  94. package/L/context.ts +0 -12
  95. package/L/model.ts +0 -13
  96. package/ModelRegistry.ts +0 -55
  97. package/dist/L/context.d.ts +0 -2
  98. package/dist/L/context.js +0 -12
  99. package/dist/L/context.js.map +0 -1
  100. package/dist/L/model.d.ts +0 -4
  101. package/dist/L/model.js +0 -10
  102. package/dist/L/model.js.map +0 -1
  103. package/dist/Model.js +0 -13
  104. package/dist/Model.js.map +0 -1
  105. package/dist/ModelRegistry.d.ts +0 -15
  106. package/dist/ModelRegistry.js +0 -43
  107. package/dist/ModelRegistry.js.map +0 -1
@@ -3,14 +3,14 @@ import type { SchemaObject } from "./Schema.ts"
3
3
  import type { Tool } from "./Tool.ts"
4
4
  import { attachCustomInspect } from "./util/attachCustomInspect.ts"
5
5
 
6
- export class Model {
6
+ export class Adapter {
7
7
  constructor(
8
- readonly vendor: string,
8
+ readonly name: string,
9
9
  readonly seal: (envelope: Envelope) => SealedEnvelope,
10
10
  ) {}
11
11
 
12
12
  static {
13
- attachCustomInspect(this, ({ vendor }) => ({ vendor }))
13
+ attachCustomInspect(this, ({ name }) => ({ name }))
14
14
  }
15
15
  }
16
16
 
@@ -22,6 +22,6 @@ export interface Envelope {
22
22
  }
23
23
 
24
24
  export interface SealedEnvelope {
25
- resolve(): Promise<string>
26
- stream(): ReadableStream<string>
25
+ resolve: () => Promise<string>
26
+ stream: () => ReadableStream<string>
27
27
  }
@@ -0,0 +1,78 @@
1
+ import type { Adapter } from "./Adapter.ts"
2
+ import { LiminalAssertionError } from "./LiminalAssertionError.ts"
3
+
4
+ /**
5
+ * An intrusive doubly-linked list for storing `Model`s.
6
+ * Provides efficient insertion, removal, and lookups.
7
+ */
8
+ export class AdapterRegistry {
9
+ declare head?: ModelRegistryNode | undefined
10
+ declare tail?: ModelRegistryNode | undefined
11
+
12
+ /** Returns the most recently registered model */
13
+ peek() {
14
+ return this.tail?.adapter
15
+ }
16
+
17
+ /** Ensure */
18
+ ensure(): Adapter {
19
+ LiminalAssertionError.assert(
20
+ this.tail,
21
+ "No conversation adapter registered. Use `L.focus` to focus a conversation adapter.",
22
+ )
23
+ return this.tail.adapter
24
+ }
25
+
26
+ /**
27
+ * Registers a new model and returns the created node
28
+ * @param value The model to register
29
+ */
30
+ register(value: Adapter): ModelRegistryNode {
31
+ const node: ModelRegistryNode = {
32
+ prev: this.tail,
33
+ adapter: value,
34
+ }
35
+ if (this.tail) {
36
+ this.tail.next = node
37
+ } else {
38
+ this.head = node
39
+ }
40
+ this.tail = node
41
+ return node
42
+ }
43
+
44
+ /** Remove a model from the registry. */
45
+ remove(node: ModelRegistryNode) {
46
+ if (node.prev) {
47
+ node.prev.next = node.next
48
+ }
49
+ if (node.next) {
50
+ node.next.prev = node.prev
51
+ }
52
+ if (node === this.head) {
53
+ this.head = node.next
54
+ }
55
+ if (node === this.tail) {
56
+ this.tail = node.prev
57
+ }
58
+ node.prev = undefined
59
+ delete node.next
60
+ }
61
+
62
+ /** Creates a deep copy of this registry. */
63
+ clone() {
64
+ const instance = new AdapterRegistry()
65
+ for (let node = this.head; node; node = node.next) {
66
+ if (node.adapter) {
67
+ instance.register(node.adapter)
68
+ }
69
+ }
70
+ return instance
71
+ }
72
+ }
73
+
74
+ export interface ModelRegistryNode {
75
+ prev: ModelRegistryNode | undefined
76
+ adapter: Adapter
77
+ next?: ModelRegistryNode | undefined
78
+ }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # liminal
2
2
 
3
+ ## 0.5.16
4
+
5
+ ### Patch Changes
6
+
7
+ - 6e70190: Renaming Model to Adapter and L.model to L.focus
8
+
9
+ ## 0.5.15
10
+
11
+ ### Patch Changes
12
+
13
+ - 9c276c3: Fix message list cloning, add streaming to ollama adapter.
14
+
3
15
  ## 0.5.14
4
16
 
5
17
  ### Patch Changes
package/Config.ts CHANGED
@@ -1,12 +1,12 @@
1
+ import { AdapterRegistry } from "./AdapterRegistry.ts"
1
2
  import type { Message } from "./Message.ts"
2
- import { ModelRegistry } from "./ModelRegistry.ts"
3
3
  import type { Rune } from "./Rune.ts"
4
4
  import type { Strand } from "./Strand.ts"
5
5
  import type { Tool } from "./Tool.ts"
6
6
 
7
7
  export interface Config<Y extends Rune<any> = Rune<any>, T = any> {
8
8
  handler?: ((this: Strand<Y, T>, event: Rune.E<Y>) => void) | undefined
9
- models?: ModelRegistry | undefined
9
+ models?: AdapterRegistry | undefined
10
10
  messages?: Array<Message>
11
11
  tools?: Set<Tool> | undefined
12
12
  signal?: AbortSignal | undefined
package/Context.ts CHANGED
@@ -1,28 +1,45 @@
1
+ import { AdapterRegistry } from "./AdapterRegistry.ts"
1
2
  import type { Handler } from "./Handler.ts"
2
3
  import type { Message } from "./Message.ts"
3
- import { ModelRegistry } from "./ModelRegistry.ts"
4
4
  import type { Tool } from "./Tool.ts"
5
5
 
6
+ /**
7
+ * Context represents the execution environment for a Strand.
8
+ *
9
+ * It holds all the stateful components needed during strand execution:
10
+ * - Message history.
11
+ * - Event handler for processing events.
12
+ * - Model registry for tracking available language models.
13
+ * - Available tools for model-driven function calling.
14
+ */
6
15
  export interface Context {
16
+ /** Event handler for processing events during strand execution. */
7
17
  readonly handler: Handler | undefined
8
- readonly models: ModelRegistry
18
+ /** Registry of available models for inference. */
19
+ readonly adapters: AdapterRegistry
20
+ /** Accumulated message history. */
9
21
  readonly messages: Array<Message>
22
+ /** Set of tools available to the models. */
10
23
  readonly tools: Set<Tool>
11
-
24
+ /** Creates a copy of the current `Context` for child strands. */
12
25
  clone(): Context
13
26
  }
14
27
 
28
+ /**
29
+ * Factory function to create a new Context.
30
+ * @param context Optional base context from which to initialize.
31
+ * @returns A newly created Context.
32
+ */
15
33
  export function Context(context?: Omit<Context, "clone">): Context {
16
34
  return {
17
35
  handler: context?.handler,
18
- models: context?.models.clone() ?? new ModelRegistry(),
19
- messages: [],
36
+ adapters: context?.adapters?.clone() ?? new AdapterRegistry(),
37
+ messages: [...(context?.messages ?? [])],
20
38
  tools: new Set(context?.tools),
21
-
22
39
  clone(): Context {
23
40
  return {
24
41
  handler: this.handler,
25
- models: this.models.clone(),
42
+ adapters: this.adapters.clone(),
26
43
  messages: [...this.messages],
27
44
  tools: new Set(this.tools),
28
45
  clone: this.clone,
package/Definition.ts CHANGED
@@ -1,22 +1,38 @@
1
1
  import type { Rune } from "./Rune.ts"
2
2
 
3
3
  export type RuneIterator<Y extends Rune<any> = Rune<any>, T = any> = Iterator<Y, T> | AsyncIterator<Y, T>
4
+
4
5
  export type RuneIterable<Y extends Rune<any> = Rune<any>, T = any> = Iterable<Y, T> | AsyncIterable<Y, T>
6
+
5
7
  export type Definition<Y extends Rune<any> = Rune<any>, T = any> = RuneIterable<Y, T> | (() => RuneIterable<Y, T>)
6
8
 
7
9
  export namespace Definition {
10
+ /** Extracts the Rune type from a Definition. */
8
11
  export type Y<X extends Definition> = X extends RuneIterable<infer Y> ? Y
9
12
  : X extends () => RuneIterable<infer Y> ? Y
10
13
  : X extends RuneIterator<infer Y> ? Y
11
14
  : never
12
15
 
16
+ /** Extracts the result type from a Definition. */
13
17
  export type T<X extends Definition> = X extends RuneIterable<Rune<any>, infer T> ? T
14
18
  : X extends () => RuneIterable<Rune<any>, infer T> ? T
15
19
  : X extends RuneIterator<Rune<any>, infer T> ? T
16
20
  : never
17
21
 
22
+ /** Extracts the event type from a Definition. */
18
23
  export type E<X extends Definition> = Rune.E<Y<X>>
19
24
 
25
+ /**
26
+ * Converts a Definition into a RuneIterator.
27
+ *
28
+ * This function handles all the different forms a Definition can take:
29
+ * - Synchronous iterables
30
+ * - Asynchronous iterables
31
+ * - Factory functions returning iterables
32
+ *
33
+ * @param definition The definition to unwrap.
34
+ * @returns A RuneIterator ready for consumption.
35
+ */
20
36
  export function unwrap<Y extends Rune<any>, T>(definition: Definition<Y, T>): RuneIterator<Y, T> {
21
37
  if (Symbol.iterator in definition) {
22
38
  return definition[Symbol.iterator]()
package/L/L.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  export * from "./all.ts"
2
2
  export * from "./assistant.ts"
3
3
  export * from "./catch.ts"
4
- export * from "./context.ts"
5
4
  export * from "./continuation.ts"
6
5
  export * from "./emit.ts"
6
+ export * from "./focus.ts"
7
7
  export * from "./infer.ts"
8
8
  export * from "./message.ts"
9
- export * from "./model.ts"
10
9
  export * from "./reflect.ts"
11
10
  export * from "./run.ts"
12
11
  export * from "./schema/anyOf.ts"
package/L/all.ts CHANGED
@@ -6,6 +6,10 @@ import { Strand } from "../Strand.ts"
6
6
  import { continuation } from "./continuation.ts"
7
7
  import { reflect } from "./reflect.ts"
8
8
 
9
+ /**
10
+ * Runs multiple definitions in parallel and collects their results.
11
+ * Can be used with an array or object of definitions.
12
+ */
9
13
  export function all<A extends Array<Definition>>(
10
14
  definitions: A,
11
15
  context?: Context,
package/L/assistant.ts CHANGED
@@ -4,6 +4,10 @@ import { Schema } from "../Schema.ts"
4
4
  import { infer } from "./infer.ts"
5
5
  import { message } from "./message.ts"
6
6
 
7
+ /**
8
+ * Produces an assistant message when yielded. Can be called with a schema
9
+ * for structured output. Otherwise produces a string.
10
+ */
7
11
  export interface assistant extends Iterable<Rune<LEvent>, string> {
8
12
  <T>(schema: Schema<T>): Generator<Rune<LEvent>, T>
9
13
  }
package/L/catch.ts CHANGED
@@ -7,6 +7,10 @@ import { reflect } from "./reflect.ts"
7
7
 
8
8
  export { catch_ as catch }
9
9
 
10
+ /**
11
+ * Error handling utility that catches exceptions from running a definition.
12
+ * Returns a result object indicating whether the operation succeeded or failed.
13
+ */
10
14
  function* catch_<Y extends Rune<any>, T>(
11
15
  definition: Definition<Y, T>,
12
16
  ): Generator<Rune<LEvent> | Rune<Y>, CatchResult<T>> {
package/L/continuation.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import type { LEvent } from "../LEvent.ts"
2
2
  import { Rune, RuneKey } from "../Rune.ts"
3
3
 
4
+ /** Yields a continuation rune that executes a function and passes its result to the next iteration. */
4
5
  export function* continuation<R>(debug: string, f: () => R): Generator<Rune<LEvent>, Awaited<R>> {
5
6
  return yield {
6
7
  [RuneKey]: true,
7
- value: {
8
- kind: "continuation",
8
+ instruction: {
9
+ kind: "continue",
9
10
  debug,
10
11
  f,
11
12
  },
package/L/emit.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  import { Rune, RuneKey } from "../Rune.ts"
2
2
  import type { EnsureNarrow } from "../util/EnsureNarrow.ts"
3
3
 
4
+ /**
5
+ * Emits an event to be supplied to handlers.
6
+ * Used for broadcasting state changes and triggering side effects.
7
+ */
4
8
  export function* emit<E>(event: EnsureNarrow<E>): Generator<Rune<E>, void> {
5
9
  return yield {
6
10
  [RuneKey]: true,
7
- value: {
8
- kind: "event",
11
+ instruction: {
12
+ kind: "emit",
9
13
  event,
10
14
  },
11
15
  }
package/L/focus.ts ADDED
@@ -0,0 +1,17 @@
1
+ import type { Adapter } from "../Adapter.ts"
2
+ import type { LEvent } from "../LEvent.ts"
3
+ import { AdapterFocused } from "../LEvent.ts"
4
+ import type { Rune } from "../Rune.ts"
5
+ import { emit } from "./emit.ts"
6
+ import { reflect } from "./reflect.ts"
7
+
8
+ /**
9
+ * Registers a model in the current context and emits a model registration event.
10
+ * Returns the registered model instance.
11
+ */
12
+ export function* focus(adapter: Adapter): Generator<Rune<LEvent>, Adapter> {
13
+ const { context: { adapters } } = yield* reflect
14
+ adapters.register(adapter)
15
+ yield* emit(new AdapterFocused(adapter))
16
+ return adapter
17
+ }
package/L/infer.ts CHANGED
@@ -1,27 +1,31 @@
1
1
  import { InferenceRequested, Inferred, type LEvent } from "../LEvent.ts"
2
- import { LiminalAssertionError } from "../LiminalAssertionError.ts"
3
2
  import type { Rune } from "../Rune.ts"
4
3
  import { Schema } from "../Schema.ts"
5
4
  import { continuation } from "./continuation.ts"
6
5
  import { emit } from "./emit.ts"
7
6
  import { reflect } from "./reflect.ts"
8
7
 
8
+ /**
9
+ * Requests an inference from the current model, optionally with a schema.
10
+ * Emits inference-related events and returns the model's response as a string.
11
+ */
9
12
  export function* infer(schema?: Schema): Generator<Rune<LEvent>, string> {
10
- const { context: { models, messages }, signal } = yield* reflect
11
- const model = models.peek()
12
- LiminalAssertionError.assert(model)
13
+ const { context: { adapters: models, messages }, signal } = yield* reflect
14
+ const model = models.ensure()
13
15
  const requestId = crypto.randomUUID()
14
16
  yield* emit(new InferenceRequested(requestId, schema))
15
- let inference = yield* continuation("infer", () =>
16
- model.seal({
17
- messages,
18
- ...schema && {
19
- schema: schema.type === "object"
20
- ? schema
21
- : Schema.wrap(schema),
22
- },
23
- signal,
24
- }).resolve())
17
+ let inference = yield* continuation(
18
+ "infer",
19
+ model
20
+ .seal({
21
+ messages,
22
+ ...schema && {
23
+ schema: schema.type === "object" ? schema : Schema.wrap(schema),
24
+ },
25
+ signal,
26
+ })
27
+ .resolve,
28
+ )
25
29
  if (schema?.type && schema.type !== "object") {
26
30
  inference = JSON.stringify(JSON.parse(inference).value)
27
31
  }
package/L/message.ts CHANGED
@@ -4,6 +4,10 @@ import type { Rune } from "../Rune.ts"
4
4
  import { emit } from "./emit.ts"
5
5
  import { reflect } from "./reflect.ts"
6
6
 
7
+ /**
8
+ * Adds a new message to the current context's message list.
9
+ * Emits a message append event to observers.
10
+ */
7
11
  export function* message(role: MessageRole, content: Array<Content>): Generator<Rune<LEvent>, void> {
8
12
  const { context: { messages } } = yield* reflect
9
13
  const message: Message = { role, parts: content }
package/L/reflect.ts CHANGED
@@ -2,11 +2,12 @@ import type { LEvent } from "../LEvent.ts"
2
2
  import { Rune, RuneKey } from "../Rune.ts"
3
3
  import type { Strand } from "../Strand.ts"
4
4
 
5
+ /** Returns the current strand instance, providing access to context and parent information. */
5
6
  export const reflect: Iterable<Rune<LEvent>, Strand> = {
6
7
  *[Symbol.iterator]() {
7
8
  return yield {
8
9
  [RuneKey]: true,
9
- value: { kind: "reflect" },
10
+ instruction: { kind: "reflect" },
10
11
  }
11
12
  },
12
13
  }
package/L/run.ts CHANGED
@@ -1,15 +1,16 @@
1
+ import { AdapterRegistry } from "../AdapterRegistry.ts"
1
2
  import { Context } from "../Context.ts"
2
3
  import type { Definition } from "../Definition.ts"
3
4
  import type { Handler } from "../Handler.ts"
4
5
  import type { Message } from "../Message.ts"
5
- import { ModelRegistry } from "../ModelRegistry.ts"
6
6
  import type { Rune } from "../Rune.ts"
7
7
  import { Strand } from "../Strand.ts"
8
8
  import type { Tool } from "../Tool.ts"
9
9
 
10
+ /** Configuration options for running a definition. */
10
11
  export interface RunConfig<Y extends Rune<any>> {
11
12
  handler?: Handler<Y> | undefined
12
- models?: ModelRegistry | undefined
13
+ models?: AdapterRegistry | undefined
13
14
  messages?: Array<Message> | undefined
14
15
  tools?: Set<Tool> | undefined
15
16
  signal?: AbortSignal | undefined
@@ -18,7 +19,7 @@ export interface RunConfig<Y extends Rune<any>> {
18
19
  export function run<Y extends Rune<any>, T>(definition: Definition<Y, T>, config?: RunConfig<Y>): Strand<Y, T> {
19
20
  const context = Context({
20
21
  handler: config?.handler,
21
- models: config?.models ?? new ModelRegistry(),
22
+ adapters: config?.models ?? new AdapterRegistry(),
22
23
  messages: config?.messages ?? [],
23
24
  tools: config?.tools ?? new Set(),
24
25
  })
package/L/strand.ts CHANGED
@@ -3,14 +3,18 @@ import type { Definition } from "../Definition.ts"
3
3
  import type { LEvent } from "../LEvent.ts"
4
4
  import { type Rune, RuneKey } from "../Rune.ts"
5
5
 
6
+ /**
7
+ * Creates a child strand that executes a definition.
8
+ * Optionally specify the context. Otherwise the current context is inherited.
9
+ */
6
10
  export function* strand<Y extends Rune<any>, T>(
7
11
  definition: Definition<Y, T>,
8
12
  context?: Context,
9
13
  ): Generator<Rune<LEvent>, T> {
10
14
  return yield {
11
15
  [RuneKey]: true,
12
- value: {
13
- kind: "child",
16
+ instruction: {
17
+ kind: "create_child",
14
18
  definition,
15
19
  context,
16
20
  },
package/L/stream.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  import { InferenceRequested, type LEvent } from "../LEvent.ts"
2
- import { LiminalAssertionError } from "../LiminalAssertionError.ts"
3
2
  import type { Rune } from "../Rune.ts"
4
3
  import { continuation } from "./continuation.ts"
5
4
  import { emit } from "./emit.ts"
6
5
  import { reflect } from "./reflect.ts"
7
6
 
7
+ /** Creates a readable stream of content from the current model. */
8
8
  export const stream: Iterable<Rune<LEvent>, ReadableStream<string>> = {
9
9
  *[Symbol.iterator]() {
10
- const { context: { models, messages }, signal } = yield* reflect
11
- const model = models.peek()
12
- LiminalAssertionError.assert(model)
10
+ const { context: { adapters, messages }, signal } = yield* reflect
11
+ const adapter = adapters.ensure()
13
12
  const requestId = crypto.randomUUID()
14
13
  yield* emit(new InferenceRequested(requestId))
15
- return yield* continuation("stream", () => model.seal({ messages, signal }).stream())
14
+ return yield* continuation("stream", adapter.seal({ messages, signal }).stream)
16
15
  },
17
16
  }
package/LEvent.ts CHANGED
@@ -1,15 +1,15 @@
1
+ import type { Adapter } from "./Adapter.ts"
1
2
  import { EventBase } from "./EventBase.ts"
2
3
  import type { Message } from "./Message.ts"
3
- import type { Model } from "./Model.ts"
4
4
  import type { Schema } from "./Schema.ts"
5
5
  import type { StrandStatus } from "./Strand.ts"
6
6
 
7
7
  export type LEvent =
8
- | StrandStatusChanged
8
+ | AdapterFocused
9
9
  | InferenceRequested
10
10
  | Inferred
11
11
  | MessageAppended
12
- | ModelRegistered
12
+ | StrandStatusChanged
13
13
 
14
14
  export namespace LEvent {
15
15
  export function is(value: unknown): value is LEvent {
@@ -20,8 +20,8 @@ export namespace LEvent {
20
20
  export const LEventTag: unique symbol = Symbol.for("liminal/LEvent")
21
21
  export type LEventTag = typeof LEventTag
22
22
 
23
- export class ModelRegistered extends EventBase(LEventTag, "model_registered") {
24
- constructor(readonly model: Model) {
23
+ export class AdapterFocused extends EventBase(LEventTag, "adapter_focused") {
24
+ constructor(readonly adapter: Adapter) {
25
25
  super()
26
26
  }
27
27
  }
package/Rune.ts CHANGED
@@ -1,31 +1,60 @@
1
1
  import type { Context } from "./Context.ts"
2
2
  import type { Definition } from "./Definition.ts"
3
3
 
4
+ /**
5
+ * `Rune` represents a computational unit within a Strand execution.
6
+ * It is a specialized protocol for expressing different kinds of operations
7
+ * that can be yielded from generator functions to control message state
8
+ * and concurrency within the Liminal runtime.
9
+ * @template E The event type this Rune can handle
10
+ */
4
11
  export interface Rune<E> {
5
12
  [RuneKey]: true
6
- value: {
7
- kind: "continuation"
13
+ instruction: RuneInstruction<E>
14
+ }
15
+
16
+ export type RuneInstruction<E> =
17
+ | RuneInstruction.Continue
18
+ | RuneInstruction.Emit<E>
19
+ | RuneInstruction.Reflect
20
+ | RuneInstruction.CreateChild
21
+ export namespace RuneInstruction {
22
+ /** Tells the runtime to call this function and and pass the result to the next iteration. */
23
+ export interface Continue {
24
+ kind: "continue"
8
25
  debug: string
9
26
  f: () => any
10
- } | {
11
- kind: "event"
27
+ }
28
+
29
+ /** Dispatch an event to the registered handler. */
30
+ export interface Emit<E> {
31
+ kind: "emit"
12
32
  event: E
13
- } | {
33
+ }
34
+
35
+ /** Tells the runtime to provide a reference to the current strand */
36
+ export interface Reflect {
14
37
  kind: "reflect"
15
- } | {
16
- kind: "child"
38
+ }
39
+
40
+ /** Creates a nested execution context with its own definition. */
41
+ export interface CreateChild {
42
+ kind: "create_child"
17
43
  definition: Definition
18
44
  context?: Context | undefined
19
45
  }
20
46
  }
21
47
 
22
48
  export namespace Rune {
49
+ /** Extract the event type from a Rune type. */
23
50
  export type E<X extends Rune<any>> = X extends Rune<infer E> ? E : never
24
51
 
52
+ /** Type guard to check if a value is a Rune. */
25
53
  export function is(value: unknown): value is Rune<any> {
26
54
  return typeof value === "object" && value !== null && RuneKey in value
27
55
  }
28
56
  }
29
57
 
58
+ /** Symbol used to identify Rune objects. */
30
59
  export const RuneKey: unique symbol = Symbol.for("liminal/RuneKey")
31
60
  export type RuneKey = typeof RuneKey