@yolk-sdk/agent 0.0.1-canary.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/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/client/index.d.mts +3 -0
- package/dist/client/index.mjs +3 -0
- package/dist/client/state.d.mts +99 -0
- package/dist/client/state.d.mts.map +1 -0
- package/dist/client/state.mjs +245 -0
- package/dist/client/state.mjs.map +1 -0
- package/dist/client/transport.d.mts +67 -0
- package/dist/client/transport.d.mts.map +1 -0
- package/dist/client/transport.mjs +219 -0
- package/dist/client/transport.mjs.map +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/loop/accumulator.d.mts +11 -0
- package/dist/loop/accumulator.d.mts.map +1 -0
- package/dist/loop/accumulator.mjs +40 -0
- package/dist/loop/accumulator.mjs.map +1 -0
- package/dist/loop/error.d.mts +36 -0
- package/dist/loop/error.d.mts.map +1 -0
- package/dist/loop/error.mjs +84 -0
- package/dist/loop/error.mjs.map +1 -0
- package/dist/loop/index.d.mts +9 -0
- package/dist/loop/index.mjs +9 -0
- package/dist/loop/llm-event.d.mts +44 -0
- package/dist/loop/llm-event.d.mts.map +1 -0
- package/dist/loop/llm-event.mjs +34 -0
- package/dist/loop/llm-event.mjs.map +1 -0
- package/dist/loop/run.d.mts +37 -0
- package/dist/loop/run.d.mts.map +1 -0
- package/dist/loop/run.mjs +624 -0
- package/dist/loop/run.mjs.map +1 -0
- package/dist/loop/services/context-transformer.d.mts +18 -0
- package/dist/loop/services/context-transformer.d.mts.map +1 -0
- package/dist/loop/services/context-transformer.mjs +12 -0
- package/dist/loop/services/context-transformer.mjs.map +1 -0
- package/dist/loop/services/llm-provider.d.mts +20 -0
- package/dist/loop/services/llm-provider.d.mts.map +1 -0
- package/dist/loop/services/llm-provider.mjs +7 -0
- package/dist/loop/services/llm-provider.mjs.map +1 -0
- package/dist/loop/services/loop-config.d.mts +17 -0
- package/dist/loop/services/loop-config.d.mts.map +1 -0
- package/dist/loop/services/loop-config.mjs +15 -0
- package/dist/loop/services/loop-config.mjs.map +1 -0
- package/dist/loop/services/tool-executor.d.mts +12 -0
- package/dist/loop/services/tool-executor.d.mts.map +1 -0
- package/dist/loop/services/tool-executor.mjs +7 -0
- package/dist/loop/services/tool-executor.mjs.map +1 -0
- package/dist/loop/testing/faux-provider.d.mts +31 -0
- package/dist/loop/testing/faux-provider.d.mts.map +1 -0
- package/dist/loop/testing/faux-provider.mjs +47 -0
- package/dist/loop/testing/faux-provider.mjs.map +1 -0
- package/dist/loop/testing/index.d.mts +3 -0
- package/dist/loop/testing/index.mjs +3 -0
- package/dist/loop/testing/test-tool-executor.d.mts +10 -0
- package/dist/loop/testing/test-tool-executor.d.mts.map +1 -0
- package/dist/loop/testing/test-tool-executor.mjs +21 -0
- package/dist/loop/testing/test-tool-executor.mjs.map +1 -0
- package/dist/protocol/capability.d.mts +20 -0
- package/dist/protocol/capability.d.mts.map +1 -0
- package/dist/protocol/capability.mjs +34 -0
- package/dist/protocol/capability.mjs.map +1 -0
- package/dist/protocol/content.d.mts +31 -0
- package/dist/protocol/content.d.mts.map +1 -0
- package/dist/protocol/content.mjs +52 -0
- package/dist/protocol/content.mjs.map +1 -0
- package/dist/protocol/event.d.mts +228 -0
- package/dist/protocol/event.d.mts.map +1 -0
- package/dist/protocol/event.mjs +217 -0
- package/dist/protocol/event.mjs.map +1 -0
- package/dist/protocol/index.d.mts +14 -0
- package/dist/protocol/index.d.mts.map +1 -0
- package/dist/protocol/index.mjs +9 -0
- package/dist/protocol/message.d.mts +53 -0
- package/dist/protocol/message.d.mts.map +1 -0
- package/dist/protocol/message.mjs +49 -0
- package/dist/protocol/message.mjs.map +1 -0
- package/dist/protocol/reasoning.d.mts +8 -0
- package/dist/protocol/reasoning.d.mts.map +1 -0
- package/dist/protocol/reasoning.mjs +13 -0
- package/dist/protocol/reasoning.mjs.map +1 -0
- package/dist/protocol/session.d.mts +39 -0
- package/dist/protocol/session.d.mts.map +1 -0
- package/dist/protocol/session.mjs +38 -0
- package/dist/protocol/session.mjs.map +1 -0
- package/dist/protocol/tool.d.mts +101 -0
- package/dist/protocol/tool.d.mts.map +1 -0
- package/dist/protocol/tool.mjs +102 -0
- package/dist/protocol/tool.mjs.map +1 -0
- package/dist/protocol/usage.d.mts +26 -0
- package/dist/protocol/usage.d.mts.map +1 -0
- package/dist/protocol/usage.mjs +40 -0
- package/dist/protocol/usage.mjs.map +1 -0
- package/dist/runtime/error.d.mts +29 -0
- package/dist/runtime/error.d.mts.map +1 -0
- package/dist/runtime/error.mjs +46 -0
- package/dist/runtime/error.mjs.map +1 -0
- package/dist/runtime/index.d.mts +9 -0
- package/dist/runtime/index.d.mts.map +1 -0
- package/dist/runtime/index.mjs +4 -0
- package/dist/runtime/run-runtime.d.mts +47 -0
- package/dist/runtime/run-runtime.d.mts.map +1 -0
- package/dist/runtime/run-runtime.mjs +112 -0
- package/dist/runtime/run-runtime.mjs.map +1 -0
- package/dist/runtime/session-event-store.d.mts +75 -0
- package/dist/runtime/session-event-store.d.mts.map +1 -0
- package/dist/runtime/session-event-store.mjs +124 -0
- package/dist/runtime/session-event-store.mjs.map +1 -0
- package/dist/tools/index.d.mts +4 -0
- package/dist/tools/index.mjs +4 -0
- package/dist/tools/question.d.mts +21 -0
- package/dist/tools/question.d.mts.map +1 -0
- package/dist/tools/question.mjs +41 -0
- package/dist/tools/question.mjs.map +1 -0
- package/dist/tools/registry.d.mts +61 -0
- package/dist/tools/registry.d.mts.map +1 -0
- package/dist/tools/registry.mjs +113 -0
- package/dist/tools/registry.mjs.map +1 -0
- package/dist/tools/task.d.mts +34 -0
- package/dist/tools/task.d.mts.map +1 -0
- package/dist/tools/task.mjs +81 -0
- package/dist/tools/task.mjs.map +1 -0
- package/package.json +86 -0
- package/src/client/README.md +23 -0
- package/src/client/index.ts +43 -0
- package/src/client/state.ts +380 -0
- package/src/client/transport.ts +517 -0
- package/src/index.ts +2 -0
- package/src/loop/README.md +23 -0
- package/src/loop/accumulator.ts +71 -0
- package/src/loop/error.ts +105 -0
- package/src/loop/index.ts +35 -0
- package/src/loop/llm-event.ts +52 -0
- package/src/loop/run.ts +1237 -0
- package/src/loop/services/context-transformer.ts +24 -0
- package/src/loop/services/llm-provider.ts +20 -0
- package/src/loop/services/loop-config.ts +20 -0
- package/src/loop/services/tool-executor.ts +11 -0
- package/src/loop/testing/faux-provider.ts +94 -0
- package/src/loop/testing/index.ts +3 -0
- package/src/loop/testing/test-tool-executor.ts +28 -0
- package/src/protocol/README.md +24 -0
- package/src/protocol/capability.ts +29 -0
- package/src/protocol/content.ts +76 -0
- package/src/protocol/event.ts +286 -0
- package/src/protocol/index.ts +109 -0
- package/src/protocol/message.ts +86 -0
- package/src/protocol/reasoning.ts +4 -0
- package/src/protocol/session.ts +47 -0
- package/src/protocol/tool.ts +154 -0
- package/src/protocol/usage.ts +48 -0
- package/src/runtime/README.md +44 -0
- package/src/runtime/error.ts +70 -0
- package/src/runtime/index.ts +43 -0
- package/src/runtime/run-runtime.ts +307 -0
- package/src/runtime/session-event-store.ts +254 -0
- package/src/tools/README.md +22 -0
- package/src/tools/index.ts +29 -0
- package/src/tools/question.ts +58 -0
- package/src/tools/registry.ts +228 -0
- package/src/tools/task.ts +132 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from 'effect'
|
|
2
|
+
import type { AgentEvent, AgentMessage } from '@yolk-sdk/agent/protocol'
|
|
3
|
+
import type { ContextTransformError } from '../error.ts'
|
|
4
|
+
|
|
5
|
+
export type ContextTransformResult = {
|
|
6
|
+
readonly messages: ReadonlyArray<AgentMessage>
|
|
7
|
+
readonly events: ReadonlyArray<AgentEvent>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class ContextTransformer extends Context.Service<
|
|
11
|
+
ContextTransformer,
|
|
12
|
+
{
|
|
13
|
+
readonly transform: (
|
|
14
|
+
messages: ReadonlyArray<AgentMessage>
|
|
15
|
+
) => Effect.Effect<ContextTransformResult, ContextTransformError>
|
|
16
|
+
}
|
|
17
|
+
>()('@yolk-sdk/agent/loop/ContextTransformer') {
|
|
18
|
+
static identity = Layer.succeed(
|
|
19
|
+
this,
|
|
20
|
+
this.of({
|
|
21
|
+
transform: messages => Effect.succeed({ messages, events: [] })
|
|
22
|
+
})
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Context } from 'effect'
|
|
2
|
+
import type { Stream } from 'effect'
|
|
3
|
+
import type { AgentMessage, AgentReasoningEffort, ToolDef } from '@yolk-sdk/agent/protocol'
|
|
4
|
+
import type { LLMProviderError } from '../error.ts'
|
|
5
|
+
import type { LLMEvent } from '../llm-event.ts'
|
|
6
|
+
|
|
7
|
+
export type LLMRequest = {
|
|
8
|
+
readonly messages: ReadonlyArray<AgentMessage>
|
|
9
|
+
readonly tools: ReadonlyArray<ToolDef>
|
|
10
|
+
readonly model: string
|
|
11
|
+
readonly systemPrompt: string
|
|
12
|
+
readonly reasoningEffort?: AgentReasoningEffort
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class LLMProvider extends Context.Service<
|
|
16
|
+
LLMProvider,
|
|
17
|
+
{
|
|
18
|
+
readonly stream: (request: LLMRequest) => Stream.Stream<LLMEvent, LLMProviderError>
|
|
19
|
+
}
|
|
20
|
+
>()('@yolk-sdk/agent/loop/LLMProvider') {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Context, Layer } from 'effect'
|
|
2
|
+
|
|
3
|
+
export type LoopConfigShape = {
|
|
4
|
+
readonly maxTurns: number
|
|
5
|
+
readonly maxRetries: number
|
|
6
|
+
readonly retryBaseDelayMs: number
|
|
7
|
+
readonly toolConcurrency: number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class LoopConfig extends Context.Service<LoopConfig, LoopConfigShape>()(
|
|
11
|
+
'@yolk-sdk/agent/loop/LoopConfig'
|
|
12
|
+
) {
|
|
13
|
+
static layer = (config: LoopConfigShape) => Layer.succeed(this, config)
|
|
14
|
+
static defaultLayer = this.layer({
|
|
15
|
+
maxTurns: 500,
|
|
16
|
+
maxRetries: 2,
|
|
17
|
+
retryBaseDelayMs: 1000,
|
|
18
|
+
toolConcurrency: 4
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Context } from 'effect'
|
|
2
|
+
import type { Effect } from 'effect'
|
|
3
|
+
import type { ToolCall, ToolResult } from '@yolk-sdk/agent/protocol'
|
|
4
|
+
import type { ToolError } from '../error.ts'
|
|
5
|
+
|
|
6
|
+
export class ToolExecutor extends Context.Service<
|
|
7
|
+
ToolExecutor,
|
|
8
|
+
{
|
|
9
|
+
readonly execute: (call: ToolCall) => Effect.Effect<ToolResult, ToolError>
|
|
10
|
+
}
|
|
11
|
+
>()('@yolk-sdk/agent/loop/ToolExecutor') {}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Effect, Layer, Ref, Stream } from 'effect'
|
|
2
|
+
import { AgentInputUsage, AgentOutputUsage, AgentUsage, ToolCall } from '@yolk-sdk/agent/protocol'
|
|
3
|
+
import { FauxExhaustedError } from '../error.ts'
|
|
4
|
+
import {
|
|
5
|
+
LLMDone,
|
|
6
|
+
LLMReasoningDelta,
|
|
7
|
+
LLMTextDelta,
|
|
8
|
+
LLMToolCall,
|
|
9
|
+
LLMUsage,
|
|
10
|
+
type LLMEvent
|
|
11
|
+
} from '../llm-event.ts'
|
|
12
|
+
import { LLMProvider, type LLMRequest } from '../services/llm-provider.ts'
|
|
13
|
+
|
|
14
|
+
export type FauxResponse = {
|
|
15
|
+
readonly events: ReadonlyArray<LLMEvent>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Reply = {
|
|
19
|
+
text: (text: string): FauxResponse => ({
|
|
20
|
+
events: [
|
|
21
|
+
...text.split('').map(character => LLMTextDelta.make({ text: character })),
|
|
22
|
+
LLMDone.make({ stopReason: 'stop' })
|
|
23
|
+
]
|
|
24
|
+
}),
|
|
25
|
+
reasoningText: (reasoning: string, text: string): FauxResponse => ({
|
|
26
|
+
events: [
|
|
27
|
+
LLMReasoningDelta.make({ text: reasoning }),
|
|
28
|
+
...text.split('').map(character => LLMTextDelta.make({ text: character })),
|
|
29
|
+
LLMDone.make({ stopReason: 'stop' })
|
|
30
|
+
]
|
|
31
|
+
}),
|
|
32
|
+
toolCall: (input: {
|
|
33
|
+
readonly id: string
|
|
34
|
+
readonly name: string
|
|
35
|
+
readonly params: unknown
|
|
36
|
+
}): FauxResponse => ({
|
|
37
|
+
events: [
|
|
38
|
+
LLMToolCall.make({
|
|
39
|
+
call: ToolCall.make({ id: input.id, name: input.name, params: input.params })
|
|
40
|
+
}),
|
|
41
|
+
LLMDone.make({ stopReason: 'tool_use' })
|
|
42
|
+
]
|
|
43
|
+
}),
|
|
44
|
+
usage: (input: { readonly input: number; readonly output: number }): FauxResponse => ({
|
|
45
|
+
events: [
|
|
46
|
+
LLMUsage.make({
|
|
47
|
+
usage: AgentUsage.make({
|
|
48
|
+
input: AgentInputUsage.make({ total: input.input }),
|
|
49
|
+
output: AgentOutputUsage.make({ total: input.output })
|
|
50
|
+
})
|
|
51
|
+
}),
|
|
52
|
+
LLMDone.make({ stopReason: 'stop' })
|
|
53
|
+
]
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const takeResponse = (responses: Ref.Ref<ReadonlyArray<FauxResponse>>) =>
|
|
58
|
+
Effect.gen(function* () {
|
|
59
|
+
const current = yield* Ref.get(responses)
|
|
60
|
+
const response = current[0]
|
|
61
|
+
|
|
62
|
+
if (response === undefined) {
|
|
63
|
+
return yield* Effect.fail(
|
|
64
|
+
new FauxExhaustedError({ message: 'No more faux responses queued' })
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
yield* Ref.set(responses, current.slice(1))
|
|
69
|
+
return response
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
export const FauxProvider = {
|
|
73
|
+
layer: (...initialResponses: ReadonlyArray<FauxResponse>) =>
|
|
74
|
+
FauxProvider.layerWithRequests({ responses: initialResponses, requests: [] }),
|
|
75
|
+
layerWithRequests: (input: {
|
|
76
|
+
readonly responses: ReadonlyArray<FauxResponse>
|
|
77
|
+
readonly requests: Array<LLMRequest>
|
|
78
|
+
}) =>
|
|
79
|
+
Layer.effect(
|
|
80
|
+
LLMProvider,
|
|
81
|
+
Effect.gen(function* () {
|
|
82
|
+
const responses = yield* Ref.make(input.responses)
|
|
83
|
+
|
|
84
|
+
return LLMProvider.of({
|
|
85
|
+
stream: request => {
|
|
86
|
+
input.requests.push(request)
|
|
87
|
+
return Stream.fromEffect(takeResponse(responses)).pipe(
|
|
88
|
+
Stream.flatMap(response => Stream.fromIterable(response.events))
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
)
|
|
94
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Effect, Layer } from 'effect'
|
|
2
|
+
import { ToolResult } from '@yolk-sdk/agent/protocol'
|
|
3
|
+
import { ToolError } from '../error.ts'
|
|
4
|
+
import { ToolExecutor } from '../services/tool-executor.ts'
|
|
5
|
+
|
|
6
|
+
export const TestToolExecutor = {
|
|
7
|
+
layer: (resultsByName: Readonly<Record<string, string>>) =>
|
|
8
|
+
Layer.succeed(
|
|
9
|
+
ToolExecutor,
|
|
10
|
+
ToolExecutor.of({
|
|
11
|
+
execute: call => {
|
|
12
|
+
const content = resultsByName[call.name]
|
|
13
|
+
|
|
14
|
+
if (content === undefined) {
|
|
15
|
+
return Effect.fail(
|
|
16
|
+
new ToolError({
|
|
17
|
+
tool: call.name,
|
|
18
|
+
message: `No canned result for tool: ${call.name}`,
|
|
19
|
+
cause: 'execution'
|
|
20
|
+
})
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return Effect.succeed(ToolResult.make({ toolCallId: call.id, content }))
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @yolk-sdk/agent/protocol
|
|
2
|
+
|
|
3
|
+
Domain-free agent protocol types and helpers.
|
|
4
|
+
|
|
5
|
+
## What it provides
|
|
6
|
+
|
|
7
|
+
- Agent transcript message schemas.
|
|
8
|
+
- Streamed agent event schemas.
|
|
9
|
+
- Tool definition/call/result schemas.
|
|
10
|
+
- HITL approval/question request and response schemas.
|
|
11
|
+
- Text/image/audio content helpers.
|
|
12
|
+
- Model capability and reasoning config types.
|
|
13
|
+
|
|
14
|
+
## Use it when
|
|
15
|
+
|
|
16
|
+
- Building providers, loops, clients, or transports that need the shared Yolk agent wire model.
|
|
17
|
+
- Converting app state into protocol messages before an agent run.
|
|
18
|
+
- Rendering or storing provider-produced agent events.
|
|
19
|
+
|
|
20
|
+
## Boundaries
|
|
21
|
+
|
|
22
|
+
- No provider SDKs.
|
|
23
|
+
- No app auth, storage, routes, or product concepts.
|
|
24
|
+
- No transport assumptions.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
|
|
3
|
+
export class AgentContentCapabilities extends Schema.Class<AgentContentCapabilities>(
|
|
4
|
+
'AgentContentCapabilities'
|
|
5
|
+
)({
|
|
6
|
+
text: Schema.Boolean,
|
|
7
|
+
image: Schema.Boolean,
|
|
8
|
+
audio: Schema.Boolean
|
|
9
|
+
}) {}
|
|
10
|
+
|
|
11
|
+
export class AgentModelCapabilities extends Schema.Class<AgentModelCapabilities>(
|
|
12
|
+
'AgentModelCapabilities'
|
|
13
|
+
)({
|
|
14
|
+
input: AgentContentCapabilities,
|
|
15
|
+
tools: Schema.Boolean,
|
|
16
|
+
reasoning: Schema.Boolean
|
|
17
|
+
}) {}
|
|
18
|
+
|
|
19
|
+
export const textOnlyModelCapabilities = AgentModelCapabilities.make({
|
|
20
|
+
input: AgentContentCapabilities.make({ text: true, image: false, audio: false }),
|
|
21
|
+
tools: true,
|
|
22
|
+
reasoning: true
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
export const textImageModelCapabilities = AgentModelCapabilities.make({
|
|
26
|
+
input: AgentContentCapabilities.make({ text: true, image: true, audio: false }),
|
|
27
|
+
tools: true,
|
|
28
|
+
reasoning: true
|
|
29
|
+
})
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Array as Arr, Option } from 'effect'
|
|
2
|
+
import * as Schema from 'effect/Schema'
|
|
3
|
+
|
|
4
|
+
export class TextPart extends Schema.TaggedClass<TextPart>()('Text', {
|
|
5
|
+
text: Schema.String
|
|
6
|
+
}) {}
|
|
7
|
+
|
|
8
|
+
export class ImagePart extends Schema.TaggedClass<ImagePart>()('Image', {
|
|
9
|
+
data: Schema.String,
|
|
10
|
+
mimeType: Schema.String
|
|
11
|
+
}) {}
|
|
12
|
+
|
|
13
|
+
export class AudioPart extends Schema.TaggedClass<AudioPart>()('Audio', {
|
|
14
|
+
data: Schema.String,
|
|
15
|
+
format: Schema.Literals(['pcm16', 'wav', 'mp3', 'opus'])
|
|
16
|
+
}) {}
|
|
17
|
+
|
|
18
|
+
export const ContentPart = Schema.Union([TextPart, ImagePart, AudioPart])
|
|
19
|
+
export type ContentPart = typeof ContentPart.Type
|
|
20
|
+
|
|
21
|
+
export const Content = Schema.Union([Schema.String, Schema.Array(ContentPart)])
|
|
22
|
+
export type Content = typeof Content.Type
|
|
23
|
+
|
|
24
|
+
export const contentPartText = (part: ContentPart) => {
|
|
25
|
+
switch (part._tag) {
|
|
26
|
+
case 'Text':
|
|
27
|
+
return part.text
|
|
28
|
+
case 'Image':
|
|
29
|
+
case 'Audio':
|
|
30
|
+
return ''
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const contentPartPreview = (part: ContentPart) => {
|
|
35
|
+
switch (part._tag) {
|
|
36
|
+
case 'Text':
|
|
37
|
+
return part.text
|
|
38
|
+
case 'Image':
|
|
39
|
+
return 'Image'
|
|
40
|
+
case 'Audio':
|
|
41
|
+
return 'Audio'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const contentText = (content: Content) =>
|
|
46
|
+
typeof content === 'string' ? content : Arr.map(content, contentPartText).join('')
|
|
47
|
+
|
|
48
|
+
export const contentPreview = (content: Content) =>
|
|
49
|
+
typeof content === 'string' ? content : Arr.map(content, contentPartPreview).join(', ')
|
|
50
|
+
|
|
51
|
+
export const contentParts = (content: Content): ReadonlyArray<ContentPart> =>
|
|
52
|
+
typeof content === 'string' ? [TextPart.make({ text: content })] : content
|
|
53
|
+
|
|
54
|
+
export const isContentEmpty = (content: Content) =>
|
|
55
|
+
typeof content === 'string'
|
|
56
|
+
? content.length === 0
|
|
57
|
+
: content.length === 0 ||
|
|
58
|
+
Arr.every(content, part => part._tag === 'Text' && part.text.length === 0)
|
|
59
|
+
|
|
60
|
+
export const appendTextToContent = (content: Content, text: string): Content => {
|
|
61
|
+
if (typeof content === 'string') {
|
|
62
|
+
return `${content}${text}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return Option.match(Arr.last(content), {
|
|
66
|
+
onNone: () => [TextPart.make({ text })],
|
|
67
|
+
onSome: last =>
|
|
68
|
+
last._tag !== 'Text'
|
|
69
|
+
? [...content, TextPart.make({ text })]
|
|
70
|
+
: Arr.map(content, (part, index) =>
|
|
71
|
+
index === content.length - 1 && part._tag === 'Text'
|
|
72
|
+
? TextPart.make({ text: `${part.text}${text}` })
|
|
73
|
+
: part
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
import { AssistantAgentMessage, AgentMessage } from './message.ts'
|
|
3
|
+
import {
|
|
4
|
+
HitlRequest,
|
|
5
|
+
QuestionRequest,
|
|
6
|
+
QuestionResponse,
|
|
7
|
+
ToolApprovalRequest,
|
|
8
|
+
ToolApprovalResponse,
|
|
9
|
+
ToolCall,
|
|
10
|
+
ToolResult
|
|
11
|
+
} from './tool.ts'
|
|
12
|
+
import { AgentUsage } from './usage.ts'
|
|
13
|
+
|
|
14
|
+
const NonEmptyTrimmedString = Schema.Trimmed.pipe(Schema.check(Schema.isNonEmpty()))
|
|
15
|
+
|
|
16
|
+
const EventIdentity = {
|
|
17
|
+
eventId: Schema.optional(NonEmptyTrimmedString),
|
|
18
|
+
createdAtMs: Schema.optional(Schema.Number)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const SubagentStatus = Schema.Literals(['running', 'completed', 'error'])
|
|
22
|
+
export type SubagentStatus = typeof SubagentStatus.Type
|
|
23
|
+
|
|
24
|
+
export const AgentErrorCode = Schema.Literals([
|
|
25
|
+
'validation_error',
|
|
26
|
+
'provider_error',
|
|
27
|
+
'rate_limit',
|
|
28
|
+
'context_overflow',
|
|
29
|
+
'invalid_response',
|
|
30
|
+
'tool_error',
|
|
31
|
+
'tool_denied',
|
|
32
|
+
'tool_timeout',
|
|
33
|
+
'store_error',
|
|
34
|
+
'aborted',
|
|
35
|
+
'session_not_found',
|
|
36
|
+
'conflict',
|
|
37
|
+
'unknown'
|
|
38
|
+
])
|
|
39
|
+
export type AgentErrorCode = typeof AgentErrorCode.Type
|
|
40
|
+
|
|
41
|
+
export class AgentStart extends Schema.TaggedClass<AgentStart>()('AgentStart', {
|
|
42
|
+
...EventIdentity
|
|
43
|
+
}) {}
|
|
44
|
+
|
|
45
|
+
export class AgentError extends Schema.TaggedClass<AgentError>()('AgentError', {
|
|
46
|
+
...EventIdentity,
|
|
47
|
+
code: AgentErrorCode,
|
|
48
|
+
message: Schema.String,
|
|
49
|
+
retryable: Schema.Boolean
|
|
50
|
+
}) {}
|
|
51
|
+
|
|
52
|
+
export class AgentEnd extends Schema.TaggedClass<AgentEnd>()('AgentEnd', {
|
|
53
|
+
...EventIdentity,
|
|
54
|
+
messages: Schema.Array(AgentMessage),
|
|
55
|
+
turns: Schema.Number,
|
|
56
|
+
usage: AgentUsage
|
|
57
|
+
}) {}
|
|
58
|
+
|
|
59
|
+
export class AgentAwaitingInput extends Schema.TaggedClass<AgentAwaitingInput>()(
|
|
60
|
+
'AgentAwaitingInput',
|
|
61
|
+
{
|
|
62
|
+
...EventIdentity,
|
|
63
|
+
requests: Schema.NonEmptyArray(HitlRequest),
|
|
64
|
+
messages: Schema.Array(AgentMessage),
|
|
65
|
+
turns: Schema.Number,
|
|
66
|
+
usage: AgentUsage
|
|
67
|
+
}
|
|
68
|
+
) {}
|
|
69
|
+
|
|
70
|
+
export class UsageUpdate extends Schema.TaggedClass<UsageUpdate>()('UsageUpdate', {
|
|
71
|
+
...EventIdentity,
|
|
72
|
+
usage: AgentUsage
|
|
73
|
+
}) {}
|
|
74
|
+
|
|
75
|
+
export class AgentRetry extends Schema.TaggedClass<AgentRetry>()('AgentRetry', {
|
|
76
|
+
...EventIdentity,
|
|
77
|
+
attempt: Schema.Number,
|
|
78
|
+
reason: AgentErrorCode,
|
|
79
|
+
delayMs: Schema.Number,
|
|
80
|
+
message: Schema.String
|
|
81
|
+
}) {}
|
|
82
|
+
|
|
83
|
+
export class CompactionStart extends Schema.TaggedClass<CompactionStart>()('CompactionStart', {
|
|
84
|
+
...EventIdentity,
|
|
85
|
+
strategy: Schema.String
|
|
86
|
+
}) {}
|
|
87
|
+
|
|
88
|
+
export class CompactionEnd extends Schema.TaggedClass<CompactionEnd>()('CompactionEnd', {
|
|
89
|
+
...EventIdentity,
|
|
90
|
+
strategy: Schema.String,
|
|
91
|
+
beforeTokens: Schema.optional(Schema.Number),
|
|
92
|
+
afterTokens: Schema.optional(Schema.Number)
|
|
93
|
+
}) {}
|
|
94
|
+
|
|
95
|
+
export class TurnStart extends Schema.TaggedClass<TurnStart>()('TurnStart', {
|
|
96
|
+
...EventIdentity,
|
|
97
|
+
turn: Schema.Number
|
|
98
|
+
}) {}
|
|
99
|
+
|
|
100
|
+
export class TurnEnd extends Schema.TaggedClass<TurnEnd>()('TurnEnd', {
|
|
101
|
+
...EventIdentity,
|
|
102
|
+
turn: Schema.Number,
|
|
103
|
+
reason: Schema.Literals(['stop', 'tool_use'])
|
|
104
|
+
}) {}
|
|
105
|
+
|
|
106
|
+
export class LLMStreamStart extends Schema.TaggedClass<LLMStreamStart>()('LLMStreamStart', {
|
|
107
|
+
...EventIdentity,
|
|
108
|
+
turn: Schema.Number
|
|
109
|
+
}) {}
|
|
110
|
+
|
|
111
|
+
export class LLMTextDelta extends Schema.TaggedClass<LLMTextDelta>()('LLMTextDelta', {
|
|
112
|
+
...EventIdentity,
|
|
113
|
+
text: Schema.String
|
|
114
|
+
}) {}
|
|
115
|
+
|
|
116
|
+
export class LLMReasoningDelta extends Schema.TaggedClass<LLMReasoningDelta>()(
|
|
117
|
+
'LLMReasoningDelta',
|
|
118
|
+
{
|
|
119
|
+
...EventIdentity,
|
|
120
|
+
text: Schema.String
|
|
121
|
+
}
|
|
122
|
+
) {}
|
|
123
|
+
|
|
124
|
+
export class ToolInputStart extends Schema.TaggedClass<ToolInputStart>()('ToolInputStart', {
|
|
125
|
+
...EventIdentity,
|
|
126
|
+
id: Schema.String,
|
|
127
|
+
name: Schema.optional(Schema.String)
|
|
128
|
+
}) {}
|
|
129
|
+
|
|
130
|
+
export class ToolInputDelta extends Schema.TaggedClass<ToolInputDelta>()('ToolInputDelta', {
|
|
131
|
+
...EventIdentity,
|
|
132
|
+
id: Schema.String,
|
|
133
|
+
delta: Schema.String
|
|
134
|
+
}) {}
|
|
135
|
+
|
|
136
|
+
export class ToolInputEnd extends Schema.TaggedClass<ToolInputEnd>()('ToolInputEnd', {
|
|
137
|
+
...EventIdentity,
|
|
138
|
+
call: ToolCall
|
|
139
|
+
}) {}
|
|
140
|
+
|
|
141
|
+
export class ToolApprovalRequested extends Schema.TaggedClass<ToolApprovalRequested>()(
|
|
142
|
+
'ToolApprovalRequested',
|
|
143
|
+
{
|
|
144
|
+
...EventIdentity,
|
|
145
|
+
call: ToolCall,
|
|
146
|
+
request: Schema.optional(ToolApprovalRequest)
|
|
147
|
+
}
|
|
148
|
+
) {}
|
|
149
|
+
|
|
150
|
+
export class ToolApprovalGranted extends Schema.TaggedClass<ToolApprovalGranted>()(
|
|
151
|
+
'ToolApprovalGranted',
|
|
152
|
+
{
|
|
153
|
+
...EventIdentity,
|
|
154
|
+
toolCallId: Schema.String,
|
|
155
|
+
response: Schema.optional(ToolApprovalResponse)
|
|
156
|
+
}
|
|
157
|
+
) {}
|
|
158
|
+
|
|
159
|
+
export class ToolApprovalDenied extends Schema.TaggedClass<ToolApprovalDenied>()(
|
|
160
|
+
'ToolApprovalDenied',
|
|
161
|
+
{
|
|
162
|
+
...EventIdentity,
|
|
163
|
+
toolCallId: Schema.String,
|
|
164
|
+
reason: Schema.String,
|
|
165
|
+
response: Schema.optional(ToolApprovalResponse)
|
|
166
|
+
}
|
|
167
|
+
) {}
|
|
168
|
+
|
|
169
|
+
export class QuestionRequested extends Schema.TaggedClass<QuestionRequested>()('QuestionRequested', {
|
|
170
|
+
...EventIdentity,
|
|
171
|
+
request: QuestionRequest
|
|
172
|
+
}) {}
|
|
173
|
+
|
|
174
|
+
export class QuestionAnswered extends Schema.TaggedClass<QuestionAnswered>()('QuestionAnswered', {
|
|
175
|
+
...EventIdentity,
|
|
176
|
+
response: QuestionResponse
|
|
177
|
+
}) {}
|
|
178
|
+
|
|
179
|
+
export class QuestionCancelled extends Schema.TaggedClass<QuestionCancelled>()('QuestionCancelled', {
|
|
180
|
+
...EventIdentity,
|
|
181
|
+
response: QuestionResponse
|
|
182
|
+
}) {}
|
|
183
|
+
|
|
184
|
+
export class LLMStreamEnd extends Schema.TaggedClass<LLMStreamEnd>()('LLMStreamEnd', {
|
|
185
|
+
...EventIdentity,
|
|
186
|
+
turn: Schema.Number
|
|
187
|
+
}) {}
|
|
188
|
+
|
|
189
|
+
export class AssistantMessageEvent extends Schema.TaggedClass<AssistantMessageEvent>()(
|
|
190
|
+
'AssistantMessage',
|
|
191
|
+
{
|
|
192
|
+
...EventIdentity,
|
|
193
|
+
message: AssistantAgentMessage
|
|
194
|
+
}
|
|
195
|
+
) {}
|
|
196
|
+
|
|
197
|
+
export class ToolExecutionStarted extends Schema.TaggedClass<ToolExecutionStarted>()(
|
|
198
|
+
'ToolExecutionStarted',
|
|
199
|
+
{
|
|
200
|
+
...EventIdentity,
|
|
201
|
+
call: ToolCall
|
|
202
|
+
}
|
|
203
|
+
) {}
|
|
204
|
+
|
|
205
|
+
export class ToolExecutionCompleted extends Schema.TaggedClass<ToolExecutionCompleted>()(
|
|
206
|
+
'ToolExecutionCompleted',
|
|
207
|
+
{
|
|
208
|
+
...EventIdentity,
|
|
209
|
+
call: ToolCall,
|
|
210
|
+
result: ToolResult
|
|
211
|
+
}
|
|
212
|
+
) {}
|
|
213
|
+
|
|
214
|
+
export class ToolExecutionError extends Schema.TaggedClass<ToolExecutionError>()(
|
|
215
|
+
'ToolExecutionError',
|
|
216
|
+
{
|
|
217
|
+
...EventIdentity,
|
|
218
|
+
call: ToolCall,
|
|
219
|
+
message: Schema.String,
|
|
220
|
+
code: AgentErrorCode
|
|
221
|
+
}
|
|
222
|
+
) {}
|
|
223
|
+
|
|
224
|
+
export class ProviderToolResult extends Schema.TaggedClass<ProviderToolResult>()(
|
|
225
|
+
'ProviderToolResult',
|
|
226
|
+
{
|
|
227
|
+
...EventIdentity,
|
|
228
|
+
call: ToolCall,
|
|
229
|
+
result: ToolResult
|
|
230
|
+
}
|
|
231
|
+
) {}
|
|
232
|
+
|
|
233
|
+
export class SubagentStarted extends Schema.TaggedClass<SubagentStarted>()('SubagentStarted', {
|
|
234
|
+
...EventIdentity,
|
|
235
|
+
parentToolCallId: NonEmptyTrimmedString,
|
|
236
|
+
subagentRunId: NonEmptyTrimmedString,
|
|
237
|
+
subagentType: NonEmptyTrimmedString,
|
|
238
|
+
description: Schema.String,
|
|
239
|
+
model: Schema.String
|
|
240
|
+
}) {}
|
|
241
|
+
|
|
242
|
+
export class SubagentCompleted extends Schema.TaggedClass<SubagentCompleted>()('SubagentCompleted', {
|
|
243
|
+
...EventIdentity,
|
|
244
|
+
parentToolCallId: NonEmptyTrimmedString,
|
|
245
|
+
subagentRunId: NonEmptyTrimmedString,
|
|
246
|
+
subagentType: NonEmptyTrimmedString,
|
|
247
|
+
description: Schema.String,
|
|
248
|
+
model: Schema.String,
|
|
249
|
+
status: SubagentStatus,
|
|
250
|
+
durationMs: Schema.Number,
|
|
251
|
+
summary: Schema.optional(Schema.String)
|
|
252
|
+
}) {}
|
|
253
|
+
|
|
254
|
+
export const AgentEvent = Schema.Union([
|
|
255
|
+
AgentStart,
|
|
256
|
+
AgentError,
|
|
257
|
+
AgentEnd,
|
|
258
|
+
AgentAwaitingInput,
|
|
259
|
+
UsageUpdate,
|
|
260
|
+
AgentRetry,
|
|
261
|
+
CompactionStart,
|
|
262
|
+
CompactionEnd,
|
|
263
|
+
TurnStart,
|
|
264
|
+
TurnEnd,
|
|
265
|
+
LLMStreamStart,
|
|
266
|
+
LLMTextDelta,
|
|
267
|
+
LLMReasoningDelta,
|
|
268
|
+
ToolInputStart,
|
|
269
|
+
ToolInputDelta,
|
|
270
|
+
ToolInputEnd,
|
|
271
|
+
LLMStreamEnd,
|
|
272
|
+
AssistantMessageEvent,
|
|
273
|
+
ToolApprovalRequested,
|
|
274
|
+
ToolApprovalGranted,
|
|
275
|
+
ToolApprovalDenied,
|
|
276
|
+
QuestionRequested,
|
|
277
|
+
QuestionAnswered,
|
|
278
|
+
QuestionCancelled,
|
|
279
|
+
ToolExecutionStarted,
|
|
280
|
+
ToolExecutionCompleted,
|
|
281
|
+
ToolExecutionError,
|
|
282
|
+
ProviderToolResult,
|
|
283
|
+
SubagentStarted,
|
|
284
|
+
SubagentCompleted
|
|
285
|
+
])
|
|
286
|
+
export type AgentEvent = typeof AgentEvent.Type
|