liminal 0.5.8 → 0.5.10

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 (81) hide show
  1. package/Agent.ts +3 -0
  2. package/CHANGELOG.md +15 -0
  3. package/Context.ts +1 -10
  4. package/EventBase.ts +6 -0
  5. package/Fiber.ts +17 -3
  6. package/L/L.ts +1 -0
  7. package/L/_common.ts +6 -0
  8. package/L/_infer.ts +11 -12
  9. package/L/assistant.ts +1 -1
  10. package/L/branch.ts +9 -12
  11. package/L/catch.ts +3 -4
  12. package/L/emit.ts +1 -1
  13. package/L/rune.ts +24 -13
  14. package/L/stream.ts +32 -0
  15. package/LEvent.ts +10 -3
  16. package/Model.ts +13 -2
  17. package/ModelRegistry.ts +0 -8
  18. package/Rune.ts +1 -0
  19. package/Tool.ts +34 -0
  20. package/ToolRegistry.ts +5 -0
  21. package/dist/Agent.d.ts +2 -0
  22. package/dist/Agent.js +2 -0
  23. package/dist/Agent.js.map +1 -1
  24. package/dist/Context.d.ts +1 -2
  25. package/dist/Context.js +0 -8
  26. package/dist/Context.js.map +1 -1
  27. package/dist/EventBase.d.ts +1 -0
  28. package/dist/EventBase.js +5 -0
  29. package/dist/EventBase.js.map +1 -1
  30. package/dist/Fiber.d.ts +1 -3
  31. package/dist/Fiber.js +17 -2
  32. package/dist/Fiber.js.map +1 -1
  33. package/dist/L/L.d.ts +1 -0
  34. package/dist/L/L.js +1 -0
  35. package/dist/L/L.js.map +1 -1
  36. package/dist/L/_common.d.ts +4 -0
  37. package/dist/L/_common.js +7 -0
  38. package/dist/L/_common.js.map +1 -0
  39. package/dist/L/_infer.js +10 -10
  40. package/dist/L/_infer.js.map +1 -1
  41. package/dist/L/assistant.js +1 -1
  42. package/dist/L/assistant.js.map +1 -1
  43. package/dist/L/branch.js +9 -10
  44. package/dist/L/branch.js.map +1 -1
  45. package/dist/L/catch.js +3 -4
  46. package/dist/L/catch.js.map +1 -1
  47. package/dist/L/emit.js +1 -1
  48. package/dist/L/emit.js.map +1 -1
  49. package/dist/L/rune.d.ts +5 -3
  50. package/dist/L/rune.js +11 -4
  51. package/dist/L/rune.js.map +1 -1
  52. package/dist/L/stream.d.ts +5 -0
  53. package/dist/L/stream.js +29 -0
  54. package/dist/L/stream.js.map +1 -0
  55. package/dist/LEvent.d.ts +21 -1
  56. package/dist/LEvent.js +13 -2
  57. package/dist/LEvent.js.map +1 -1
  58. package/dist/Model.d.ts +12 -3
  59. package/dist/Model.js +3 -3
  60. package/dist/Model.js.map +1 -1
  61. package/dist/ModelRegistry.d.ts +0 -1
  62. package/dist/ModelRegistry.js +0 -7
  63. package/dist/ModelRegistry.js.map +1 -1
  64. package/dist/Rune.d.ts +1 -0
  65. package/dist/Rune.js.map +1 -1
  66. package/dist/Tool.d.ts +9 -0
  67. package/dist/Tool.js +20 -0
  68. package/dist/Tool.js.map +1 -0
  69. package/dist/ToolRegistry.d.ts +5 -0
  70. package/dist/ToolRegistry.js +5 -0
  71. package/dist/ToolRegistry.js.map +1 -0
  72. package/dist/index.d.ts +2 -0
  73. package/dist/index.js +2 -0
  74. package/dist/index.js.map +1 -1
  75. package/dist/tsconfig.tsbuildinfo +1 -1
  76. package/index.ts +2 -0
  77. package/package.json +3 -3
  78. package/cli/main.ts +0 -1
  79. package/dist/cli/main.d.ts +0 -1
  80. package/dist/cli/main.js +0 -3
  81. package/dist/cli/main.js.map +0 -1
package/Agent.ts CHANGED
@@ -5,11 +5,13 @@ import { MessageRegistry, MessageRegistryContext } from "./MessageRegistry.ts"
5
5
  import { ModelRegistry, ModelRegistryContext } from "./ModelRegistry.ts"
6
6
  import type { Rune } from "./Rune.ts"
7
7
  import type { Runic } from "./Runic.ts"
8
+ import { ToolRegistry, ToolRegistryContext } from "./ToolRegistry.ts"
8
9
 
9
10
  export interface AgentConfig<T, E> {
10
11
  handler?: ((this: Fiber<T>, event: E) => void) | undefined
11
12
  models?: ModelRegistry
12
13
  messages?: MessageRegistry
14
+ tools?: ToolRegistry
13
15
  signal?: AbortSignal | undefined
14
16
  }
15
17
 
@@ -28,6 +30,7 @@ export function Agent<Y extends Rune, T>(
28
30
  [HandlerContext, config?.handler],
29
31
  [ModelRegistryContext, config?.models ?? new ModelRegistry()],
30
32
  [MessageRegistryContext, config?.messages ?? new MessageRegistry()],
33
+ [ToolRegistryContext, config?.tools ?? new ToolRegistry()],
31
34
  ])
32
35
  .run(() => new Fiber(runic).resolution().then(onfulfilled, onrejected))
33
36
  },
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # liminal
2
2
 
3
+ ## 0.5.10
4
+
5
+ ### Patch Changes
6
+
7
+ - aef5564: Update Model interface to support streaming. Improve event-related functionality and emit fiber-related events.
8
+ - Updated dependencies [aef5564]
9
+ - liminal-schema@0.0.4
10
+ - liminal-util@0.0.5
11
+
12
+ ## 0.5.9
13
+
14
+ ### Patch Changes
15
+
16
+ - dbd5e93: Reintroduced tools and various examples.
17
+
3
18
  ## 0.5.8
4
19
 
5
20
  ### Patch Changes
package/Context.ts CHANGED
@@ -14,15 +14,6 @@ export class Context extends Map<ContextHandle, unknown> {
14
14
  return super.get(context) as never
15
15
  }
16
16
 
17
- getOrInit<V>(context: ContextHandle<V>, init: () => V): V {
18
- if (this.has(context)) {
19
- return this.get(context) as V
20
- }
21
- const instance = init()
22
- this.set(context, instance)
23
- return instance
24
- }
25
-
26
17
  set<V>(context: ContextHandle<V>, value: V): this {
27
18
  super.set(context, value)
28
19
  return this
@@ -44,7 +35,7 @@ export class Context extends Map<ContextHandle, unknown> {
44
35
  }
45
36
 
46
37
  export type ContextHandle<V = any> = {
47
- clone?: ((value: V) => V) | undefined
38
+ clone: ((value: V) => V) | undefined
48
39
  }
49
40
 
50
41
  export function ContextHandle<V>(clone?: (value: V) => V): ContextHandle<V> {
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,8 +1,9 @@
1
1
  import { attachCustomInspect } from "liminal-util"
2
2
  import { Context } from "./Context.ts"
3
+ import { type Handler, HandlerContext } from "./Handler.ts"
4
+ import { FiberCreated, FiberRejected, FiberResolved, FiberStarted } from "./LEvent.ts"
3
5
  import type { Rune } from "./Rune.ts"
4
6
  import { Runic } from "./Runic.ts"
5
-
6
7
  export type FiberStatus<T> = {
7
8
  type: "untouched"
8
9
  } | {
@@ -29,6 +30,7 @@ export class Fiber<T = any> {
29
30
  #runic: Runic<Rune, T>
30
31
  declare readonly parent?: Fiber
31
32
  #context: Context = Context.ensure()
33
+ #handler?: Handler = this.#context.get(HandlerContext)
32
34
 
33
35
  signal: AbortSignal
34
36
  either: AbortSignal
@@ -48,10 +50,11 @@ export class Fiber<T = any> {
48
50
  this.signal,
49
51
  ])
50
52
  this.abort = controller.abort.bind(controller)
53
+ this.#handler?.call(this, new FiberCreated())
51
54
  }
52
55
 
53
- static async join<F extends Array<Fiber>>(fibers: F): Promise<{ [I in keyof F]: F[I]["T"] }> {
54
- return await Promise.all(fibers.map((fiber) => fiber.resolution())) as never
56
+ fork<T>(runic: Runic<Rune, T>): Fiber<T> {
57
+ return new Fiber(runic, this)
55
58
  }
56
59
 
57
60
  resolution(this: Fiber<T>): Promise<T> {
@@ -64,6 +67,7 @@ export class Fiber<T = any> {
64
67
  self: this.signal,
65
68
  promise,
66
69
  }
70
+ this.#handler?.call(this, new FiberStarted())
67
71
  const iterator = Runic.unwrap(this.#runic)
68
72
  let nextArg: unknown
69
73
  this.#context.run(async () => {
@@ -75,9 +79,19 @@ export class Fiber<T = any> {
75
79
  current = await iterator.next(nextArg)
76
80
  }
77
81
  const { value } = current
82
+ this.status = {
83
+ type: "resolved",
84
+ value,
85
+ }
86
+ this.#handler?.call(this, new FiberResolved(value))
78
87
  abort()
79
88
  resolve(value)
80
89
  } catch (exception) {
90
+ this.status = {
91
+ type: "rejected",
92
+ exception,
93
+ }
94
+ this.#handler?.call(this, new FiberRejected(exception))
81
95
  abort(exception)
82
96
  reject(exception)
83
97
  }
package/L/L.ts CHANGED
@@ -6,5 +6,6 @@ export * from "./branch.ts"
6
6
  export * from "./catch.ts"
7
7
  export * from "./emit.ts"
8
8
  export * from "./model.ts"
9
+ export * from "./stream.ts"
9
10
  export * from "./system.ts"
10
11
  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/_infer.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import type { SchemaObject } from "liminal-schema"
2
2
  import { assert } from "liminal-util"
3
- import { Context, ContextHandle } from "../Context.ts"
3
+ import { Context } from "../Context.ts"
4
4
  import { InferenceRequested, Inferred, type LEvent } from "../LEvent.ts"
5
5
  import { MessageRegistryContext } from "../MessageRegistry.ts"
6
6
  import { ModelRegistryContext } from "../ModelRegistry.ts"
7
7
  import type { Rune } from "../Rune.ts"
8
+ import { RequestCounter } from "./_common.ts"
8
9
  import { emit } from "./emit.ts"
9
10
  import { rune } from "./rune.ts"
10
11
 
@@ -14,20 +15,18 @@ export function* _infer(schema?: SchemaObject): Generator<Rune<LEvent>, string>
14
15
  assert(modelRegistry)
15
16
  const model = modelRegistry.peek()
16
17
  assert(model)
17
- const requestId = context.getOrInit(InferenceRequestCounterContext, () => new InferenceRequestCounter()).next()
18
+ const requestId = RequestCounter.next()
18
19
  yield* emit(new InferenceRequested(requestId, schema))
19
20
  const messageRegistry = context.get(MessageRegistryContext)
20
21
  assert(messageRegistry)
21
- const inference = yield* rune(() => model.resolve(messageRegistry.messages, schema))
22
+ const inference = yield* rune((fiber) =>
23
+ model
24
+ .seal({
25
+ messages: messageRegistry.messages,
26
+ schema,
27
+ signal: fiber.signal,
28
+ })
29
+ .resolve(), "infer")
22
30
  yield* emit(new Inferred(requestId, inference))
23
31
  return inference
24
32
  }
25
-
26
- class InferenceRequestCounter {
27
- count: number = 0
28
- next(): number {
29
- return this.count++
30
- }
31
- }
32
-
33
- const InferenceRequestCounterContext: ContextHandle<InferenceRequestCounter> = ContextHandle()
package/L/assistant.ts CHANGED
@@ -15,7 +15,7 @@ export const assistant: assistant = Object.assign(
15
15
  const inference = yield* _infer(schema)
16
16
  yield* _message("assistant", [{ part: inference }])
17
17
  const input = JSON.parse(inference)
18
- return yield* rune(() => validate(type, input))
18
+ return yield* rune(() => validate(type, input), "validate_assistant_message")
19
19
  },
20
20
  {
21
21
  *[Symbol.iterator]() {
package/L/branch.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Context } from "../Context.ts"
2
- import { Fiber } from "../Fiber.ts"
3
2
  import { type Rune } from "../Rune.ts"
4
3
  import type { Runic } from "../Runic.ts"
5
4
  import { rune } from "./rune.ts"
@@ -15,22 +14,20 @@ export function branch<XR extends Record<keyof any, Runic>>(
15
14
  ): branch<Runic.Y<XR[keyof XR]> | Rune<never>, { [K in keyof XR]: Runic.T<XR[K]> }>
16
15
  export function* branch(value: Runic | Array<Runic> | Record<keyof any, Runic>): branch<Rune, any> {
17
16
  const context = Context.ensure()
18
- const parent = yield* rune((fiber) => fiber)
17
+ const parent = yield* rune
19
18
  if (Array.isArray(value)) {
20
- const fibers = value.map((runic) => context.clone().run(() => new Fiber(runic, parent)))
21
- return yield* rune(() => Fiber.join(fibers))
19
+ const fibers = value.map((runic) => context.clone().run(() => parent.fork(runic)))
20
+ return yield* rune(() => Promise.all(fibers.map((fiber) => fiber.resolution())), "branch")
22
21
  } else if (typeof value === "object") {
23
- const fibers = Object.values(value).map(
24
- (runic) => context.clone().run(() => new Fiber(runic, parent)),
25
- )
22
+ const fibers = Object.values(value).map((runic) => context.clone().run(() => parent.fork(runic)))
26
23
  return yield* rune(async () => {
27
24
  const keys = Object.keys(value)
28
- return await Fiber
29
- .join(fibers)
25
+ return await Promise
26
+ .all(fibers.map((fiber) => fiber.resolution()))
30
27
  .then((resolved) => resolved.map((value, i) => [keys[i], value]))
31
28
  .then(Object.fromEntries)
32
- })
29
+ }, "branch")
33
30
  }
34
- const fiber = context.clone().run(() => new Fiber(typeof value === "function" ? value() : value, parent))
35
- return yield* rune(() => fiber.resolution())
31
+ const fiber = context.clone().run(() => parent.fork(typeof value === "function" ? value() : value))
32
+ return yield* rune(() => fiber.resolution(), "branch")
36
33
  }
package/L/catch.ts CHANGED
@@ -1,17 +1,16 @@
1
- import { Fiber } from "../Fiber.ts"
2
1
  import type { Rune } from "../Rune.ts"
3
2
  import type { Runic } from "../Runic.ts"
4
3
  import { rune } from "./rune.ts"
5
4
 
6
5
  export { catch_ as catch }
7
6
  function* catch_<Y extends Rune, T>(runic: Runic<Y, T>): Generator<Rune<Y>, CatchResult<T>> {
8
- return yield* rune(async () => {
7
+ return yield* rune(async (fiber) => {
9
8
  try {
10
- return { resolved: await new Fiber(runic).resolution() }
9
+ return { resolved: await fiber.fork(runic).resolution() }
11
10
  } catch (exception: unknown) {
12
11
  return { rejected: exception }
13
12
  }
14
- })
13
+ }, "catch")
15
14
  }
16
15
  Object.defineProperty(catch_, "name", { value: "catch" })
17
16
 
package/L/emit.ts CHANGED
@@ -9,6 +9,6 @@ export interface emit<E> extends Generator<Rune<E>, void> {}
9
9
  export function* emit<const E>(event: EnsureNarrow<E>): emit<E> {
10
10
  const context = Context.ensure()
11
11
  const handler = context.get(HandlerContext)
12
- const fiber = yield* rune((fiber) => fiber)
12
+ const fiber = yield* rune
13
13
  handler?.call(fiber, event)
14
14
  }
package/L/rune.ts CHANGED
@@ -1,19 +1,30 @@
1
1
  import { Fiber } from "../Fiber.ts"
2
2
  import { type Rune, RuneKey } from "../Rune.ts"
3
3
 
4
- export interface rune<T> extends Iterable<Rune<never>, T> {
5
- <E>(): Generator<Rune<E>, T>
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
+ }
6
8
  }
7
-
8
- export function rune<R>(source: (fiber: Fiber) => R): rune<Awaited<R>> {
9
- return Object.assign(
10
- function*<E>(): Generator<Rune<E>, Awaited<R>> {
11
- return yield Object.assign(source, { [RuneKey]: true } as never)
12
- },
13
- {
14
- *[Symbol.iterator](): Generator<Rune<never>, Awaited<R>> {
15
- return yield Object.assign(source, { [RuneKey]: true } as never)
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)
16
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)
17
28
  },
18
- )
19
- }
29
+ },
30
+ )
package/L/stream.ts ADDED
@@ -0,0 +1,32 @@
1
+ import { assert } from "liminal-util"
2
+ import { Context } from "../Context.ts"
3
+ import { InferenceRequested, type LEvent } from "../LEvent.ts"
4
+ import { MessageRegistryContext } from "../MessageRegistry.ts"
5
+ import { ModelRegistryContext } from "../ModelRegistry.ts"
6
+ import { type Rune } from "../Rune.ts"
7
+ import { RequestCounter } from "./_common.ts"
8
+ import { emit } from "./emit.ts"
9
+ import { rune } from "./rune.ts"
10
+
11
+ export interface stream extends Iterable<Rune<LEvent>, ReadableStream<string>> {}
12
+
13
+ export const stream: stream = {
14
+ *[Symbol.iterator](): Generator<Rune<LEvent>, ReadableStream<string>> {
15
+ const context = Context.ensure()
16
+ const modelRegistry = context.get(ModelRegistryContext)
17
+ assert(modelRegistry)
18
+ const model = modelRegistry.peek()
19
+ assert(model)
20
+ const requestId = RequestCounter.next()
21
+ yield* emit(new InferenceRequested(requestId))
22
+ const messageRegistry = context.get(MessageRegistryContext)
23
+ assert(messageRegistry)
24
+ return yield* rune((fiber) =>
25
+ model
26
+ .seal({
27
+ messages: messageRegistry.messages,
28
+ signal: fiber.signal,
29
+ })
30
+ .stream(), "stream")
31
+ },
32
+ }
package/LEvent.ts CHANGED
@@ -12,6 +12,12 @@ export type LEvent =
12
12
  | MessageAppended
13
13
  | ModelRegistered
14
14
 
15
+ export namespace LEvent {
16
+ export function is(value: unknown): value is LEvent {
17
+ return typeof value === "object" && value !== null && "brand" in value && value.brand === LEventTag
18
+ }
19
+ }
20
+
15
21
  export const LEventTag: unique symbol = Symbol.for("liminal/LEvent")
16
22
  export type LEventTag = typeof LEventTag
17
23
 
@@ -56,7 +62,8 @@ export class FiberResolved extends EventBase(LEventTag, "fiber_resolved") {
56
62
  super()
57
63
  }
58
64
  }
59
-
60
- export function isLEvent(value: unknown): value is LEvent {
61
- return typeof value === "object" && value !== null && LEventTag in value
65
+ export class FiberRejected extends EventBase(LEventTag, "fiber_rejected") {
66
+ constructor(readonly reason: any) {
67
+ super()
68
+ }
62
69
  }
package/Model.ts CHANGED
@@ -1,14 +1,25 @@
1
- import type { Schema } from "liminal-schema"
1
+ import type { SchemaObject } from "liminal-schema"
2
2
  import { attachCustomInspect } from "liminal-util"
3
3
  import type { Message } from "./Message.ts"
4
4
 
5
5
  export class Model {
6
6
  constructor(
7
7
  readonly vendor: string,
8
- readonly resolve: (messages: Array<Message>, schema?: Schema) => Promise<string>,
8
+ readonly seal: (envelope: Envelope) => SealedEnvelope,
9
9
  ) {}
10
10
 
11
11
  static {
12
12
  attachCustomInspect(this, ({ vendor }) => ({ vendor }))
13
13
  }
14
14
  }
15
+
16
+ export interface Envelope {
17
+ messages: Array<Message>
18
+ schema?: SchemaObject | undefined
19
+ signal?: AbortSignal
20
+ }
21
+
22
+ export interface SealedEnvelope {
23
+ resolve(): Promise<string>
24
+ stream(): ReadableStream<string>
25
+ }
package/ModelRegistry.ts CHANGED
@@ -6,14 +6,6 @@ export class ModelRegistry {
6
6
  declare head?: ModelRegistryNode | undefined
7
7
  declare tail?: ModelRegistryNode | undefined
8
8
 
9
- constructor(models?: Array<Model>) {
10
- if (models) {
11
- for (const model of models) {
12
- this.register(model)
13
- }
14
- }
15
- }
16
-
17
9
  peek() {
18
10
  return this.tail?.model
19
11
  }
package/Rune.ts CHANGED
@@ -4,6 +4,7 @@ export interface Rune<out E = any> {
4
4
  E: E
5
5
  (fiber: Fiber): any
6
6
  [RuneKey]: true
7
+ debug?: string
7
8
  }
8
9
 
9
10
  export declare namespace Rune {
package/Tool.ts ADDED
@@ -0,0 +1,34 @@
1
+ import {
2
+ type LType,
3
+ Schema,
4
+ type SchemaObject,
5
+ toJSONSchema,
6
+ validate,
7
+ type Value,
8
+ type ValueObject,
9
+ } from "liminal-schema"
10
+
11
+ export class Tool {
12
+ static async make<T extends ValueObject>(
13
+ description: string,
14
+ type: LType<T>,
15
+ f: (arg: T) => Value | Promise<Value>,
16
+ ) {
17
+ const schema = toJSONSchema(type)
18
+ return new Tool(
19
+ await Schema.id(schema, description),
20
+ description,
21
+ schema,
22
+ async (arg) => {
23
+ return await f(await validate(type, arg) as never)
24
+ },
25
+ )
26
+ }
27
+
28
+ constructor(
29
+ readonly name: string,
30
+ readonly description: string,
31
+ readonly parameterSchema: SchemaObject,
32
+ readonly f: (arg: any) => Value | Promise<Value>,
33
+ ) {}
34
+ }
@@ -0,0 +1,5 @@
1
+ import { ContextHandle } from "liminal"
2
+ import type { Tool } from "./Tool"
3
+
4
+ export class ToolRegistry extends Set<Tool> {}
5
+ export const ToolRegistryContext: ContextHandle<ToolRegistry> = ContextHandle()
package/dist/Agent.d.ts CHANGED
@@ -3,10 +3,12 @@ import { MessageRegistry } from "./MessageRegistry.ts";
3
3
  import { ModelRegistry } from "./ModelRegistry.ts";
4
4
  import type { Rune } from "./Rune.ts";
5
5
  import type { Runic } from "./Runic.ts";
6
+ import { ToolRegistry } from "./ToolRegistry.ts";
6
7
  export interface AgentConfig<T, E> {
7
8
  handler?: ((this: Fiber<T>, event: E) => void) | undefined;
8
9
  models?: ModelRegistry;
9
10
  messages?: MessageRegistry;
11
+ tools?: ToolRegistry;
10
12
  signal?: AbortSignal | undefined;
11
13
  }
12
14
  export interface Agent<out T, out E> extends PromiseLike<T> {
package/dist/Agent.js CHANGED
@@ -3,6 +3,7 @@ import { Fiber } from "./Fiber.js";
3
3
  import { HandlerContext } from "./Handler.js";
4
4
  import { MessageRegistry, MessageRegistryContext } from "./MessageRegistry.js";
5
5
  import { ModelRegistry, ModelRegistryContext } from "./ModelRegistry.js";
6
+ import { ToolRegistry, ToolRegistryContext } from "./ToolRegistry.js";
6
7
  export function Agent(runic, config) {
7
8
  return {
8
9
  then(onfulfilled, onrejected) {
@@ -10,6 +11,7 @@ export function Agent(runic, config) {
10
11
  [HandlerContext, config?.handler],
11
12
  [ModelRegistryContext, config?.models ?? new ModelRegistry()],
12
13
  [MessageRegistryContext, config?.messages ?? new MessageRegistry()],
14
+ [ToolRegistryContext, config?.tools ?? new ToolRegistry()],
13
15
  ])
14
16
  .run(() => new Fiber(runic).resolution().then(onfulfilled, onrejected));
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,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,MAAkC;IAElC,OAAO;QACL,IAAI,CAAC,WAAW,EAAE,UAAU;YAC1B,OAAO,IAAI,OAAO,CAAC;gBACjB,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;iBACC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAA;QAC3E,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;AAGxE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAerE,MAAM,UAAU,KAAK,CACnB,KAAkB,EAClB,MAAkC;IAElC,OAAO;QACL,IAAI,CAAC,WAAW,EAAE,UAAU;YAC1B,OAAO,IAAI,OAAO,CAAC;gBACjB,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;gBACnE,CAAC,mBAAmB,EAAE,MAAM,EAAE,KAAK,IAAI,IAAI,YAAY,EAAE,CAAC;aAC3D,CAAC;iBACC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAA;QAC3E,CAAC;KACsD,CAAA;AAC3D,CAAC"}
package/dist/Context.d.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  export declare class Context extends Map<ContextHandle, unknown> {
2
2
  static ensure(): Context;
3
3
  get<V>(context: ContextHandle<V>): V | undefined;
4
- getOrInit<V>(context: ContextHandle<V>, init: () => V): V;
5
4
  set<V>(context: ContextHandle<V>, value: V): this;
6
5
  run<R>(callback: () => R): R;
7
6
  clone(overrides?: Iterable<[ContextHandle, unknown]>): Context;
8
7
  }
9
8
  export type ContextHandle<V = any> = {
10
- clone?: ((value: V) => V) | undefined;
9
+ clone: ((value: V) => V) | undefined;
11
10
  };
12
11
  export declare function ContextHandle<V>(clone?: (value: V) => V): ContextHandle<V>;
package/dist/Context.js CHANGED
@@ -10,14 +10,6 @@ export class Context extends Map {
10
10
  get(context) {
11
11
  return super.get(context);
12
12
  }
13
- getOrInit(context, init) {
14
- if (this.has(context)) {
15
- return this.get(context);
16
- }
17
- const instance = init();
18
- this.set(context, instance);
19
- return instance;
20
- }
21
13
  set(context, value) {
22
14
  super.set(context, value);
23
15
  return this;
@@ -1 +1 @@
1
- {"version":3,"file":"Context.js","sourceRoot":"","sources":["../Context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEpD,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAW,CAAA;AAEhD,MAAM,OAAO,OAAQ,SAAQ,GAA2B;IACtD,MAAM,CAAC,MAAM;QACX,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAA;QAClC,MAAM,CAAC,OAAO,CAAC,CAAA;QACf,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,GAAG,CAAI,OAAyB;QAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAU,CAAA;IACpC,CAAC;IAED,SAAS,CAAI,OAAyB,EAAE,IAAa;QACnD,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAM,CAAA;QAC/B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,EAAE,CAAA;QACvB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC3B,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,GAAG,CAAI,OAAyB,EAAE,KAAQ;QACxC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,GAAG,CAAI,QAAiB;QACtB,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,SAA8C;QAClD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAA;QACtC,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAMD,MAAM,UAAU,aAAa,CAAI,KAAuB;IACtD,OAAO,EAAE,KAAK,EAAE,CAAA;AAClB,CAAC"}
1
+ {"version":3,"file":"Context.js","sourceRoot":"","sources":["../Context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEpD,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAW,CAAA;AAEhD,MAAM,OAAO,OAAQ,SAAQ,GAA2B;IACtD,MAAM,CAAC,MAAM;QACX,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAA;QAClC,MAAM,CAAC,OAAO,CAAC,CAAA;QACf,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,GAAG,CAAI,OAAyB;QAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAU,CAAA;IACpC,CAAC;IAED,GAAG,CAAI,OAAyB,EAAE,KAAQ;QACxC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,GAAG,CAAI,QAAiB;QACtB,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,SAA8C;QAClD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAA;QACtC,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAMD,MAAM,UAAU,aAAa,CAAI,KAAuB;IACtD,OAAO,EAAE,KAAK,EAAE,CAAA;AAClB,CAAC"}
@@ -7,4 +7,5 @@ export declare function EventBase<B extends symbol, K extends string>(brand: B,
7
7
  readonly brand: B;
8
8
  readonly type: K;
9
9
  };
10
+ is<T>(this: new (...args: any) => T, value: unknown): value is T;
10
11
  };
package/dist/EventBase.js CHANGED
@@ -1,6 +1,11 @@
1
1
  import { attachCustomInspect } from "liminal-util";
2
2
  export function EventBase(brand, type) {
3
3
  return class {
4
+ static is(value) {
5
+ return typeof value === "object" && value !== null
6
+ && "brand" in value && value.brand === brand
7
+ && "type" in value && value.type === type;
8
+ }
4
9
  brand = brand;
5
10
  type = type;
6
11
  static {
@@ -1 +1 @@
1
- {"version":3,"file":"EventBase.js","sourceRoot":"","sources":["../EventBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAOlD,MAAM,UAAU,SAAS,CAAqC,KAAQ,EAAE,IAAO;IAC7E,OAAO;QACI,KAAK,GAAG,KAAK,CAAA;QACb,IAAI,GAAG,IAAI,CAAA;QAEpB;YACE,mBAAmB,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAA;QACvE,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"EventBase.js","sourceRoot":"","sources":["../EventBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAOlD,MAAM,UAAU,SAAS,CAAqC,KAAQ,EAAE,IAAO;IAC7E,OAAO;QACL,MAAM,CAAC,EAAE,CAAkC,KAAc;YACvD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;mBAC7C,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK;mBACzC,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAA;QAC7C,CAAC;QAEQ,KAAK,GAAG,KAAK,CAAA;QACb,IAAI,GAAG,IAAI,CAAA;QAEpB;YACE,mBAAmB,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAA;QACvE,CAAC;KACF,CAAA;AACH,CAAC"}
package/dist/Fiber.d.ts CHANGED
@@ -27,8 +27,6 @@ export declare class Fiber<T = any> {
27
27
  abort: (reason?: any) => void;
28
28
  status: FiberStatus<T>;
29
29
  constructor(runic: Runic<Rune, T>, parent?: Fiber);
30
- static join<F extends Array<Fiber>>(fibers: F): Promise<{
31
- [I in keyof F]: F[I]["T"];
32
- }>;
30
+ fork<T>(runic: Runic<Rune, T>): Fiber<T>;
33
31
  resolution(this: Fiber<T>): Promise<T>;
34
32
  }
package/dist/Fiber.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import { attachCustomInspect } from "liminal-util";
2
2
  import { Context } from "./Context.js";
3
+ import { HandlerContext } from "./Handler.js";
4
+ import { FiberCreated, FiberRejected, FiberResolved, FiberStarted } from "./LEvent.js";
3
5
  import { Runic } from "./Runic.js";
4
6
  export class Fiber {
5
7
  static nextIndex = 0;
6
8
  index = Fiber.nextIndex++;
7
9
  #runic;
8
10
  #context = Context.ensure();
11
+ #handler = this.#context.get(HandlerContext);
9
12
  signal;
10
13
  either;
11
14
  abort;
@@ -22,9 +25,10 @@ export class Fiber {
22
25
  this.signal,
23
26
  ]);
24
27
  this.abort = controller.abort.bind(controller);
28
+ this.#handler?.call(this, new FiberCreated());
25
29
  }
26
- static async join(fibers) {
27
- return await Promise.all(fibers.map((fiber) => fiber.resolution()));
30
+ fork(runic) {
31
+ return new Fiber(runic, this);
28
32
  }
29
33
  resolution() {
30
34
  const { status, abort } = this;
@@ -36,6 +40,7 @@ export class Fiber {
36
40
  self: this.signal,
37
41
  promise,
38
42
  };
43
+ this.#handler?.call(this, new FiberStarted());
39
44
  const iterator = Runic.unwrap(this.#runic);
40
45
  let nextArg;
41
46
  this.#context.run(async () => {
@@ -47,10 +52,20 @@ export class Fiber {
47
52
  current = await iterator.next(nextArg);
48
53
  }
49
54
  const { value } = current;
55
+ this.status = {
56
+ type: "resolved",
57
+ value,
58
+ };
59
+ this.#handler?.call(this, new FiberResolved(value));
50
60
  abort();
51
61
  resolve(value);
52
62
  }
53
63
  catch (exception) {
64
+ this.status = {
65
+ type: "rejected",
66
+ exception,
67
+ };
68
+ this.#handler?.call(this, new FiberRejected(exception));
54
69
  abort(exception);
55
70
  reject(exception);
56
71
  }