@llm4ts/flow 2.35.2 → 2.35.4
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.
- package/dist/AutonomyContract.d.ts +3 -2
- package/dist/AutonomyContract.d.ts.map +1 -1
- package/dist/AutonomyContract.js +17 -4
- package/dist/AutonomyContract.js.map +1 -1
- package/dist/FlowEvents.d.ts +2 -0
- package/dist/FlowEvents.d.ts.map +1 -1
- package/dist/FlowEvents.js +3 -1
- package/dist/FlowEvents.js.map +1 -1
- package/dist/Review.d.ts.map +1 -1
- package/dist/Review.js +15 -2
- package/dist/Review.js.map +1 -1
- package/dist/Roster.d.ts +2 -0
- package/dist/Roster.d.ts.map +1 -1
- package/dist/Roster.js +21 -13
- package/dist/Roster.js.map +1 -1
- package/dist/RosterSeats.d.ts.map +1 -1
- package/dist/RosterSeats.js +3 -0
- package/dist/RosterSeats.js.map +1 -1
- package/dist/Timing.d.ts +4 -0
- package/dist/Timing.d.ts.map +1 -1
- package/dist/Timing.js +12 -0
- package/dist/Timing.js.map +1 -1
- package/package.json +2 -2
- package/src/AutonomyContract.ts +18 -4
- package/src/FlowEvents.ts +5 -1
- package/src/Review.ts +25 -2
- package/src/Roster.ts +27 -13
- package/src/RosterSeats.ts +3 -0
- package/src/Timing.ts +16 -0
package/src/Roster.ts
CHANGED
|
@@ -407,6 +407,8 @@ export interface LeaseOptions {
|
|
|
407
407
|
readonly prefer?: string
|
|
408
408
|
/** Who is asking, for the events (a story's worktree). */
|
|
409
409
|
readonly label?: string
|
|
410
|
+
/** What the call is for beyond its role (a review lens), for the events. */
|
|
411
|
+
readonly purpose?: string
|
|
410
412
|
/**
|
|
411
413
|
* The executor holding this context's coder, taken when independence
|
|
412
414
|
* cannot be had now: no executor outside `avoid` can ever take the role,
|
|
@@ -516,6 +518,9 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
516
518
|
}
|
|
517
519
|
}
|
|
518
520
|
|
|
521
|
+
const purposeOf = (who: LeaseOptions): { readonly purpose?: string } =>
|
|
522
|
+
who.purpose === undefined ? {} : { purpose: who.purpose }
|
|
523
|
+
|
|
519
524
|
const say = (message: string): Effect.Effect<void> =>
|
|
520
525
|
events.publish(Info.make({ message: `roster: ${message}` }))
|
|
521
526
|
|
|
@@ -599,13 +604,15 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
599
604
|
const leaseOf = (
|
|
600
605
|
spec: ExecutorSpec,
|
|
601
606
|
role: Role,
|
|
602
|
-
|
|
607
|
+
who: LeaseOptions,
|
|
603
608
|
because?: "nobody" | "held" | "out"
|
|
604
609
|
): Effect.Effect<Lease, never, Scope.Scope> =>
|
|
605
610
|
Effect.gen(function* () {
|
|
606
|
-
const labelled = label === undefined ? {} : { label }
|
|
611
|
+
const labelled = who.label === undefined ? {} : { label: who.label }
|
|
607
612
|
const own = because === undefined ? {} : { because }
|
|
608
|
-
yield* events.publish(
|
|
613
|
+
yield* events.publish(
|
|
614
|
+
ExecutorLeased.make({ executor: spec.id, role, ...labelled, ...purposeOf(who), ...own })
|
|
615
|
+
)
|
|
609
616
|
const done = yield* Ref.make(false)
|
|
610
617
|
const free = Effect.flatMap(Ref.getAndSet(done, true), (was) =>
|
|
611
618
|
was
|
|
@@ -623,13 +630,20 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
623
630
|
const borrowedLease = (
|
|
624
631
|
spec: ExecutorSpec,
|
|
625
632
|
role: Role,
|
|
626
|
-
|
|
633
|
+
who: LeaseOptions,
|
|
627
634
|
because: "nobody" | "held" | "out"
|
|
628
635
|
): Effect.Effect<Lease, never, Scope.Scope> =>
|
|
629
636
|
Effect.gen(function* () {
|
|
630
|
-
const labelled = label === undefined ? {} : { label }
|
|
637
|
+
const labelled = who.label === undefined ? {} : { label: who.label }
|
|
631
638
|
yield* events.publish(
|
|
632
|
-
ExecutorLeased.make({
|
|
639
|
+
ExecutorLeased.make({
|
|
640
|
+
executor: spec.id,
|
|
641
|
+
role,
|
|
642
|
+
...labelled,
|
|
643
|
+
...purposeOf(who),
|
|
644
|
+
borrowed: true,
|
|
645
|
+
because
|
|
646
|
+
})
|
|
633
647
|
)
|
|
634
648
|
const done = yield* Ref.make(false)
|
|
635
649
|
const free = Effect.flatMap(Ref.getAndSet(done, true), (was) =>
|
|
@@ -842,11 +856,11 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
842
856
|
})
|
|
843
857
|
yield* waited
|
|
844
858
|
return own !== undefined && own.id === borrow.id
|
|
845
|
-
? yield* leaseOf(own, role, leaseOptions
|
|
859
|
+
? yield* leaseOf(own, role, leaseOptions, because)
|
|
846
860
|
: own !== undefined
|
|
847
861
|
? // Someone came back between the check and the pick: independent after all.
|
|
848
|
-
yield* leaseOf(own, role, leaseOptions
|
|
849
|
-
: yield* borrowedLease(borrow, role, leaseOptions
|
|
862
|
+
yield* leaseOf(own, role, leaseOptions)
|
|
863
|
+
: yield* borrowedLease(borrow, role, leaseOptions, because)
|
|
850
864
|
})
|
|
851
865
|
let announced = false
|
|
852
866
|
const asked = yield* Clock.currentTimeMillis
|
|
@@ -867,7 +881,7 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
867
881
|
const spec = yield* attempt(role, leaseOptions)
|
|
868
882
|
if (spec !== undefined) {
|
|
869
883
|
yield* waited
|
|
870
|
-
return yield* leaseOf(spec, role, leaseOptions
|
|
884
|
+
return yield* leaseOf(spec, role, leaseOptions)
|
|
871
885
|
}
|
|
872
886
|
if (!(yield* canEverServe(role, avoid))) {
|
|
873
887
|
const own = yield* takeOwn("nobody")
|
|
@@ -906,14 +920,14 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
906
920
|
})
|
|
907
921
|
)
|
|
908
922
|
yield* say(
|
|
909
|
-
`waiting for an executor to take ${role}${leaseOptions.label === undefined ? "" : ` for ${leaseOptions.label}`}: ${yield* waitingReport(role, avoid)}`
|
|
923
|
+
`waiting for an executor to take ${role}${leaseOptions.label === undefined ? "" : ` for ${leaseOptions.label}`}${leaseOptions.purpose === undefined ? "" : ` (${leaseOptions.purpose})`}: ${yield* waitingReport(role, avoid)}`
|
|
910
924
|
)
|
|
911
925
|
}
|
|
912
926
|
yield* probeDue
|
|
913
927
|
const recovered = yield* attempt(role, leaseOptions)
|
|
914
928
|
if (recovered !== undefined) {
|
|
915
929
|
yield* waited
|
|
916
|
-
return yield* leaseOf(recovered, role, leaseOptions
|
|
930
|
+
return yield* leaseOf(recovered, role, leaseOptions)
|
|
917
931
|
}
|
|
918
932
|
yield* waitOrProbe(role)
|
|
919
933
|
}
|
|
@@ -924,7 +938,7 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
|
|
|
924
938
|
leaseOptions: LeaseOptions = {}
|
|
925
939
|
): Effect.Effect<Lease | undefined, never, Scope.Scope> =>
|
|
926
940
|
Effect.flatMap(attempt(role, leaseOptions), (spec) =>
|
|
927
|
-
spec === undefined ? Effect.succeed(undefined) : leaseOf(spec, role, leaseOptions
|
|
941
|
+
spec === undefined ? Effect.succeed(undefined) : leaseOf(spec, role, leaseOptions)
|
|
928
942
|
)
|
|
929
943
|
|
|
930
944
|
const exclude = (exclusion: Exclusion): Effect.Effect<void> =>
|
package/src/RosterSeats.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { LlmServiceShape } from "@llm4ts/core/LlmService"
|
|
|
13
13
|
import { Message, type ConnectorCapabilities, type LlmChunk } from "@llm4ts/core/Models"
|
|
14
14
|
import { describeFlowError, type FlowError } from "./FlowError.ts"
|
|
15
15
|
import { ExecutorHandedOver, type FlowEventsShape } from "./FlowEvents.ts"
|
|
16
|
+
import { callPurpose } from "./Timing.ts"
|
|
16
17
|
import {
|
|
17
18
|
describeExclusion,
|
|
18
19
|
hasRole,
|
|
@@ -141,10 +142,12 @@ export const rosterSeat = (
|
|
|
141
142
|
// The roster decides who serves: an independent executor, or, when
|
|
142
143
|
// none can ever serve or every one is held by a coder, the context's own.
|
|
143
144
|
const borrow = options.borrow === undefined ? undefined : yield* options.borrow
|
|
145
|
+
const purpose = yield* callPurpose
|
|
144
146
|
const lease = yield* roster
|
|
145
147
|
.lease(role, {
|
|
146
148
|
avoid,
|
|
147
149
|
...(options.label === undefined ? {} : { label: options.label }),
|
|
150
|
+
...(purpose === undefined ? {} : { purpose }),
|
|
148
151
|
...(borrow === undefined ? {} : { borrow })
|
|
149
152
|
})
|
|
150
153
|
.pipe(Effect.mapError(asLlmError))
|
package/src/Timing.ts
CHANGED
|
@@ -178,6 +178,22 @@ const TimedRole = Context.Reference<string | undefined>("@llm4ts/flow/Timing/Tim
|
|
|
178
178
|
defaultValue: () => undefined
|
|
179
179
|
})
|
|
180
180
|
|
|
181
|
+
/**
|
|
182
|
+
* What a call is for, beyond its role: a review lens, a vote. A roster
|
|
183
|
+
* lease names it (`topolino takes reviewer for home · adversarial lens`),
|
|
184
|
+
* so parallel calls of one role read as the different questions they are.
|
|
185
|
+
*/
|
|
186
|
+
const CallPurpose = Context.Reference<string | undefined>("@llm4ts/flow/Timing/CallPurpose", {
|
|
187
|
+
defaultValue: () => undefined
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
/** The purpose the current call is made for, when its caller named one. */
|
|
191
|
+
export const callPurpose: Effect.Effect<string | undefined> = CallPurpose
|
|
192
|
+
|
|
193
|
+
/** Runs `effect`'s calls under `purpose`, for the roster's lease events. */
|
|
194
|
+
export const withCallPurpose = <A, E, R>(purpose: string, effect: Effect.Effect<A, E, R>) =>
|
|
195
|
+
Effect.provideService(effect, CallPurpose, purpose)
|
|
196
|
+
|
|
181
197
|
/** The role the current call is made for: the caller's, or else `label`. */
|
|
182
198
|
export const roleOr = (label: string): Effect.Effect<string> =>
|
|
183
199
|
Effect.map(TimedRole, (role) => role ?? label)
|