@xandreed/core 0.3.0 → 0.8.0-next.0
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/README.md +1 -1
- package/dist/conformance.entity.d.ts +15 -0
- package/dist/conformance.entity.js +7 -0
- package/dist/decision-record.entity.d.ts +31 -0
- package/dist/decision-record.entity.functions.d.ts +6 -0
- package/dist/decision-record.entity.functions.js +3 -0
- package/dist/decision-record.entity.js +24 -0
- package/dist/domain/agent-failure.entity.d.ts +6 -6
- package/dist/domain/agent-failure.entity.js +12 -1
- package/dist/domain/failure.entity.d.ts +2 -2
- package/dist/domain/loop-event.entity.d.ts +2 -0
- package/dist/domain/message.entity.d.ts +143 -156
- package/dist/domain/message.entity.js +6 -6
- package/dist/domain/model-call-policy.entity.d.ts +3 -3
- package/dist/domain/model-call-policy.entity.js +1 -1
- package/dist/domain/model-catalog.entity.d.ts +4 -4
- package/dist/domain/model-catalog.entity.js +1 -1
- package/dist/domain/model-selection.entity.d.ts +6 -13
- package/dist/domain/prompt-provenance.entity.d.ts +6 -6
- package/dist/domain/prompt-provenance.entity.js +4 -4
- package/dist/domain/token-usage.entity.d.ts +4 -4
- package/dist/harness/capability.entity.d.ts +88 -41
- package/dist/harness/capability.entity.functions.d.ts +30 -1
- package/dist/harness/capability.entity.functions.js +55 -2
- package/dist/harness/capability.entity.js +33 -12
- package/dist/harness/config.entity.d.ts +28 -28
- package/dist/harness/config.entity.js +4 -4
- package/dist/harness/plugin-stack.adapter.d.ts +24 -0
- package/dist/harness/plugin-stack.adapter.js +8 -0
- package/dist/harness/plugin-stack.adapter.test.d.ts +1 -0
- package/dist/harness/plugin.adapter.d.ts +15 -4
- package/dist/harness/plugin.adapter.js +18 -11
- package/dist/harness/plugin.adapter.test.d.ts +1 -0
- package/dist/harness/plugin.entity.d.ts +26 -10
- package/dist/harness/plugin.entity.js +1 -1
- package/dist/harness/session.entity.d.ts +20 -20
- package/dist/harness/session.entity.js +1 -1
- package/dist/harness/skill-files.d.ts +17 -0
- package/dist/harness/skill-files.js +25 -0
- package/dist/index.d.ts +48 -4
- package/dist/index.js +46 -4
- package/dist/loop/cacheKey.d.ts +3 -3
- package/dist/loop/cacheKey.js +4 -2
- package/dist/loop/mapping.d.ts +4 -5
- package/dist/loop/mapping.js +8 -16
- package/dist/loop/modelPolicy.d.ts +4 -4
- package/dist/loop/modelPolicy.js +2 -2
- package/dist/loop/promptProvenance.d.ts +2 -2
- package/dist/loop/promptProvenance.js +2 -2
- package/dist/loop/stepContext.d.ts +2 -2
- package/dist/loop/stepContext.js +2 -2
- package/dist/loop/streamFold.js +3 -3
- package/dist/loop/toolSchema.d.ts +17 -0
- package/dist/loop/toolSchema.js +25 -0
- package/dist/loop/toolSchema.test.d.ts +1 -0
- package/dist/mcp/bridge.d.ts +15 -15
- package/dist/mcp/bridge.js +14 -14
- package/dist/memory/memory-log.entity.d.ts +320 -0
- package/dist/memory/memory-log.entity.functions.d.ts +89 -0
- package/dist/memory/memory-log.entity.functions.js +180 -0
- package/dist/memory/memory-log.entity.js +75 -0
- package/dist/memory/memory-log.entity.test.d.ts +1 -0
- package/dist/memory/memory-session.d.ts +51 -0
- package/dist/memory/memory-session.js +97 -0
- package/dist/memory/memory-session.test.d.ts +1 -0
- package/dist/memory/memory.conformance.d.ts +32 -0
- package/dist/memory/memory.conformance.js +102 -0
- package/dist/ports/auth-store.port.d.ts +16 -18
- package/dist/ports/auth-store.port.js +13 -9
- package/dist/ports/capability.port.d.ts +131 -7
- package/dist/ports/capability.port.js +2 -2
- package/dist/ports/conversation-store.port.d.ts +54 -177
- package/dist/ports/conversation-store.port.js +9 -9
- package/dist/ports/file-system.port.d.ts +5 -7
- package/dist/ports/file-system.port.js +1 -1
- package/dist/ports/harness.port.d.ts +19 -13
- package/dist/ports/harness.port.js +10 -10
- package/dist/ports/mcp-client.port.d.ts +15 -47
- package/dist/ports/mcp-client.port.js +3 -3
- package/dist/ports/memory.port.d.ts +116 -0
- package/dist/ports/memory.port.js +7 -0
- package/dist/ports/model-catalog.port.d.ts +1 -1
- package/dist/ports/model-catalog.port.js +1 -1
- package/dist/ports/permission.port.d.ts +10 -0
- package/dist/ports/permission.port.js +4 -0
- package/dist/ports/run-context.port.d.ts +28 -0
- package/dist/ports/run-context.port.js +4 -0
- package/dist/ports/session-log.port.d.ts +25 -0
- package/dist/ports/session-log.port.js +4 -0
- package/dist/ports/sessions.port.d.ts +141 -0
- package/dist/ports/sessions.port.js +4 -0
- package/dist/ports/settings-store.port.d.ts +18 -56
- package/dist/ports/settings-store.port.js +3 -3
- package/dist/ports/shell.port.d.ts +9 -21
- package/dist/ports/shell.port.js +1 -1
- package/dist/ports/step-loop.port.d.ts +85 -0
- package/dist/ports/step-loop.port.js +4 -0
- package/dist/ports/tasks.port.d.ts +59 -0
- package/dist/ports/tasks.port.js +10 -0
- package/dist/ports/tool-registry.port.d.ts +53 -0
- package/dist/ports/tool-registry.port.js +4 -0
- package/dist/ports/turn-admission.port.d.ts +23 -0
- package/dist/ports/turn-admission.port.js +4 -0
- package/dist/ports/turn-events.port.d.ts +55 -0
- package/dist/ports/turn-events.port.js +7 -0
- package/dist/ports/turn-scope.port.d.ts +101 -0
- package/dist/ports/turn-scope.port.js +10 -0
- package/dist/ports/turn.port.d.ts +113 -0
- package/dist/ports/turn.port.js +0 -0
- package/dist/ports/utility-llm.port.d.ts +12 -31
- package/dist/ports/utility-llm.port.js +1 -1
- package/dist/session/chassis.js +7 -7
- package/dist/session/session-event.entity.d.ts +55 -0
- package/dist/session/session-event.entity.functions.d.ts +31 -0
- package/dist/session/session-event.entity.functions.js +42 -0
- package/dist/session/session-event.entity.js +37 -0
- package/dist/session/session-event.entity.test.d.ts +1 -0
- package/dist/session/session-log.conformance.d.ts +13 -0
- package/dist/session/session-log.conformance.js +167 -0
- package/dist/session/session-log.entity.d.ts +164 -0
- package/dist/session/session-log.entity.js +82 -0
- package/dist/session/session-log.memory.adapter.d.ts +7 -0
- package/dist/session/session-log.memory.adapter.js +82 -0
- package/dist/session/session-log.memory.adapter.test.d.ts +1 -0
- package/dist/session/sessions.entity.d.ts +201 -0
- package/dist/session/sessions.entity.js +98 -0
- package/dist/session/tasks.entity.d.ts +39 -0
- package/dist/session/tasks.entity.js +26 -0
- package/dist/session/turn-admission.open.adapter.d.ts +4 -0
- package/dist/session/turn-admission.open.adapter.js +3 -0
- package/dist/spec/SpecDoc.d.ts +30 -117
- package/dist/spec/SpecDoc.js +10 -10
- package/dist/spec/codec.js +1 -1
- package/dist/turn/model-request.entity.d.ts +99 -0
- package/dist/turn/model-request.entity.functions.d.ts +108 -0
- package/dist/turn/model-request.entity.functions.js +167 -0
- package/dist/turn/model-request.entity.js +41 -0
- package/dist/turn/model-request.entity.test.d.ts +1 -0
- package/dist/turn/prompt-sections.d.ts +10 -0
- package/dist/turn/prompt-sections.js +3 -0
- package/dist/turn/step-loop.conformance.d.ts +16 -0
- package/dist/turn/step-loop.conformance.js +164 -0
- package/dist/turn/testing.d.ts +30 -0
- package/dist/turn/turn-bus.d.ts +23 -0
- package/dist/turn/turn-bus.js +54 -0
- package/dist/turn/turn-bus.test.d.ts +1 -0
- package/dist/turn/turn-event.entity.d.ts +263 -0
- package/dist/turn/turn-event.entity.functions.d.ts +35 -0
- package/dist/turn/turn-event.entity.functions.js +21 -0
- package/dist/turn/turn-event.entity.js +101 -0
- package/dist/turn/turn-lifecycle.d.ts +32 -0
- package/dist/turn/turn-lifecycle.js +48 -0
- package/dist/turn/turn-run.d.ts +26 -0
- package/dist/turn/turn-run.js +105 -0
- package/dist/turn/turn.adapter.d.ts +21 -0
- package/dist/turn/turn.adapter.js +126 -0
- package/dist/turn/turn.adapter.test.d.ts +1 -0
- package/dist/turn/turn.conformance.d.ts +20 -0
- package/dist/turn/turn.conformance.js +74 -0
- package/dist/turn/user-message.entity.d.ts +14 -0
- package/dist/turn/user-message.entity.js +10 -0
- package/dist/util/json.d.ts +2 -2
- package/dist/util/json.js +10 -10
- package/package.json +2 -3
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect, Option } from "effect";
|
|
3
|
+
import type { ConversationId } from "../domain/message.entity.js";
|
|
4
|
+
import type { HarnessError } from "../harness/plugin.entity.js";
|
|
5
|
+
import type { JsonObject, SessionExists, SessionLogError, SessionMissing } from "../session/session-log.entity.js";
|
|
6
|
+
import type { SessionAddress } from "../session/sessions.entity.js";
|
|
7
|
+
import type { TaskMissing, TaskMode, TaskRefused, TaskView } from "../session/tasks.entity.js";
|
|
8
|
+
import type { TurnWriter } from "./sessions.port.js";
|
|
9
|
+
import type { TurnOutcome } from "./turn.port.js";
|
|
10
|
+
declare const Tasks_base: Context.ServiceClass<Tasks, "efferent/Tasks", {
|
|
11
|
+
readonly start: (parent: SessionAddress, input: {
|
|
12
|
+
/** Stable across retries: starting the same task twice starts it once. */
|
|
13
|
+
readonly taskId?: ConversationId;
|
|
14
|
+
readonly instructions: string;
|
|
15
|
+
readonly mode: TaskMode;
|
|
16
|
+
readonly meta?: JsonObject;
|
|
17
|
+
}) => Effect.Effect<TaskView, TaskRefused | SessionExists | SessionMissing | SessionLogError>;
|
|
18
|
+
readonly status: (parent: SessionAddress, taskId: string) => Effect.Effect<TaskView, TaskMissing | SessionMissing | SessionLogError>;
|
|
19
|
+
readonly list: (parent: SessionAddress) => Effect.Effect<ReadonlyArray<TaskView>, SessionMissing | SessionLogError>;
|
|
20
|
+
/** Stop a task: its child's turn is cancelled and nothing is delivered. */
|
|
21
|
+
readonly cancel: (parent: SessionAddress, taskId: string) => Effect.Effect<boolean, TaskMissing | SessionMissing | SessionLogError>;
|
|
22
|
+
/** Deliver finished results a runner lost, and start tasks that never ran. */
|
|
23
|
+
readonly reconcile: (parent: SessionAddress) => Effect.Effect<{
|
|
24
|
+
readonly delivered: number;
|
|
25
|
+
readonly started: number;
|
|
26
|
+
}, SessionMissing | SessionLogError>;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Background tasks of a session. A task is one turn of a child session: a
|
|
30
|
+
* fork (its history is the conversation so far) or a spawn (it starts
|
|
31
|
+
* empty); the child's id is the task's. Starting records `task.started` in
|
|
32
|
+
* the parent and hands the work to the host's TaskRunner; when the child's
|
|
33
|
+
* turn ends, its result is delivered to the parent's inbox (once) and the
|
|
34
|
+
* parent is drained, so it reacts after the answer in flight. `reconcile`
|
|
35
|
+
* finishes what a lost runner left undone; its caller drains.
|
|
36
|
+
*/
|
|
37
|
+
export declare class Tasks extends Tasks_base {
|
|
38
|
+
}
|
|
39
|
+
declare const TaskRunner_base: Context.ServiceClass<TaskRunner, "efferent/TaskRunner", {
|
|
40
|
+
readonly run: (work: (deadline: Option.Option<number>) => Effect.Effect<void>) => Effect.Effect<void>;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Where background work runs: a fiber of this process, or the host's own
|
|
44
|
+
* mechanism (e.g. a serverless waitUntil). `run` returns once the work is
|
|
45
|
+
* handed over; the work is told when it must be done by (Clock time), if
|
|
46
|
+
* the runner has a limit, so a task ends interrupted rather than lost.
|
|
47
|
+
*/
|
|
48
|
+
export declare class TaskRunner extends TaskRunner_base {
|
|
49
|
+
}
|
|
50
|
+
declare const TaskExecutor_base: Context.ServiceClass<TaskExecutor, "efferent/TaskExecutor", {
|
|
51
|
+
/** Run the child's turn on its writer (the tasks plugin ends it). */
|
|
52
|
+
readonly turn: (writer: TurnWriter, task: TaskView) => Effect.Effect<TurnOutcome, HarnessError>;
|
|
53
|
+
/** Run the parent's inbox turn on its writer. */
|
|
54
|
+
readonly react: (writer: TurnWriter) => Effect.Effect<void, HarnessError>;
|
|
55
|
+
}>;
|
|
56
|
+
/** How the host runs the turns tasks need: the child's one turn, and the parent's reaction to results. */
|
|
57
|
+
export declare class TaskExecutor extends TaskExecutor_base {
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
|
|
3
|
+
export class Tasks extends Context.Service()("efferent/Tasks") {
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export class TaskRunner extends Context.Service()("efferent/TaskRunner") {
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class TaskExecutor extends Context.Service()("efferent/TaskExecutor") {
|
|
10
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect, Option, Scope } from "effect";
|
|
3
|
+
import type { Tool, Toolkit } from "effect/ai";
|
|
4
|
+
import type { DecisionRecord } from "../decision-record.entity.js";
|
|
5
|
+
import type { CapabilityCatalog } from "../harness/capability.entity.js";
|
|
6
|
+
import type { SkillDefinition } from "../harness/capability.entity.js";
|
|
7
|
+
import type { HarnessError } from "../harness/plugin.entity.js";
|
|
8
|
+
import type { ActivationSource } from "../memory/memory-log.entity.js";
|
|
9
|
+
import type { UserMessage } from "../turn/user-message.entity.js";
|
|
10
|
+
import type { MemorySession, ToolViews } from "./memory.port.js";
|
|
11
|
+
import type { RunContext } from "./run-context.port.js";
|
|
12
|
+
/**
|
|
13
|
+
* What the pre-turn matcher chose, before anything is recorded: `match`
|
|
14
|
+
* writes nothing, so it can run beside other pre-turn work (and be dropped
|
|
15
|
+
* when the turn ends early); `apply` activates, records and publishes it.
|
|
16
|
+
*/
|
|
17
|
+
export interface SkillMatch {
|
|
18
|
+
readonly userMessage: UserMessage;
|
|
19
|
+
/** Skills the matcher chose that are not loaded yet. */
|
|
20
|
+
readonly skills: ReadonlyArray<string>;
|
|
21
|
+
readonly probabilities: Option.Option<Readonly<Record<string, number>>>;
|
|
22
|
+
/** The decision as matched; None without a matcher. `apply` records it with its final validation. */
|
|
23
|
+
readonly record: Option.Option<DecisionRecord>;
|
|
24
|
+
}
|
|
25
|
+
/** The tools of one run: the full set is fixed at run start; the active set only grows. */
|
|
26
|
+
export interface RunTools {
|
|
27
|
+
readonly toolkit: Toolkit.Toolkit<Record<string, Tool.Any>>;
|
|
28
|
+
readonly handlers: Context.Context<never>;
|
|
29
|
+
/** Active tool names in activation order. */
|
|
30
|
+
readonly active: Effect.Effect<ReadonlyArray<string>>;
|
|
31
|
+
readonly activate: (skills: ReadonlyArray<string>, source: ActivationSource) => Effect.Effect<ReadonlyArray<string>, HarnessError>;
|
|
32
|
+
/** Ask the matcher, without writing anything. */
|
|
33
|
+
readonly match: (userMessage: UserMessage) => Effect.Effect<SkillMatch, HarnessError>;
|
|
34
|
+
/** Always-on skills plus a match: activated, recorded as a decision, seeded as a load_skill exchange. */
|
|
35
|
+
readonly apply: (match: SkillMatch) => Effect.Effect<ReadonlyArray<string>, HarnessError>;
|
|
36
|
+
/** `match` then `apply`. */
|
|
37
|
+
readonly select: (userMessage: UserMessage) => Effect.Effect<ReadonlyArray<string>, HarnessError>;
|
|
38
|
+
readonly views: ToolViews;
|
|
39
|
+
readonly pollable: ReadonlyArray<string>;
|
|
40
|
+
readonly skills: ReadonlyArray<SkillDefinition>;
|
|
41
|
+
}
|
|
42
|
+
declare const ToolRegistry_base: Context.ServiceClass<ToolRegistry, "efferent/ToolRegistry", {
|
|
43
|
+
readonly catalog: CapabilityCatalog;
|
|
44
|
+
/**
|
|
45
|
+
* Open the tools of one run. The handlers run with the services of where
|
|
46
|
+
* it is opened (host services, run layers, RunContext), captured at open;
|
|
47
|
+
* an IntentMatcher, ActionPolicy and PermissionGrants there are used.
|
|
48
|
+
*/
|
|
49
|
+
readonly open: (session: MemorySession) => Effect.Effect<RunTools, HarnessError, RunContext | Scope.Scope>;
|
|
50
|
+
}>;
|
|
51
|
+
export declare class ToolRegistry extends ToolRegistry_base {
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect } from "effect";
|
|
3
|
+
import type { SessionAddress, TurnRefused } from "../session/sessions.entity.js";
|
|
4
|
+
/** The turn a host is asked to admit. */
|
|
5
|
+
export interface TurnToAdmit {
|
|
6
|
+
readonly session: SessionAddress;
|
|
7
|
+
readonly origin: "user" | "inbox";
|
|
8
|
+
readonly runId: string;
|
|
9
|
+
readonly key: string;
|
|
10
|
+
}
|
|
11
|
+
declare const TurnAdmission_base: Context.ServiceClass<TurnAdmission, "efferent/TurnAdmission", {
|
|
12
|
+
readonly admit: <A, E>(turn: TurnToAdmit, open: Effect.Effect<A, E>) => Effect.Effect<A, E | TurnRefused>;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* The host's say on every turn before it opens: a user's, the inbox's, a
|
|
16
|
+
* background task's. `admit` runs around the one commit that opens the turn,
|
|
17
|
+
* never around the turn's later writes, so a host can count and open in one
|
|
18
|
+
* transaction; a duplicate or a busy session fails inside it and counts
|
|
19
|
+
* nothing. A refusal opens nothing.
|
|
20
|
+
*/
|
|
21
|
+
export declare class TurnAdmission extends TurnAdmission_base {
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect, Option, Scope } from "effect";
|
|
3
|
+
import type { HarnessError } from "../harness/plugin.entity.js";
|
|
4
|
+
import type { TurnEvent } from "../turn/turn-event.entity.js";
|
|
5
|
+
/**
|
|
6
|
+
* How a subscription receives events.
|
|
7
|
+
* - `inline` (default): the handler runs before `publish` returns, so the
|
|
8
|
+
* state it changes is visible to the next step; its failure fails the publisher.
|
|
9
|
+
* - `background`: events are queued (bounded, in order) for the handler's own
|
|
10
|
+
* fiber, so the publisher never waits on it. The turn drains every
|
|
11
|
+
* background subscription before it ends; a handler failure fails the
|
|
12
|
+
* next delivery to it and the drain.
|
|
13
|
+
*/
|
|
14
|
+
export interface SubscribeOptions {
|
|
15
|
+
readonly mode?: "inline" | "background";
|
|
16
|
+
/** Background queue size; publishing waits when it is full. */
|
|
17
|
+
readonly capacity?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The turn's event bus. Publication is ordered: subscribers are served in
|
|
21
|
+
* subscription order, depth-first (a handler may publish in turn, up to a
|
|
22
|
+
* depth cap). Inline handlers run before `publish` returns; background ones
|
|
23
|
+
* are queued. Background work that is not a reaction belongs in `TurnTasks`.
|
|
24
|
+
*/
|
|
25
|
+
export interface TurnEventsService {
|
|
26
|
+
readonly publish: (event: TurnEvent) => Effect.Effect<void, HarnessError>;
|
|
27
|
+
/** Active until the caller's scope closes. `select` narrows and decodes. */
|
|
28
|
+
readonly subscribe: <E, R>(select: (event: TurnEvent) => Option.Option<E>, handle: (event: E) => Effect.Effect<void, HarnessError, R>, options?: SubscribeOptions) => Effect.Effect<void, never, R | Scope.Scope>;
|
|
29
|
+
/** Wait until every background subscription has handled what was published to it. */
|
|
30
|
+
readonly drain: Effect.Effect<void, HarnessError>;
|
|
31
|
+
/** Background deliveries so far: a caller can tell whether a drain left new work. */
|
|
32
|
+
readonly activity: Effect.Effect<number>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Background work of one turn. Tasks run in the turn's scope: the turn
|
|
36
|
+
* awaits them before it ends and interrupts them when it fails.
|
|
37
|
+
*/
|
|
38
|
+
export interface TurnTasksService {
|
|
39
|
+
readonly fork: <R>(tag: string, task: Effect.Effect<void, HarnessError, R>) => Effect.Effect<void, never, R>;
|
|
40
|
+
/** True while any task with this tag is still running. */
|
|
41
|
+
readonly pending: (tag: string) => Effect.Effect<boolean>;
|
|
42
|
+
/** Join every task with one of these tags (all tasks when empty). */
|
|
43
|
+
readonly await: (tags: ReadonlyArray<string>) => Effect.Effect<void, HarnessError>;
|
|
44
|
+
/** Tasks forked so far: a caller can tell whether joining them started more. */
|
|
45
|
+
readonly activity: Effect.Effect<number>;
|
|
46
|
+
}
|
|
47
|
+
declare const TurnEvents_base: Context.ServiceClass<TurnEvents, "efferent/TurnEvents", TurnEventsService>;
|
|
48
|
+
export declare class TurnEvents extends TurnEvents_base {
|
|
49
|
+
}
|
|
50
|
+
declare const TurnTasks_base: Context.ServiceClass<TurnTasks, "efferent/TurnTasks", TurnTasksService>;
|
|
51
|
+
export declare class TurnTasks extends TurnTasks_base {
|
|
52
|
+
}
|
|
53
|
+
/** One subscription, ready to attach to a turn's bus (see `onTool`, `onEvent`). */
|
|
54
|
+
export type Subscription<R> = (events: TurnEventsService) => Effect.Effect<void, never, R | Scope.Scope>;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect, Option } from "effect";
|
|
3
|
+
import type { HarnessError } from "../harness/plugin.entity.js";
|
|
4
|
+
import type { MemoryReader, MemorySession } from "./memory.port.js";
|
|
5
|
+
import type { TurnWriter } from "./sessions.port.js";
|
|
6
|
+
import type { LoopLimits } from "./step-loop.port.js";
|
|
7
|
+
import type { RunTools } from "./tool-registry.port.js";
|
|
8
|
+
import type { TurnOutcome } from "./turn.port.js";
|
|
9
|
+
import type { LogEntry } from "../memory/memory-log.entity.js";
|
|
10
|
+
import type { ModelRequestHeader } from "../turn/model-request.entity.js";
|
|
11
|
+
import type { SessionLogEvent } from "../session/session-log.entity.js";
|
|
12
|
+
/** A turn-context message the model sees this turn (e.g. the user's intent). */
|
|
13
|
+
export interface TurnContextEntry {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly version: string;
|
|
16
|
+
readonly text: string;
|
|
17
|
+
}
|
|
18
|
+
/** What storage holds of a turn's requests: what a dispatch is checked against. */
|
|
19
|
+
export interface RequestSnapshot {
|
|
20
|
+
/** The memory entries, in log order (a fork's inherited history first), decoded from the stored memory events. */
|
|
21
|
+
readonly entries: ReadonlyArray<LogEntry>;
|
|
22
|
+
/** This run's stored request headers (`request.prepared`), in log order. */
|
|
23
|
+
readonly requests: ReadonlyArray<SessionLogEvent>;
|
|
24
|
+
}
|
|
25
|
+
declare const TurnMemory_base: Context.ServiceClass<TurnMemory, "efferent/TurnMemory", MemoryReader & {
|
|
26
|
+
readonly strategy: {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly version: string;
|
|
29
|
+
};
|
|
30
|
+
readonly session: MemorySession;
|
|
31
|
+
/** Record and flush a request's reconstruction header before dispatch. */
|
|
32
|
+
readonly prepareRequest: (header: ModelRequestHeader) => Effect.Effect<void, HarnessError>;
|
|
33
|
+
/**
|
|
34
|
+
* Flush, then read what storage holds, never the memory session's state:
|
|
35
|
+
* the history memory was opened over (read once, at open), and this
|
|
36
|
+
* turn's events from its start, each read taking only the events stored
|
|
37
|
+
* after the last one read.
|
|
38
|
+
*/
|
|
39
|
+
readonly requestSnapshot: Effect.Effect<RequestSnapshot, HarnessError>;
|
|
40
|
+
/** The turn's number; fails with `turn.unstarted` before `persistMessage`. */
|
|
41
|
+
readonly number: Effect.Effect<number, HarnessError>;
|
|
42
|
+
/**
|
|
43
|
+
* Record TurnStarted, then publish `turn.started`, and return the turn's
|
|
44
|
+
* number. Once: a second call fails. Anything built before it (a host
|
|
45
|
+
* layer, a matcher's history) sees only earlier turns.
|
|
46
|
+
*/
|
|
47
|
+
readonly persistMessage: Effect.Effect<number, HarnessError>;
|
|
48
|
+
/**
|
|
49
|
+
* Record a TurnContext entry. Before `persistMessage` (a plugin or a host
|
|
50
|
+
* layer built with the turn) it waits, and is recorded right after the
|
|
51
|
+
* message: the turn's entries follow its TurnStarted.
|
|
52
|
+
*/
|
|
53
|
+
readonly context: (entry: TurnContextEntry) => Effect.Effect<void, HarnessError>;
|
|
54
|
+
/** Record TurnEnded, then publish `turn.ended`. Once; a no-op when the message was never persisted. */
|
|
55
|
+
readonly persistReply: (outcome: TurnOutcome) => Effect.Effect<void, HarnessError>;
|
|
56
|
+
}>;
|
|
57
|
+
/** The turn's memory session, and the records that open and close the turn. */
|
|
58
|
+
export declare class TurnMemory extends TurnMemory_base {
|
|
59
|
+
}
|
|
60
|
+
declare const TurnToolbox_base: Context.ServiceClass<TurnToolbox, "efferent/TurnToolbox", {
|
|
61
|
+
/** Open the tools. Once: a second call fails. The handlers run with the services of the opener. */
|
|
62
|
+
readonly open: Effect.Effect<RunTools, HarnessError>;
|
|
63
|
+
/** The open tools; fails with `tools.unavailable` before `open`. */
|
|
64
|
+
readonly tools: Effect.Effect<RunTools, HarnessError>;
|
|
65
|
+
}>;
|
|
66
|
+
/** The turn's tools: registry-opened once, then shared by the loop, the host and RunContext.activate. */
|
|
67
|
+
export declare class TurnToolbox extends TurnToolbox_base {
|
|
68
|
+
}
|
|
69
|
+
declare const TurnPrompt_base: Context.ServiceClass<TurnPrompt, "efferent/TurnPrompt", {
|
|
70
|
+
/**
|
|
71
|
+
* The system prompt of one variant: the prefix and the static and session
|
|
72
|
+
* sections, rendered once per turn in the caller's services and recorded
|
|
73
|
+
* (SystemPrepared) when it differs from the last one recorded.
|
|
74
|
+
*/
|
|
75
|
+
readonly system: (variant: Option.Option<string>) => Effect.Effect<string, HarnessError>;
|
|
76
|
+
/** Render the turn-tier sections once, as TurnContext entries (later calls do nothing). */
|
|
77
|
+
readonly turnSections: Effect.Effect<void, HarnessError>;
|
|
78
|
+
}>;
|
|
79
|
+
/** The turn's prompt assembly: the system prompt per variant, and the turn-tier sections. */
|
|
80
|
+
export declare class TurnPrompt extends TurnPrompt_base {
|
|
81
|
+
}
|
|
82
|
+
/** What `TurnLive` builds one turn from. */
|
|
83
|
+
export interface TurnLiveInput {
|
|
84
|
+
/** The admitted turn's writer (see `Sessions.begin`): the session, the message, and where everything is stored. */
|
|
85
|
+
readonly turn: TurnWriter;
|
|
86
|
+
/** The system prompt prefix, before the contributed sections. */
|
|
87
|
+
readonly system?: string;
|
|
88
|
+
/** How deep event reactions may nest before the bus fails the publisher (8). */
|
|
89
|
+
readonly maxEventDepth?: number;
|
|
90
|
+
}
|
|
91
|
+
/** The agent-level defaults of one run; a policy overrides limits and budget. */
|
|
92
|
+
export interface TurnRunOptions {
|
|
93
|
+
readonly limits?: Partial<LoopLimits>;
|
|
94
|
+
/** Input tokens one request may use (system, tool schemas and messages); 64 000 by default. */
|
|
95
|
+
readonly budgetTokens?: number;
|
|
96
|
+
/** The provider prompt-cache key (see `cacheKeyOf`); none by default. */
|
|
97
|
+
readonly cacheKey?: Option.Option<string>;
|
|
98
|
+
/** A mid-run user message, consulted between steps. */
|
|
99
|
+
readonly steering?: Effect.Effect<Option.Option<string>, HarnessError>;
|
|
100
|
+
}
|
|
101
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
|
|
3
|
+
export class TurnMemory extends Context.Service()("efferent/TurnMemory") {
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export class TurnToolbox extends Context.Service()("efferent/TurnToolbox") {
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class TurnPrompt extends Context.Service()("efferent/TurnPrompt") {
|
|
10
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { Context, Effect, Layer, Option, Scope } from "effect";
|
|
2
|
+
import type { ConversationId } from "../domain/message.entity.js";
|
|
3
|
+
import type { SkillDefinition } from "../harness/capability.entity.js";
|
|
4
|
+
import type { HarnessError } from "../harness/plugin.entity.js";
|
|
5
|
+
import type { CompletionVerdict } from "../turn/turn-event.entity.js";
|
|
6
|
+
import type { UserMessage } from "../turn/user-message.entity.js";
|
|
7
|
+
import type { InitialBatch, ModelChoice, StepDirective, StepInfo } from "./capability.port.js";
|
|
8
|
+
import type { MemoryReader } from "./memory.port.js";
|
|
9
|
+
import type { RunContext } from "./run-context.port.js";
|
|
10
|
+
import type { TurnWriter } from "./sessions.port.js";
|
|
11
|
+
import type { JsonObject } from "../session/session-log.entity.js";
|
|
12
|
+
import type { SessionAddress } from "../session/sessions.entity.js";
|
|
13
|
+
import type { Correctives, LoopLimits, RunResult } from "./step-loop.port.js";
|
|
14
|
+
import type { SkillMatch } from "./tool-registry.port.js";
|
|
15
|
+
import type { TurnEvents, TurnEventsService, TurnTasks, TurnTasksService } from "./turn-events.port.js";
|
|
16
|
+
/**
|
|
17
|
+
* The host's policy for one run: plain functions, not plugins. The step
|
|
18
|
+
* loop implementation is the plugin; what a step says, which model it uses
|
|
19
|
+
* and when the turn is complete are the application's decisions.
|
|
20
|
+
*/
|
|
21
|
+
export interface TurnPolicy<R = never> {
|
|
22
|
+
readonly initial?: InitialBatch;
|
|
23
|
+
readonly model?: (step: StepInfo) => Effect.Effect<Option.Option<ModelChoice>, HarnessError, R>;
|
|
24
|
+
readonly step?: (step: StepInfo) => Effect.Effect<StepDirective, HarnessError, R>;
|
|
25
|
+
/** Read-only by contract: react to events, decide here. */
|
|
26
|
+
readonly completion?: (step: StepInfo) => Effect.Effect<CompletionVerdict, HarnessError, R>;
|
|
27
|
+
readonly limits?: Partial<LoopLimits>;
|
|
28
|
+
/** Input tokens one request may use (system, tool schemas and messages). */
|
|
29
|
+
readonly budgetTokens?: number;
|
|
30
|
+
/** Where the step context goes: closing the messages, or appended to the system prompt. */
|
|
31
|
+
readonly stepContext?: "tail" | "system";
|
|
32
|
+
readonly correctives?: Correctives;
|
|
33
|
+
}
|
|
34
|
+
export interface TurnOutcome {
|
|
35
|
+
readonly outcome: "completed" | "partial" | "failed";
|
|
36
|
+
/** The reply follow-up turns remember. */
|
|
37
|
+
readonly reply: Option.Option<string>;
|
|
38
|
+
}
|
|
39
|
+
export interface TurnTools {
|
|
40
|
+
/** Ask the matcher without writing anything (run it beside other pre-turn work). */
|
|
41
|
+
readonly match: (userMessage: UserMessage) => Effect.Effect<SkillMatch, HarnessError>;
|
|
42
|
+
/** Activate the always-on skills and a match; recorded as a decision. */
|
|
43
|
+
readonly apply: (match: SkillMatch) => Effect.Effect<ReadonlyArray<string>, HarnessError>;
|
|
44
|
+
/** `match` then `apply`. */
|
|
45
|
+
readonly select: (userMessage: UserMessage) => Effect.Effect<ReadonlyArray<string>, HarnessError>;
|
|
46
|
+
readonly activate: (skills: ReadonlyArray<string>) => Effect.Effect<ReadonlyArray<string>, HarnessError>;
|
|
47
|
+
readonly active: Effect.Effect<ReadonlyArray<string>>;
|
|
48
|
+
readonly skills: ReadonlyArray<SkillDefinition>;
|
|
49
|
+
}
|
|
50
|
+
/** One admitted turn, composed by the host (see `Agent.turn`). */
|
|
51
|
+
export interface Turn {
|
|
52
|
+
readonly conversation: ConversationId;
|
|
53
|
+
readonly runId: string;
|
|
54
|
+
readonly turn: number;
|
|
55
|
+
readonly userMessage: UserMessage;
|
|
56
|
+
readonly memory: MemoryReader;
|
|
57
|
+
readonly events: TurnEventsService;
|
|
58
|
+
readonly tasks: TurnTasksService;
|
|
59
|
+
readonly tools: TurnTools;
|
|
60
|
+
/** Record a turn-context message (e.g. the user's intent) the model sees this turn. */
|
|
61
|
+
readonly context: (entry: {
|
|
62
|
+
readonly id: string;
|
|
63
|
+
readonly version: string;
|
|
64
|
+
readonly text: string;
|
|
65
|
+
}) => Effect.Effect<void, HarnessError>;
|
|
66
|
+
/** Answer without the loop; still a recorded turn. */
|
|
67
|
+
readonly reply: (text: string) => Effect.Effect<TurnOutcome>;
|
|
68
|
+
readonly run: <R = never>(policy: TurnPolicy<R>) => Effect.Effect<RunResult, HarnessError, R>;
|
|
69
|
+
/** Wait until every journal write queued so far is stored (e.g. before delivering an answer). */
|
|
70
|
+
readonly flush: Effect.Effect<void, HarnessError>;
|
|
71
|
+
/** Run a host store write in journal order and return its result. */
|
|
72
|
+
readonly write: <A, E>(op: Effect.Effect<A, E>) => Effect.Effect<A, E | HarnessError>;
|
|
73
|
+
}
|
|
74
|
+
/** What every turn provides to the host's code, its per-turn layer and its tools. */
|
|
75
|
+
export type TurnServices = RunContext | TurnEvents | TurnTasks;
|
|
76
|
+
/** A turn to begin: the session (through the `Sessions` in the turn's services), the message and the run. */
|
|
77
|
+
export interface NewTurn {
|
|
78
|
+
readonly session: SessionAddress;
|
|
79
|
+
readonly userMessage: UserMessage;
|
|
80
|
+
readonly runId: string;
|
|
81
|
+
/** The idempotency key; the run id by default. */
|
|
82
|
+
readonly key?: string;
|
|
83
|
+
/** The host's input beside the message, part of the key's fingerprint. */
|
|
84
|
+
readonly command?: JsonObject;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* One turn's input. `turn` is either a turn the host already began (its
|
|
88
|
+
* writer: the host ends it) or one to begin and end here. `layer` is the
|
|
89
|
+
* host's per-turn services (state stores, adapters for this user
|
|
90
|
+
* message…): built after RunContext, it is provided to the host's `use`, to
|
|
91
|
+
* the tools, the policy, subscriptions and tasks alike.
|
|
92
|
+
*/
|
|
93
|
+
export interface TurnInput<A = never, E = never> {
|
|
94
|
+
readonly turn: TurnWriter | NewTurn;
|
|
95
|
+
/** This turn's services: the model, per-turn budgets, data ports… */
|
|
96
|
+
readonly services: Context.Context<never>;
|
|
97
|
+
/** A system prompt prefix before the contributed sections. */
|
|
98
|
+
readonly system?: string;
|
|
99
|
+
/** Per-conversation prompt-cache key for providers that support one. */
|
|
100
|
+
readonly cacheKey?: string;
|
|
101
|
+
/** A mid-run user message, consulted between steps. */
|
|
102
|
+
readonly steering?: Effect.Effect<Option.Option<string>, HarnessError>;
|
|
103
|
+
/** The host's per-turn services; its requirements are met by the turn's services. */
|
|
104
|
+
readonly layer?: Layer.Layer<A, E, unknown>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Anything that runs one admitted turn the way `Agent.turn` does: an
|
|
108
|
+
* agent, or a host's own composition of the turn's steps (see
|
|
109
|
+
* `turnConformance`).
|
|
110
|
+
*/
|
|
111
|
+
export interface TurnRunner {
|
|
112
|
+
readonly turn: <A = never, E = never, R = never>(input: TurnInput<A, E>, use: (turn: Turn) => Effect.Effect<TurnOutcome, HarnessError, R>) => Effect.Effect<TurnOutcome, HarnessError | E, Exclude<R, A | TurnServices | Scope.Scope>>;
|
|
113
|
+
}
|
|
File without changes
|
|
@@ -1,41 +1,22 @@
|
|
|
1
1
|
import { Context, Schema } from "effect";
|
|
2
2
|
import type { Effect } from "effect";
|
|
3
|
-
declare const UtilityError_base: Schema.
|
|
4
|
-
readonly
|
|
5
|
-
}
|
|
6
|
-
message: typeof Schema.String;
|
|
7
|
-
}>;
|
|
3
|
+
declare const UtilityError_base: Schema.Class<UtilityError, Schema.TaggedStruct<"UtilityError", {
|
|
4
|
+
readonly message: Schema.String;
|
|
5
|
+
}>, import("effect/Cause").YieldableError>;
|
|
8
6
|
export declare class UtilityError extends UtilityError_base {
|
|
9
7
|
}
|
|
10
|
-
declare const UtilityCompletion_base: Schema.Class<UtilityCompletion, {
|
|
11
|
-
text:
|
|
12
|
-
usage: Schema.Struct<{
|
|
13
|
-
inputTokens:
|
|
14
|
-
outputTokens:
|
|
15
|
-
totalTokens:
|
|
16
|
-
cacheReadTokens:
|
|
17
|
-
}>;
|
|
18
|
-
}, Schema.Struct.Encoded<{
|
|
19
|
-
text: typeof Schema.String;
|
|
20
|
-
usage: Schema.Struct<{
|
|
21
|
-
inputTokens: typeof Schema.Number;
|
|
22
|
-
outputTokens: typeof Schema.Number;
|
|
23
|
-
totalTokens: typeof Schema.Number;
|
|
24
|
-
cacheReadTokens: typeof Schema.Number;
|
|
8
|
+
declare const UtilityCompletion_base: Schema.Class<UtilityCompletion, Schema.Struct<{
|
|
9
|
+
readonly text: Schema.String;
|
|
10
|
+
readonly usage: Schema.Struct<{
|
|
11
|
+
readonly inputTokens: Schema.Number;
|
|
12
|
+
readonly outputTokens: Schema.Number;
|
|
13
|
+
readonly totalTokens: Schema.Number;
|
|
14
|
+
readonly cacheReadTokens: Schema.Number;
|
|
25
15
|
}>;
|
|
26
|
-
}>,
|
|
27
|
-
readonly text: string;
|
|
28
|
-
} & {
|
|
29
|
-
readonly usage: {
|
|
30
|
-
readonly inputTokens: number;
|
|
31
|
-
readonly outputTokens: number;
|
|
32
|
-
readonly totalTokens: number;
|
|
33
|
-
readonly cacheReadTokens: number;
|
|
34
|
-
};
|
|
35
|
-
}, {}, {}>;
|
|
16
|
+
}>, {}>;
|
|
36
17
|
export declare class UtilityCompletion extends UtilityCompletion_base {
|
|
37
18
|
}
|
|
38
|
-
declare const UtilityLlm_base: Context.
|
|
19
|
+
declare const UtilityLlm_base: Context.ServiceClass<UtilityLlm, "@xandreed/core/UtilityLlm", {
|
|
39
20
|
readonly complete: (prompt: string) => Effect.Effect<UtilityCompletion, UtilityError>;
|
|
40
21
|
}>;
|
|
41
22
|
/**
|
package/dist/session/chassis.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { Effect, Exit, Fiber, Option, PubSub, Ref, Stream } from "effect";
|
|
1
|
+
import { Effect, Exit, Fiber, Option, PubSub, Ref, Stream, Semaphore } from "effect";
|
|
2
2
|
export const makeSession = (args) => Effect.gen(function* () {
|
|
3
|
-
const context = yield* Effect.context(), log = yield* Ref.make([]), hub = yield* PubSub.sliding(512), transientHub = yield* PubSub.sliding(128), running = yield* Ref.make(Option.none()), gate = yield*
|
|
3
|
+
const context = yield* Effect.context(), log = yield* Ref.make([]), hub = yield* PubSub.sliding(512), transientHub = yield* PubSub.sliding(128), running = yield* Ref.make(Option.none()), gate = yield* Semaphore.make(1), publish = (event) => args.isTransient?.(event) === !0 ? PubSub.publish(transientHub, event).pipe(Effect.asVoid) : Ref.modify(log, (entries) => {
|
|
4
4
|
const entry = { seq: entries.length, event };
|
|
5
5
|
return [entry, [...entries, entry]];
|
|
6
|
-
}).pipe(Effect.flatMap((entry) => PubSub.publish(hub, entry)), Effect.asVoid), runContained = (text) => args.runTurn(text, publish).pipe(Effect.provide(context), Effect.
|
|
7
|
-
const fiber = yield* Effect.
|
|
6
|
+
}).pipe(Effect.flatMap((entry) => PubSub.publish(hub, entry)), Effect.asVoid), runContained = (text) => args.runTurn(text, publish).pipe(Effect.provide(context), Effect.catch((error) => publish(args.onError(String(error)))), Effect.catchDefect((defect) => publish(args.onError(`turn crashed: ${String(defect)}`)))), send = (text) => gate.withPermits(1)(Effect.gen(function* () {
|
|
7
|
+
const fiber = yield* Effect.forkChild(runContained(text));
|
|
8
8
|
yield* Ref.set(running, Option.some(fiber));
|
|
9
9
|
yield* Fiber.await(fiber).pipe(Effect.asVoid);
|
|
10
10
|
yield* Ref.set(running, Option.none());
|
|
11
11
|
})), interrupt = Ref.get(running).pipe(Effect.flatMap(Option.match({
|
|
12
12
|
onNone: () => Effect.void,
|
|
13
|
-
onSome: (fiber) => Fiber.interrupt(fiber).pipe(Effect.flatMap((exit) => Exit.
|
|
13
|
+
onSome: (fiber) => Fiber.interrupt(fiber).pipe(Effect.andThen(Fiber.await(fiber)), Effect.flatMap((exit) => Exit.hasInterrupts(exit) && args.onInterrupt !== void 0 ? publish(args.onInterrupt()) : Effect.void))
|
|
14
14
|
})));
|
|
15
15
|
return {
|
|
16
16
|
conversationId: args.conversationId,
|
|
17
17
|
send,
|
|
18
18
|
interrupt,
|
|
19
19
|
state: Ref.get(log).pipe(Effect.map((entries) => ({ log: entries, cursor: entries.length }))),
|
|
20
|
-
subscribe: (since) => Stream.
|
|
21
|
-
const sub = yield* PubSub.subscribe(hub), entries = yield* Ref.get(log), replay = Stream.fromIterable(entries.filter((e) => e.seq >= since)), seenThrough = entries.length, live = Stream.
|
|
20
|
+
subscribe: (since) => Stream.unwrap(Effect.gen(function* () {
|
|
21
|
+
const sub = yield* PubSub.subscribe(hub), entries = yield* Ref.get(log), replay = Stream.fromIterable(entries.filter((e) => e.seq >= since)), seenThrough = entries.length, live = Stream.fromSubscription(sub).pipe(Stream.filter((e) => e.seq >= Math.max(since, seenThrough)));
|
|
22
22
|
return Stream.concat(replay, live);
|
|
23
23
|
})),
|
|
24
24
|
transient: Stream.fromPubSub(transientHub),
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { UserMessage } from "../turn/user-message.entity.js";
|
|
3
|
+
/** Opens a turn: who asked, what they said, the host's command and the inbox items it claims. */
|
|
4
|
+
export declare const TurnStartedData: Schema.Struct<{
|
|
5
|
+
readonly runId: Schema.String;
|
|
6
|
+
/** The host's idempotency key: a second begin with it is the same turn. */
|
|
7
|
+
readonly key: Schema.String;
|
|
8
|
+
readonly origin: Schema.Literals<readonly ["user", "inbox"]>;
|
|
9
|
+
readonly userMessage: typeof UserMessage;
|
|
10
|
+
/** The host's own input beside the message (an attachment, a reference), part of the key's fingerprint. */
|
|
11
|
+
readonly command: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
12
|
+
/** The inbox items this turn answers (an inbox turn only). */
|
|
13
|
+
readonly claimed: Schema.$Array<Schema.String>;
|
|
14
|
+
/** The memory entry the message is to the model, and when memory took it. */
|
|
15
|
+
readonly entry: Schema.brand<Schema.Trimmed, "EntryId">;
|
|
16
|
+
readonly at: Schema.Number;
|
|
17
|
+
}>;
|
|
18
|
+
export type TurnStartedData = typeof TurnStartedData.Type;
|
|
19
|
+
export declare const TurnEndReason: Schema.Literals<readonly ["completed", "partial", "failed", "cancelled", "interrupted"]>;
|
|
20
|
+
export type TurnEndReason = typeof TurnEndReason.Type;
|
|
21
|
+
/** Closes a turn. Not model-visible: what later turns remember is `turn.reply`. */
|
|
22
|
+
export declare const TurnEndedData: Schema.Struct<{
|
|
23
|
+
readonly reason: Schema.Literals<readonly ["completed", "partial", "failed", "cancelled", "interrupted"]>;
|
|
24
|
+
readonly failure: Schema.OptionFromNullOr<Schema.Struct<{
|
|
25
|
+
readonly code: Schema.String;
|
|
26
|
+
readonly message: Schema.String;
|
|
27
|
+
}>>;
|
|
28
|
+
}>;
|
|
29
|
+
export type TurnEndedData = typeof TurnEndedData.Type;
|
|
30
|
+
/** The kind each memory entry is stored under. `TurnStarted` is the turn's own `turn.started`. */
|
|
31
|
+
export declare const MemoryKindOf: {
|
|
32
|
+
readonly SystemPrepared: "memory.system";
|
|
33
|
+
readonly TurnContext: "memory.section";
|
|
34
|
+
readonly StepContext: "memory.step";
|
|
35
|
+
readonly Message: "memory.message";
|
|
36
|
+
readonly ToolResult: "memory.tool-result";
|
|
37
|
+
readonly ToolDigest: "memory.digest";
|
|
38
|
+
readonly ToolsActivated: "memory.skills";
|
|
39
|
+
readonly Compaction: "memory.compaction";
|
|
40
|
+
readonly TurnEnded: "turn.reply";
|
|
41
|
+
};
|
|
42
|
+
/** Every kind a memory session is rebuilt from. */
|
|
43
|
+
export declare const MEMORY_KINDS: ReadonlyArray<string>;
|
|
44
|
+
/** The turn's observable events stored from its bus (a host's records keep their own names). */
|
|
45
|
+
export declare const TURN_EVENT_KINDS: ReadonlyArray<string>;
|
|
46
|
+
/** The inbox and the session's own records. */
|
|
47
|
+
export declare const SESSION_KINDS: ReadonlyArray<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Kinds only Efferent writes: a host record under one of these names is refused.
|
|
50
|
+
* `request.prepared` holds each request's full system text and tool
|
|
51
|
+
* declarations (and step context in "system" mode), next to the memory
|
|
52
|
+
* events: a host that redacts memory, or exports or streams session events,
|
|
53
|
+
* handles it the same way.
|
|
54
|
+
*/
|
|
55
|
+
export declare const RESERVED_KINDS: ReadonlyArray<string>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Effect, Option, Schema } from "effect";
|
|
2
|
+
import { LogEntry } from "../memory/memory-log.entity.js";
|
|
3
|
+
import type { TurnEvent as TurnEventType } from "../turn/turn-event.entity.js";
|
|
4
|
+
import type { TurnEndedData as TurnEnded, TurnStartedData as TurnStarted } from "./session-event.entity.js";
|
|
5
|
+
import type { SessionDraft, SessionLogEvent } from "./session-log.entity.js";
|
|
6
|
+
/**
|
|
7
|
+
* One memory entry → the draft it is stored as: its own kind, the entry's
|
|
8
|
+
* id, run, step and time, and the body. TurnStarted has none: the turn's
|
|
9
|
+
* `turn.started` (written when the turn begins) is that entry.
|
|
10
|
+
*/
|
|
11
|
+
export declare const draftOfEntry: (entry: LogEntry) => Effect.Effect<Option.Option<SessionDraft>, Schema.SchemaError>;
|
|
12
|
+
export declare const draftsOfEntries: (entries: ReadonlyArray<LogEntry>) => Effect.Effect<ReadonlyArray<SessionDraft>, Schema.SchemaError>;
|
|
13
|
+
/** The draft that opens a turn. */
|
|
14
|
+
export declare const turnStartedDraft: (turn: number, data: TurnStarted) => Effect.Effect<SessionDraft, Schema.SchemaError>;
|
|
15
|
+
/** The draft that closes a turn. */
|
|
16
|
+
export declare const turnEndedDraft: (turn: number, data: TurnEnded) => Effect.Effect<SessionDraft, Schema.SchemaError>;
|
|
17
|
+
/** A stored `turn.started`, decoded. */
|
|
18
|
+
export declare const turnStartedOf: (event: SessionLogEvent) => Effect.Effect<TurnStarted, Schema.SchemaError>;
|
|
19
|
+
/** A stored `turn.ended`, decoded. */
|
|
20
|
+
export declare const turnEndedOf: (event: SessionLogEvent) => Effect.Effect<TurnEnded, Schema.SchemaError>;
|
|
21
|
+
/** One stored event → the memory entry it is, if it is one. */
|
|
22
|
+
export declare const entryOfEvent: (event: SessionLogEvent) => Effect.Effect<Option.Option<LogEntry>, Schema.SchemaError>;
|
|
23
|
+
/** The memory log held in a session's events, in log order. */
|
|
24
|
+
export declare const entriesOfEvents: (events: ReadonlyArray<SessionLogEvent>) => Effect.Effect<ReadonlyArray<LogEntry>, Schema.SchemaError>;
|
|
25
|
+
/**
|
|
26
|
+
* The stored form of one bus event of turn `turn`: its name and encoded
|
|
27
|
+
* payload. Transient events are not stored; a host's event keeps its name
|
|
28
|
+
* and data; an assistant message is stored only as the step's model and
|
|
29
|
+
* usage (its content is memory's `memory.message`).
|
|
30
|
+
*/
|
|
31
|
+
export declare const draftOfTurnEvent: (turn: number, event: TurnEventType) => Option.Option<SessionDraft>;
|