@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,109 @@
|
|
|
1
|
+
export {
|
|
2
|
+
AgentContentCapabilities,
|
|
3
|
+
AgentModelCapabilities,
|
|
4
|
+
textImageModelCapabilities,
|
|
5
|
+
textOnlyModelCapabilities
|
|
6
|
+
} from './capability.ts'
|
|
7
|
+
export {
|
|
8
|
+
appendTextToContent,
|
|
9
|
+
AudioPart,
|
|
10
|
+
Content,
|
|
11
|
+
ContentPart,
|
|
12
|
+
contentParts,
|
|
13
|
+
contentPartPreview,
|
|
14
|
+
contentPartText,
|
|
15
|
+
contentPreview,
|
|
16
|
+
contentText,
|
|
17
|
+
ImagePart,
|
|
18
|
+
isContentEmpty,
|
|
19
|
+
TextPart
|
|
20
|
+
} from './content.ts'
|
|
21
|
+
export {
|
|
22
|
+
AgentAwaitingInput,
|
|
23
|
+
AgentEnd,
|
|
24
|
+
AgentError,
|
|
25
|
+
AgentErrorCode,
|
|
26
|
+
AgentEvent,
|
|
27
|
+
AgentRetry,
|
|
28
|
+
AgentStart,
|
|
29
|
+
AssistantMessageEvent,
|
|
30
|
+
CompactionEnd,
|
|
31
|
+
CompactionStart,
|
|
32
|
+
LLMReasoningDelta,
|
|
33
|
+
LLMStreamEnd,
|
|
34
|
+
LLMStreamStart,
|
|
35
|
+
LLMTextDelta,
|
|
36
|
+
ProviderToolResult,
|
|
37
|
+
QuestionAnswered,
|
|
38
|
+
QuestionCancelled,
|
|
39
|
+
QuestionRequested,
|
|
40
|
+
SubagentCompleted,
|
|
41
|
+
SubagentStarted,
|
|
42
|
+
SubagentStatus,
|
|
43
|
+
ToolApprovalDenied,
|
|
44
|
+
ToolApprovalGranted,
|
|
45
|
+
ToolApprovalRequested,
|
|
46
|
+
ToolExecutionCompleted,
|
|
47
|
+
ToolExecutionError,
|
|
48
|
+
ToolExecutionStarted,
|
|
49
|
+
ToolInputDelta,
|
|
50
|
+
ToolInputEnd,
|
|
51
|
+
ToolInputStart,
|
|
52
|
+
TurnEnd,
|
|
53
|
+
TurnStart,
|
|
54
|
+
UsageUpdate
|
|
55
|
+
} from './event.ts'
|
|
56
|
+
export {
|
|
57
|
+
AgentMessage,
|
|
58
|
+
AssistantAgentMessage,
|
|
59
|
+
AssistantPart,
|
|
60
|
+
AssistantReasoningPart,
|
|
61
|
+
AssistantTextPart,
|
|
62
|
+
HostToolCallPart,
|
|
63
|
+
ProviderToolCallPart,
|
|
64
|
+
ProviderToolResultPart,
|
|
65
|
+
ToolResultMessage,
|
|
66
|
+
UserMessage,
|
|
67
|
+
assistantContent,
|
|
68
|
+
assistantHostToolCalls,
|
|
69
|
+
assistantReasoningText
|
|
70
|
+
} from './message.ts'
|
|
71
|
+
export { AgentReasoningEffort } from './reasoning.ts'
|
|
72
|
+
export {
|
|
73
|
+
AgentWebSocketClientMessage,
|
|
74
|
+
AgentWebSocketServerMessage,
|
|
75
|
+
SessionSnapshot,
|
|
76
|
+
QuestionResponseInput,
|
|
77
|
+
ToolApprovalResponseInput,
|
|
78
|
+
UserInput
|
|
79
|
+
} from './session.ts'
|
|
80
|
+
export {
|
|
81
|
+
HitlRequest,
|
|
82
|
+
HitlResponse,
|
|
83
|
+
HitlResponseSource,
|
|
84
|
+
QuestionAnswer,
|
|
85
|
+
QuestionOption,
|
|
86
|
+
QuestionPrompt,
|
|
87
|
+
QuestionRequest,
|
|
88
|
+
QuestionResponse,
|
|
89
|
+
QuestionResponseOutcome,
|
|
90
|
+
QuestionToolParams,
|
|
91
|
+
formatQuestionResponseContent,
|
|
92
|
+
ToolApprovalDecision,
|
|
93
|
+
ToolApprovalMode,
|
|
94
|
+
ToolApprovalPolicy,
|
|
95
|
+
ToolApprovalRequest,
|
|
96
|
+
ToolApprovalResponse,
|
|
97
|
+
ToolCall,
|
|
98
|
+
ToolDef,
|
|
99
|
+
ToolResult
|
|
100
|
+
} from './tool.ts'
|
|
101
|
+
export {
|
|
102
|
+
addAgentUsage,
|
|
103
|
+
AgentInputUsage,
|
|
104
|
+
AgentOutputUsage,
|
|
105
|
+
AgentUsage,
|
|
106
|
+
zeroAgentUsage
|
|
107
|
+
} from './usage.ts'
|
|
108
|
+
|
|
109
|
+
export type MessageId = string
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
import { Content, contentParts } from './content.ts'
|
|
3
|
+
import { ToolCall, ToolResult } from './tool.ts'
|
|
4
|
+
|
|
5
|
+
export class UserMessage extends Schema.TaggedClass<UserMessage>()('User', {
|
|
6
|
+
content: Content
|
|
7
|
+
}) {}
|
|
8
|
+
|
|
9
|
+
export class AssistantTextPart extends Schema.TaggedClass<AssistantTextPart>()('Text', {
|
|
10
|
+
content: Content
|
|
11
|
+
}) {}
|
|
12
|
+
|
|
13
|
+
export class AssistantReasoningPart extends Schema.TaggedClass<AssistantReasoningPart>()(
|
|
14
|
+
'Reasoning',
|
|
15
|
+
{
|
|
16
|
+
text: Schema.String
|
|
17
|
+
}
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
export class HostToolCallPart extends Schema.TaggedClass<HostToolCallPart>()('HostToolCall', {
|
|
21
|
+
call: ToolCall
|
|
22
|
+
}) {}
|
|
23
|
+
|
|
24
|
+
export class ProviderToolCallPart extends Schema.TaggedClass<ProviderToolCallPart>()(
|
|
25
|
+
'ProviderToolCall',
|
|
26
|
+
{
|
|
27
|
+
call: ToolCall,
|
|
28
|
+
providerMetadata: Schema.optional(Schema.Unknown)
|
|
29
|
+
}
|
|
30
|
+
) {}
|
|
31
|
+
|
|
32
|
+
export class ProviderToolResultPart extends Schema.TaggedClass<ProviderToolResultPart>()(
|
|
33
|
+
'ProviderToolResult',
|
|
34
|
+
{
|
|
35
|
+
toolCallId: Schema.String,
|
|
36
|
+
result: ToolResult,
|
|
37
|
+
providerMetadata: Schema.optional(Schema.Unknown)
|
|
38
|
+
}
|
|
39
|
+
) {}
|
|
40
|
+
|
|
41
|
+
export const AssistantPart = Schema.Union([
|
|
42
|
+
AssistantTextPart,
|
|
43
|
+
AssistantReasoningPart,
|
|
44
|
+
HostToolCallPart,
|
|
45
|
+
ProviderToolCallPart,
|
|
46
|
+
ProviderToolResultPart
|
|
47
|
+
])
|
|
48
|
+
export type AssistantPart = typeof AssistantPart.Type
|
|
49
|
+
|
|
50
|
+
export class AssistantAgentMessage extends Schema.TaggedClass<AssistantAgentMessage>()(
|
|
51
|
+
'Assistant',
|
|
52
|
+
{
|
|
53
|
+
parts: Schema.Array(AssistantPart)
|
|
54
|
+
}
|
|
55
|
+
) {}
|
|
56
|
+
|
|
57
|
+
export class ToolResultMessage extends Schema.TaggedClass<ToolResultMessage>()('ToolResult', {
|
|
58
|
+
toolCallId: Schema.String,
|
|
59
|
+
content: Content,
|
|
60
|
+
isError: Schema.optional(Schema.Boolean),
|
|
61
|
+
structuredContent: Schema.optional(Schema.Unknown)
|
|
62
|
+
}) {}
|
|
63
|
+
|
|
64
|
+
export const AgentMessage = Schema.Union([UserMessage, AssistantAgentMessage, ToolResultMessage])
|
|
65
|
+
export type AgentMessage = typeof AgentMessage.Type
|
|
66
|
+
|
|
67
|
+
export const assistantContent = (message: AssistantAgentMessage): Content => {
|
|
68
|
+
const parts = message.parts.flatMap(part => (part._tag === 'Text' ? [part.content] : []))
|
|
69
|
+
const first = parts[0]
|
|
70
|
+
|
|
71
|
+
if (parts.length === 0) {
|
|
72
|
+
return ''
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (parts.length === 1 && first !== undefined) {
|
|
76
|
+
return first
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return parts.flatMap(contentParts)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const assistantReasoningText = (message: AssistantAgentMessage) =>
|
|
83
|
+
message.parts.flatMap(part => (part._tag === 'Reasoning' ? [part.text] : [])).join('')
|
|
84
|
+
|
|
85
|
+
export const assistantHostToolCalls = (message: AssistantAgentMessage) =>
|
|
86
|
+
message.parts.flatMap(part => (part._tag === 'HostToolCall' ? [part.call] : []))
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
import { AgentEvent } from './event.ts'
|
|
3
|
+
import { AgentMessage, UserMessage } from './message.ts'
|
|
4
|
+
import { AgentReasoningEffort } from './reasoning.ts'
|
|
5
|
+
import { QuestionResponse, ToolApprovalResponse } from './tool.ts'
|
|
6
|
+
|
|
7
|
+
export class SessionSnapshot extends Schema.TaggedClass<SessionSnapshot>()('SessionSnapshot', {
|
|
8
|
+
revision: Schema.Number,
|
|
9
|
+
messages: Schema.Array(AgentMessage)
|
|
10
|
+
}) {}
|
|
11
|
+
|
|
12
|
+
export class UserInput extends Schema.TaggedClass<UserInput>()('UserInput', {
|
|
13
|
+
message: UserMessage,
|
|
14
|
+
expectedRevision: Schema.optional(Schema.Number),
|
|
15
|
+
model: Schema.optional(Schema.String),
|
|
16
|
+
reasoningEffort: Schema.optional(AgentReasoningEffort)
|
|
17
|
+
}) {}
|
|
18
|
+
|
|
19
|
+
export class ToolApprovalResponseInput extends Schema.TaggedClass<ToolApprovalResponseInput>()(
|
|
20
|
+
'ToolApprovalResponseInput',
|
|
21
|
+
{
|
|
22
|
+
response: ToolApprovalResponse,
|
|
23
|
+
expectedRevision: Schema.optional(Schema.Number),
|
|
24
|
+
model: Schema.optional(Schema.String),
|
|
25
|
+
reasoningEffort: Schema.optional(AgentReasoningEffort)
|
|
26
|
+
}
|
|
27
|
+
) {}
|
|
28
|
+
|
|
29
|
+
export class QuestionResponseInput extends Schema.TaggedClass<QuestionResponseInput>()(
|
|
30
|
+
'QuestionResponseInput',
|
|
31
|
+
{
|
|
32
|
+
response: QuestionResponse,
|
|
33
|
+
expectedRevision: Schema.optional(Schema.Number),
|
|
34
|
+
model: Schema.optional(Schema.String),
|
|
35
|
+
reasoningEffort: Schema.optional(AgentReasoningEffort)
|
|
36
|
+
}
|
|
37
|
+
) {}
|
|
38
|
+
|
|
39
|
+
export const AgentWebSocketClientMessage = Schema.Union([
|
|
40
|
+
UserInput,
|
|
41
|
+
ToolApprovalResponseInput,
|
|
42
|
+
QuestionResponseInput
|
|
43
|
+
])
|
|
44
|
+
export type AgentWebSocketClientMessage = typeof AgentWebSocketClientMessage.Type
|
|
45
|
+
|
|
46
|
+
export const AgentWebSocketServerMessage = Schema.Union([SessionSnapshot, AgentEvent])
|
|
47
|
+
export type AgentWebSocketServerMessage = typeof AgentWebSocketServerMessage.Type
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
import { Content } from './content.ts'
|
|
3
|
+
|
|
4
|
+
const NonEmptyTrimmedString = Schema.Trimmed.pipe(Schema.check(Schema.isNonEmpty()))
|
|
5
|
+
|
|
6
|
+
export const HitlResponseSource = Schema.Literals(['user', 'policy', 'replay'])
|
|
7
|
+
export type HitlResponseSource = typeof HitlResponseSource.Type
|
|
8
|
+
|
|
9
|
+
export const ToolApprovalDecision = Schema.Literals(['approved', 'denied'])
|
|
10
|
+
export type ToolApprovalDecision = typeof ToolApprovalDecision.Type
|
|
11
|
+
|
|
12
|
+
export const ToolApprovalMode = Schema.Literals(['manual'])
|
|
13
|
+
export type ToolApprovalMode = typeof ToolApprovalMode.Type
|
|
14
|
+
|
|
15
|
+
export class ToolApprovalPolicy extends Schema.Class<ToolApprovalPolicy>('ToolApprovalPolicy')({
|
|
16
|
+
mode: ToolApprovalMode,
|
|
17
|
+
reason: Schema.optional(Schema.String)
|
|
18
|
+
}) {}
|
|
19
|
+
|
|
20
|
+
export class ToolCall extends Schema.Class<ToolCall>('ToolCall')({
|
|
21
|
+
id: NonEmptyTrimmedString,
|
|
22
|
+
name: NonEmptyTrimmedString,
|
|
23
|
+
params: Schema.Unknown
|
|
24
|
+
}) {}
|
|
25
|
+
|
|
26
|
+
export class ToolDef extends Schema.Class<ToolDef>('ToolDef')({
|
|
27
|
+
name: NonEmptyTrimmedString,
|
|
28
|
+
description: Schema.String,
|
|
29
|
+
parameters: Schema.Unknown,
|
|
30
|
+
approval: Schema.optional(ToolApprovalPolicy)
|
|
31
|
+
}) {}
|
|
32
|
+
|
|
33
|
+
export class ToolResult extends Schema.Class<ToolResult>('ToolResult')({
|
|
34
|
+
toolCallId: NonEmptyTrimmedString,
|
|
35
|
+
content: Content,
|
|
36
|
+
isError: Schema.optional(Schema.Boolean),
|
|
37
|
+
structuredContent: Schema.optional(Schema.Unknown)
|
|
38
|
+
}) {}
|
|
39
|
+
|
|
40
|
+
export class ToolApprovalRequest extends Schema.TaggedClass<ToolApprovalRequest>()(
|
|
41
|
+
'ToolApprovalRequest',
|
|
42
|
+
{
|
|
43
|
+
requestId: NonEmptyTrimmedString,
|
|
44
|
+
toolCallId: NonEmptyTrimmedString,
|
|
45
|
+
call: ToolCall,
|
|
46
|
+
policy: Schema.optional(ToolApprovalPolicy)
|
|
47
|
+
}
|
|
48
|
+
) {}
|
|
49
|
+
|
|
50
|
+
export class ToolApprovalResponse extends Schema.TaggedClass<ToolApprovalResponse>()(
|
|
51
|
+
'ToolApprovalResponse',
|
|
52
|
+
{
|
|
53
|
+
requestId: NonEmptyTrimmedString,
|
|
54
|
+
toolCallId: NonEmptyTrimmedString,
|
|
55
|
+
decision: ToolApprovalDecision,
|
|
56
|
+
source: HitlResponseSource,
|
|
57
|
+
reason: Schema.optional(Schema.String)
|
|
58
|
+
}
|
|
59
|
+
) {}
|
|
60
|
+
|
|
61
|
+
export class QuestionOption extends Schema.Class<QuestionOption>('QuestionOption')({
|
|
62
|
+
id: NonEmptyTrimmedString,
|
|
63
|
+
label: NonEmptyTrimmedString,
|
|
64
|
+
description: Schema.optional(Schema.String)
|
|
65
|
+
}) {}
|
|
66
|
+
|
|
67
|
+
export class QuestionPrompt extends Schema.Class<QuestionPrompt>('QuestionPrompt')({
|
|
68
|
+
id: NonEmptyTrimmedString,
|
|
69
|
+
prompt: NonEmptyTrimmedString,
|
|
70
|
+
options: Schema.optional(Schema.Array(QuestionOption)),
|
|
71
|
+
multiple: Schema.optional(Schema.Boolean),
|
|
72
|
+
allowCustom: Schema.optional(Schema.Boolean),
|
|
73
|
+
required: Schema.optional(Schema.Boolean)
|
|
74
|
+
}) {}
|
|
75
|
+
|
|
76
|
+
export class QuestionToolParams extends Schema.Class<QuestionToolParams>('QuestionToolParams')({
|
|
77
|
+
questions: Schema.NonEmptyArray(QuestionPrompt)
|
|
78
|
+
}) {}
|
|
79
|
+
|
|
80
|
+
export class QuestionRequest extends Schema.TaggedClass<QuestionRequest>()('QuestionRequest', {
|
|
81
|
+
requestId: NonEmptyTrimmedString,
|
|
82
|
+
toolCallId: NonEmptyTrimmedString,
|
|
83
|
+
call: ToolCall,
|
|
84
|
+
questions: Schema.NonEmptyArray(QuestionPrompt)
|
|
85
|
+
}) {}
|
|
86
|
+
|
|
87
|
+
export class QuestionAnswer extends Schema.Class<QuestionAnswer>('QuestionAnswer')({
|
|
88
|
+
questionId: NonEmptyTrimmedString,
|
|
89
|
+
optionIds: Schema.optional(Schema.Array(NonEmptyTrimmedString)),
|
|
90
|
+
customAnswer: Schema.optional(Schema.String)
|
|
91
|
+
}) {}
|
|
92
|
+
|
|
93
|
+
export const QuestionResponseOutcome = Schema.Literals(['answered', 'cancelled'])
|
|
94
|
+
export type QuestionResponseOutcome = typeof QuestionResponseOutcome.Type
|
|
95
|
+
|
|
96
|
+
export class QuestionResponse extends Schema.TaggedClass<QuestionResponse>()('QuestionResponse', {
|
|
97
|
+
requestId: NonEmptyTrimmedString,
|
|
98
|
+
toolCallId: NonEmptyTrimmedString,
|
|
99
|
+
outcome: QuestionResponseOutcome,
|
|
100
|
+
source: HitlResponseSource,
|
|
101
|
+
answers: Schema.optional(Schema.Array(QuestionAnswer)),
|
|
102
|
+
reason: Schema.optional(Schema.String)
|
|
103
|
+
}) {}
|
|
104
|
+
|
|
105
|
+
const optionLabel = (question: QuestionPrompt, optionId: string) =>
|
|
106
|
+
question.options?.find(option => option.id === optionId)?.label ?? optionId
|
|
107
|
+
|
|
108
|
+
const questionForAnswer = (
|
|
109
|
+
questions: ReadonlyArray<QuestionPrompt>,
|
|
110
|
+
answer: QuestionAnswer
|
|
111
|
+
) => questions.find(question => question.id === answer.questionId)
|
|
112
|
+
|
|
113
|
+
const formatQuestionAnswer = (
|
|
114
|
+
answer: QuestionAnswer,
|
|
115
|
+
questions: ReadonlyArray<QuestionPrompt>
|
|
116
|
+
) => {
|
|
117
|
+
const question = questionForAnswer(questions, answer)
|
|
118
|
+
const prompt = question?.prompt ?? answer.questionId
|
|
119
|
+
const selected = answer.optionIds?.map(optionId =>
|
|
120
|
+
question === undefined ? optionId : optionLabel(question, optionId)
|
|
121
|
+
) ?? []
|
|
122
|
+
const custom = answer.customAnswer?.trim()
|
|
123
|
+
const values = custom === undefined || custom.length === 0 ? selected : [...selected, custom]
|
|
124
|
+
|
|
125
|
+
return values.length === 0 ? `- ${prompt}: answered` : `- ${prompt}: ${values.join(', ')}`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const formatQuestionResponseContent = (
|
|
129
|
+
response: QuestionResponse,
|
|
130
|
+
questions: ReadonlyArray<QuestionPrompt> = []
|
|
131
|
+
) => {
|
|
132
|
+
if (response.outcome === 'cancelled') {
|
|
133
|
+
return `Question cancelled: ${response.reason ?? 'Question cancelled'}`
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const answers = response.answers ?? []
|
|
137
|
+
|
|
138
|
+
if (answers.length === 0) {
|
|
139
|
+
return 'User answered the question, but no answer values were provided. Continue with this in mind.'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const formatted = answers
|
|
143
|
+
.map(answer => formatQuestionAnswer(answer, questions).slice('- '.length))
|
|
144
|
+
.join('; ')
|
|
145
|
+
const label = answers.length === 1 ? 'question' : 'questions'
|
|
146
|
+
|
|
147
|
+
return `User has answered your ${label}: ${formatted}. Continue with the user's answers in mind.`
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const HitlRequest = Schema.Union([ToolApprovalRequest, QuestionRequest])
|
|
151
|
+
export type HitlRequest = typeof HitlRequest.Type
|
|
152
|
+
|
|
153
|
+
export const HitlResponse = Schema.Union([ToolApprovalResponse, QuestionResponse])
|
|
154
|
+
export type HitlResponse = typeof HitlResponse.Type
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Array as Arr, Option } from 'effect'
|
|
2
|
+
import * as Schema from 'effect/Schema'
|
|
3
|
+
|
|
4
|
+
export class AgentInputUsage extends Schema.Class<AgentInputUsage>('AgentInputUsage')({
|
|
5
|
+
total: Schema.Number,
|
|
6
|
+
uncached: Schema.optional(Schema.Number),
|
|
7
|
+
cacheRead: Schema.optional(Schema.Number),
|
|
8
|
+
cacheWrite: Schema.optional(Schema.Number)
|
|
9
|
+
}) {}
|
|
10
|
+
|
|
11
|
+
export class AgentOutputUsage extends Schema.Class<AgentOutputUsage>('AgentOutputUsage')({
|
|
12
|
+
total: Schema.Number,
|
|
13
|
+
text: Schema.optional(Schema.Number),
|
|
14
|
+
reasoning: Schema.optional(Schema.Number)
|
|
15
|
+
}) {}
|
|
16
|
+
|
|
17
|
+
export class AgentUsage extends Schema.Class<AgentUsage>('AgentUsage')({
|
|
18
|
+
input: AgentInputUsage,
|
|
19
|
+
output: AgentOutputUsage
|
|
20
|
+
}) {}
|
|
21
|
+
|
|
22
|
+
export const zeroAgentUsage = AgentUsage.make({
|
|
23
|
+
input: AgentInputUsage.make({ total: 0 }),
|
|
24
|
+
output: AgentOutputUsage.make({ total: 0 })
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const sumOptional = (left: number | undefined, right: number | undefined) =>
|
|
28
|
+
Option.getOrUndefined(
|
|
29
|
+
Option.liftPredicate(
|
|
30
|
+
Arr.getSomes([Option.fromNullishOr(left), Option.fromNullishOr(right)]),
|
|
31
|
+
values => values.length > 0
|
|
32
|
+
).pipe(Option.map(values => Arr.reduce(values, 0, (sum, value) => sum + value)))
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
export const addAgentUsage = (left: AgentUsage, right: AgentUsage) =>
|
|
36
|
+
AgentUsage.make({
|
|
37
|
+
input: AgentInputUsage.make({
|
|
38
|
+
total: left.input.total + right.input.total,
|
|
39
|
+
uncached: sumOptional(left.input.uncached, right.input.uncached),
|
|
40
|
+
cacheRead: sumOptional(left.input.cacheRead, right.input.cacheRead),
|
|
41
|
+
cacheWrite: sumOptional(left.input.cacheWrite, right.input.cacheWrite)
|
|
42
|
+
}),
|
|
43
|
+
output: AgentOutputUsage.make({
|
|
44
|
+
total: left.output.total + right.output.total,
|
|
45
|
+
text: sumOptional(left.output.text, right.output.text),
|
|
46
|
+
reasoning: sumOptional(left.output.reasoning, right.output.reasoning)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @yolk-sdk/agent/runtime
|
|
2
|
+
|
|
3
|
+
Generic session orchestration for `@yolk-sdk/agent/loop`.
|
|
4
|
+
|
|
5
|
+
## What it provides
|
|
6
|
+
|
|
7
|
+
- `runRuntime` for stateless transcript runs or append-backed durable runs.
|
|
8
|
+
- `SessionEventStore` service contract for append-only runtime session events.
|
|
9
|
+
- In-memory session event store layer for tests/simple hosts.
|
|
10
|
+
- Runtime-specific errors.
|
|
11
|
+
- Pending HITL state and response replay for durable sessions.
|
|
12
|
+
|
|
13
|
+
## Request modes
|
|
14
|
+
|
|
15
|
+
### `Transcript`
|
|
16
|
+
|
|
17
|
+
Use `Transcript` when the caller owns replay state. The caller passes a complete protocol transcript and runtime does not load or persist session state.
|
|
18
|
+
|
|
19
|
+
### `AppendInput`
|
|
20
|
+
|
|
21
|
+
Use `AppendInput` when the host wants durable runtime persistence. Runtime:
|
|
22
|
+
|
|
23
|
+
1. loads the prior `SessionEventStore` log,
|
|
24
|
+
2. replays protocol `AgentMessage` values from `InputAppended` and `RunCompleted`,
|
|
25
|
+
3. appends `InputAppended` and `RunStarted`,
|
|
26
|
+
4. runs the loop,
|
|
27
|
+
5. appends `RunCompleted`, `RunAwaitingInput`, or `RunFailed`.
|
|
28
|
+
|
|
29
|
+
### `AppendHitlResponse`
|
|
30
|
+
|
|
31
|
+
Use `AppendHitlResponse` to persist one approval/question response and resume a paused append-backed run.
|
|
32
|
+
|
|
33
|
+
Hosts own physical storage, auth/tenancy, reconnect/fanout, and cleanup policy. Use numeric `expectedRevision` to reject stale writes. Use `latestIncompleteRuntimeRun` to decide when a host should append `RunInterrupted`.
|
|
34
|
+
|
|
35
|
+
## Use it when
|
|
36
|
+
|
|
37
|
+
- You need reusable lifecycle around the stateless loop.
|
|
38
|
+
- Your app owns storage and wants to inject it through an Effect service.
|
|
39
|
+
|
|
40
|
+
## Boundaries
|
|
41
|
+
|
|
42
|
+
- No database implementation.
|
|
43
|
+
- No HTTP/WebSocket routes.
|
|
44
|
+
- No app auth or tenancy logic.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
import { agentLoopErrorToAgentError, type AgentLoopError } from '@yolk-sdk/agent/loop'
|
|
3
|
+
import { AgentError } from '@yolk-sdk/agent/protocol'
|
|
4
|
+
|
|
5
|
+
export class SessionNotFoundError extends Schema.TaggedErrorClass<SessionNotFoundError>()(
|
|
6
|
+
'SessionNotFoundError',
|
|
7
|
+
{
|
|
8
|
+
sessionId: Schema.String
|
|
9
|
+
}
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
export class SessionLoadError extends Schema.TaggedErrorClass<SessionLoadError>()(
|
|
13
|
+
'SessionLoadError',
|
|
14
|
+
{
|
|
15
|
+
sessionId: Schema.String,
|
|
16
|
+
message: Schema.String
|
|
17
|
+
}
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
export class SessionSaveError extends Schema.TaggedErrorClass<SessionSaveError>()(
|
|
21
|
+
'SessionSaveError',
|
|
22
|
+
{
|
|
23
|
+
sessionId: Schema.String,
|
|
24
|
+
message: Schema.String
|
|
25
|
+
}
|
|
26
|
+
) {}
|
|
27
|
+
|
|
28
|
+
export class SessionConflictError extends Schema.TaggedErrorClass<SessionConflictError>()(
|
|
29
|
+
'SessionConflictError',
|
|
30
|
+
{
|
|
31
|
+
sessionId: Schema.String,
|
|
32
|
+
message: Schema.String
|
|
33
|
+
}
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
export type RuntimeError =
|
|
37
|
+
| SessionNotFoundError
|
|
38
|
+
| SessionLoadError
|
|
39
|
+
| SessionSaveError
|
|
40
|
+
| SessionConflictError
|
|
41
|
+
|
|
42
|
+
export const runtimeErrorToAgentError = (error: RuntimeError | AgentLoopError): AgentError => {
|
|
43
|
+
switch (error._tag) {
|
|
44
|
+
case 'SessionNotFoundError':
|
|
45
|
+
return AgentError.make({
|
|
46
|
+
code: 'session_not_found',
|
|
47
|
+
message: `Session not found: ${error.sessionId}`,
|
|
48
|
+
retryable: false
|
|
49
|
+
})
|
|
50
|
+
case 'SessionLoadError':
|
|
51
|
+
case 'SessionSaveError':
|
|
52
|
+
return AgentError.make({
|
|
53
|
+
code: 'store_error',
|
|
54
|
+
message: error.message,
|
|
55
|
+
retryable: true
|
|
56
|
+
})
|
|
57
|
+
case 'SessionConflictError':
|
|
58
|
+
return AgentError.make({
|
|
59
|
+
code: 'conflict',
|
|
60
|
+
message: error.message,
|
|
61
|
+
retryable: false
|
|
62
|
+
})
|
|
63
|
+
case 'LLMError':
|
|
64
|
+
case 'ToolError':
|
|
65
|
+
case 'ContextTransformError':
|
|
66
|
+
case 'AbortError':
|
|
67
|
+
case 'FauxExhaustedError':
|
|
68
|
+
return agentLoopErrorToAgentError(error)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export {
|
|
2
|
+
runtimeErrorToAgentError,
|
|
3
|
+
SessionConflictError,
|
|
4
|
+
SessionLoadError,
|
|
5
|
+
SessionNotFoundError,
|
|
6
|
+
SessionSaveError
|
|
7
|
+
} from './error.ts'
|
|
8
|
+
export type { RuntimeError } from './error.ts'
|
|
9
|
+
export { runRuntime } from './run-runtime.ts'
|
|
10
|
+
export type {
|
|
11
|
+
AppendInputRuntimeRequest,
|
|
12
|
+
AppendHitlResponseRuntimeRequest,
|
|
13
|
+
RuntimeConfig,
|
|
14
|
+
RuntimeRequest,
|
|
15
|
+
RuntimeTranscript,
|
|
16
|
+
TranscriptRuntimeRequest
|
|
17
|
+
} from './run-runtime.ts'
|
|
18
|
+
export {
|
|
19
|
+
appendRuntimeSessionEventsToLog,
|
|
20
|
+
HitlResponseAppended,
|
|
21
|
+
InputAppended,
|
|
22
|
+
makeInMemorySessionEventStoreLayer,
|
|
23
|
+
latestIncompleteRuntimeRun,
|
|
24
|
+
replayRuntimeHitlResponses,
|
|
25
|
+
replayRuntimeSessionEvents,
|
|
26
|
+
RunAwaitingInput,
|
|
27
|
+
RunCompleted,
|
|
28
|
+
RunFailed,
|
|
29
|
+
RunInterrupted,
|
|
30
|
+
RunStarted,
|
|
31
|
+
RuntimeSessionEvent,
|
|
32
|
+
SessionEventStore
|
|
33
|
+
} from './session-event-store.ts'
|
|
34
|
+
export type {
|
|
35
|
+
AppendRuntimeSessionEventsInput,
|
|
36
|
+
IncompleteRuntimeRun,
|
|
37
|
+
RuntimeSessionEventLog,
|
|
38
|
+
SessionEventStoreApi,
|
|
39
|
+
SessionRevision,
|
|
40
|
+
StoredRuntimeSessionEvent
|
|
41
|
+
} from './session-event-store.ts'
|
|
42
|
+
|
|
43
|
+
export type RuntimeSessionId = string
|