clanka 0.0.28 → 0.1.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/dist/Agent.d.ts +87 -40
- package/dist/Agent.d.ts.map +1 -1
- package/dist/Agent.js +154 -94
- package/dist/Agent.js.map +1 -1
- package/dist/AgentExecutor.d.ts +165 -0
- package/dist/AgentExecutor.d.ts.map +1 -0
- package/dist/AgentExecutor.js +121 -0
- package/dist/AgentExecutor.js.map +1 -0
- package/dist/AgentTools.d.ts +14 -132
- package/dist/AgentTools.d.ts.map +1 -1
- package/dist/AgentTools.js +10 -12
- package/dist/AgentTools.js.map +1 -1
- package/dist/OutputFormatter.d.ts.map +1 -1
- package/dist/OutputFormatter.js +18 -0
- package/dist/OutputFormatter.js.map +1 -1
- package/dist/WebToMarkdown.d.ts.map +1 -1
- package/dist/WebToMarkdown.js +1 -1
- package/dist/WebToMarkdown.js.map +1 -1
- package/dist/WebToMarkdown.test.d.ts +2 -0
- package/dist/WebToMarkdown.test.d.ts.map +1 -0
- package/dist/WebToMarkdown.test.js +37 -0
- package/dist/WebToMarkdown.test.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/Agent.ts +290 -215
- package/src/AgentExecutor.ts +245 -0
- package/src/AgentTools.ts +25 -22
- package/src/OutputFormatter.ts +18 -0
- package/src/WebToMarkdown.test.ts +65 -0
- package/src/WebToMarkdown.ts +1 -0
- package/src/index.ts +4 -4
- package/dist/Agent.test.d.ts +0 -2
- package/dist/Agent.test.d.ts.map +0 -1
- package/dist/Agent.test.js +0 -111
- package/dist/Agent.test.js.map +0 -1
- package/dist/AgentTools.test.d.ts +0 -2
- package/dist/AgentTools.test.d.ts.map +0 -1
- package/dist/AgentTools.test.js +0 -714
- package/dist/AgentTools.test.js.map +0 -1
- package/dist/DuckDuckGo.d.ts +0 -28
- package/dist/DuckDuckGo.d.ts.map +0 -1
- package/dist/DuckDuckGo.js +0 -131
- package/dist/DuckDuckGo.js.map +0 -1
- package/dist/Executor.d.ts +0 -20
- package/dist/Executor.d.ts.map +0 -1
- package/dist/Executor.js +0 -98
- package/dist/Executor.js.map +0 -1
- package/dist/GithubCopilot.d.ts +0 -11
- package/dist/GithubCopilot.d.ts.map +0 -1
- package/dist/GithubCopilot.js +0 -14
- package/dist/GithubCopilot.js.map +0 -1
- package/dist/GithubCopilotAuth.d.ts +0 -57
- package/dist/GithubCopilotAuth.d.ts.map +0 -1
- package/dist/GithubCopilotAuth.js +0 -218
- package/dist/GithubCopilotAuth.js.map +0 -1
- package/dist/GithubCopilotAuth.test.d.ts +0 -2
- package/dist/GithubCopilotAuth.test.d.ts.map +0 -1
- package/dist/GithubCopilotAuth.test.js +0 -267
- package/dist/GithubCopilotAuth.test.js.map +0 -1
- package/dist/MockSearch.d.ts +0 -12
- package/dist/MockSearch.d.ts.map +0 -1
- package/dist/MockSearch.js +0 -4
- package/dist/MockSearch.js.map +0 -1
- package/dist/ai.d.ts +0 -2
- package/dist/ai.d.ts.map +0 -1
- package/dist/ai.js +0 -29
- package/dist/ai.js.map +0 -1
- package/dist/examples/cli.mjs +0 -68514
- package/src/Agent.test.ts +0 -159
- package/src/Executor.ts +0 -151
package/src/Agent.ts
CHANGED
|
@@ -3,17 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import {
|
|
5
5
|
Array,
|
|
6
|
-
Deferred,
|
|
7
6
|
Effect,
|
|
8
|
-
FileSystem,
|
|
9
7
|
identity,
|
|
10
8
|
Layer,
|
|
9
|
+
MutableRef,
|
|
11
10
|
Option,
|
|
12
|
-
Path,
|
|
13
11
|
pipe,
|
|
14
12
|
Queue,
|
|
15
13
|
Schema,
|
|
16
14
|
Scope,
|
|
15
|
+
Semaphore,
|
|
17
16
|
ServiceMap,
|
|
18
17
|
Stream,
|
|
19
18
|
} from "effect"
|
|
@@ -24,26 +23,62 @@ import {
|
|
|
24
23
|
Tool,
|
|
25
24
|
Toolkit,
|
|
26
25
|
} from "effect/unstable/ai"
|
|
27
|
-
import {
|
|
28
|
-
AgentToolHandlers,
|
|
29
|
-
AgentTools,
|
|
30
|
-
CurrentDirectory,
|
|
31
|
-
SubagentContext,
|
|
32
|
-
TaskCompleteDeferred,
|
|
33
|
-
} from "./AgentTools.ts"
|
|
34
|
-
import { Executor } from "./Executor.ts"
|
|
35
|
-
import { ToolkitRenderer } from "./ToolkitRenderer.ts"
|
|
36
26
|
import { ModelName, ProviderName } from "effect/unstable/ai/Model"
|
|
37
27
|
import { type StreamPart } from "effect/unstable/ai/Response"
|
|
38
|
-
import
|
|
39
|
-
import type {
|
|
28
|
+
import * as AgentExecutor from "./AgentExecutor.ts"
|
|
29
|
+
import type { Path } from "effect/Path"
|
|
30
|
+
import type { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
|
|
31
|
+
import type { HttpClient } from "effect/unstable/http/HttpClient"
|
|
32
|
+
import type {
|
|
33
|
+
CurrentDirectory,
|
|
34
|
+
SubagentExecutor,
|
|
35
|
+
TaskCompleter,
|
|
36
|
+
} from "./AgentTools.ts"
|
|
37
|
+
import type { FileSystem } from "effect/FileSystem"
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @since 1.0.0
|
|
41
|
+
* @category Models
|
|
42
|
+
*/
|
|
43
|
+
export type TypeId = "~clanka/Agent"
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @since 1.0.0
|
|
47
|
+
* @category Models
|
|
48
|
+
*/
|
|
49
|
+
export const TypeId: TypeId = "~clanka/Agent"
|
|
40
50
|
|
|
41
51
|
/**
|
|
42
52
|
* @since 1.0.0
|
|
43
53
|
* @category Models
|
|
44
54
|
*/
|
|
45
55
|
export interface Agent {
|
|
46
|
-
readonly
|
|
56
|
+
readonly [TypeId]: TypeId
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Send a prompt to the agent and receive a stream of output.
|
|
60
|
+
*/
|
|
61
|
+
send(options: {
|
|
62
|
+
/**
|
|
63
|
+
* The prompt to send to the agent.
|
|
64
|
+
*/
|
|
65
|
+
readonly prompt: Prompt.RawInput
|
|
66
|
+
/**
|
|
67
|
+
* Provide additional system instructions, or a function that generates
|
|
68
|
+
* system instructions based on the tool instructions
|
|
69
|
+
*/
|
|
70
|
+
readonly system?:
|
|
71
|
+
| string
|
|
72
|
+
| ((options: {
|
|
73
|
+
readonly toolInstructions: string
|
|
74
|
+
readonly agentsMd: string
|
|
75
|
+
}) => string)
|
|
76
|
+
| undefined
|
|
77
|
+
}): Effect.Effect<
|
|
78
|
+
Stream.Stream<Output, AgentFinished | AiError.AiError>,
|
|
79
|
+
never,
|
|
80
|
+
Scope.Scope | LanguageModel.LanguageModel | ProviderName | ModelName
|
|
81
|
+
>
|
|
47
82
|
|
|
48
83
|
/**
|
|
49
84
|
* Send a message to the agent to steer its behavior. This is useful for
|
|
@@ -57,89 +92,26 @@ export interface Agent {
|
|
|
57
92
|
}
|
|
58
93
|
|
|
59
94
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
95
|
+
* @since 1.0.0
|
|
96
|
+
* @category Service
|
|
97
|
+
*/
|
|
98
|
+
export const Agent = ServiceMap.Service<Agent>("clanka/Agent")
|
|
99
|
+
|
|
100
|
+
/**
|
|
62
101
|
* @since 1.0.0
|
|
63
102
|
* @category Constructors
|
|
64
103
|
*/
|
|
65
|
-
export const make: <
|
|
66
|
-
// oxlint-disable-next-line typescript/no-explicit-any
|
|
67
|
-
Toolkit extends Toolkit.Any = never,
|
|
68
|
-
SE = never,
|
|
69
|
-
SR = never,
|
|
70
|
-
>(options: {
|
|
71
|
-
/** The working directory to run the agent in */
|
|
72
|
-
readonly directory: string
|
|
73
|
-
/** The prompt to use for the agent */
|
|
74
|
-
readonly prompt: Prompt.RawInput
|
|
75
|
-
/**
|
|
76
|
-
* Provide additional system instructions, or a function that generates
|
|
77
|
-
* system instructions based on the tool instructions
|
|
78
|
-
*/
|
|
79
|
-
readonly system?:
|
|
80
|
-
| string
|
|
81
|
-
| ((options: {
|
|
82
|
-
readonly toolInstructions: string
|
|
83
|
-
readonly agentsMd: string
|
|
84
|
-
}) => string)
|
|
85
|
-
| undefined
|
|
86
|
-
/** Additional tools to provide to the agent */
|
|
87
|
-
readonly tools?: Toolkit | undefined
|
|
88
|
-
/** Layer to use for subagents */
|
|
89
|
-
readonly subagentModel?:
|
|
90
|
-
| Layer.Layer<
|
|
91
|
-
LanguageModel.LanguageModel | ProviderName | ModelName,
|
|
92
|
-
SE,
|
|
93
|
-
SR
|
|
94
|
-
>
|
|
95
|
-
| undefined
|
|
96
|
-
}) => Effect.Effect<
|
|
104
|
+
export const make = Effect.gen(function* (): Effect.fn.Return<
|
|
97
105
|
Agent,
|
|
98
106
|
never,
|
|
99
|
-
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
| LanguageModel.LanguageModel
|
|
104
|
-
| ProviderName
|
|
105
|
-
| ModelName
|
|
106
|
-
| ToolkitRenderer
|
|
107
|
-
| (Toolkit extends Toolkit.Toolkit<infer T>
|
|
108
|
-
? Tool.HandlersFor<T> | Tool.HandlerServices<T[keyof T]>
|
|
109
|
-
: never)
|
|
110
|
-
| Tool.HandlersFor<typeof AgentTools.tools>
|
|
111
|
-
| SR
|
|
112
|
-
> = Effect.fnUntraced(function* (options: {
|
|
113
|
-
readonly directory: string
|
|
114
|
-
readonly prompt: Prompt.RawInput
|
|
115
|
-
readonly system?:
|
|
116
|
-
| string
|
|
117
|
-
| ((options: { readonly toolInstructions: string }) => string)
|
|
118
|
-
| undefined
|
|
119
|
-
readonly tools?: Toolkit.Toolkit<{}> | undefined
|
|
120
|
-
readonly subagentModel?:
|
|
121
|
-
| Layer.Layer<LanguageModel.LanguageModel | ProviderName | ModelName>
|
|
122
|
-
| undefined
|
|
123
|
-
}) {
|
|
124
|
-
const fs = yield* FileSystem.FileSystem
|
|
125
|
-
const pathService = yield* Path.Path
|
|
126
|
-
const executor = yield* Executor
|
|
127
|
-
const renderer = yield* ToolkitRenderer
|
|
128
|
-
const generateSystem =
|
|
129
|
-
typeof options.system === "function" ? options.system : defaultSystem
|
|
130
|
-
|
|
131
|
-
const allTools = Toolkit.merge(AgentTools, options.tools ?? Toolkit.empty)
|
|
132
|
-
const allToolsDts = renderer.render(allTools)
|
|
133
|
-
const tools = yield* allTools
|
|
107
|
+
Scope.Scope | AgentExecutor.AgentExecutor
|
|
108
|
+
> {
|
|
109
|
+
const executor = yield* AgentExecutor.AgentExecutor
|
|
110
|
+
|
|
134
111
|
const singleTool = yield* SingleTools.asEffect().pipe(
|
|
135
112
|
Effect.provide(SingleToolHandlers),
|
|
136
113
|
)
|
|
137
|
-
const
|
|
138
|
-
| Tool.HandlerServices<{}>
|
|
139
|
-
| LanguageModel.LanguageModel
|
|
140
|
-
| ProviderName
|
|
141
|
-
| ModelName
|
|
142
|
-
>()
|
|
114
|
+
const toolsDts = yield* executor.toolsDts
|
|
143
115
|
|
|
144
116
|
const pendingMessages = new Set<{
|
|
145
117
|
readonly message: string
|
|
@@ -147,9 +119,10 @@ export const make: <
|
|
|
147
119
|
}>()
|
|
148
120
|
|
|
149
121
|
const agentsMd = yield* pipe(
|
|
150
|
-
|
|
122
|
+
executor.agentsMd,
|
|
151
123
|
Effect.map(
|
|
152
|
-
(
|
|
124
|
+
Option.map(
|
|
125
|
+
(content) => `# AGENTS.md
|
|
153
126
|
|
|
154
127
|
The following instructions are from ./AGENTS.md in the current directory.
|
|
155
128
|
You do not need to read this file again.
|
|
@@ -159,8 +132,8 @@ You do not need to read this file again.
|
|
|
159
132
|
<!-- AGENTS.md start -->
|
|
160
133
|
${content}
|
|
161
134
|
<!-- AGENTS.md end -->`,
|
|
135
|
+
),
|
|
162
136
|
),
|
|
163
|
-
Effect.option,
|
|
164
137
|
)
|
|
165
138
|
|
|
166
139
|
let agentCounter = 0
|
|
@@ -168,27 +141,49 @@ ${content}
|
|
|
168
141
|
const outputBuffer = new Map<number, Array<Output>>()
|
|
169
142
|
let currentOutputAgent: number | null = null
|
|
170
143
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
144
|
+
let history = MutableRef.make(Prompt.empty)
|
|
145
|
+
|
|
146
|
+
const spawn: (opts: {
|
|
147
|
+
readonly agentId: number
|
|
148
|
+
readonly prompt: Prompt.Prompt
|
|
149
|
+
readonly system?:
|
|
150
|
+
| string
|
|
151
|
+
| ((options: {
|
|
152
|
+
readonly toolInstructions: string
|
|
153
|
+
readonly agentsMd: string
|
|
154
|
+
}) => string)
|
|
155
|
+
| undefined
|
|
156
|
+
readonly disableHistory?: boolean | undefined
|
|
157
|
+
}) => Stream.Stream<
|
|
175
158
|
Output,
|
|
176
159
|
AgentFinished | AiError.AiError,
|
|
177
|
-
LanguageModel.LanguageModel | ProviderName
|
|
178
|
-
> = Effect.fnUntraced(function* (
|
|
160
|
+
LanguageModel.LanguageModel | ProviderName | ModelName
|
|
161
|
+
> = Effect.fnUntraced(function* (opts) {
|
|
162
|
+
const agentId = opts.agentId
|
|
179
163
|
const ai = yield* LanguageModel.LanguageModel
|
|
164
|
+
const subagentModel = yield* Effect.serviceOption(SubagentModel)
|
|
180
165
|
const modelConfig = yield* AgentModelConfig
|
|
166
|
+
const services = yield* Effect.services<
|
|
167
|
+
LanguageModel.LanguageModel | ProviderName | ModelName
|
|
168
|
+
>()
|
|
169
|
+
let finalSummary = Option.none<string>()
|
|
170
|
+
|
|
181
171
|
const singleToolMode = modelConfig.supportsNoTools !== true
|
|
182
|
-
const deferred = yield* Deferred.make<string>()
|
|
183
172
|
const output = yield* Queue.make<Output, AgentFinished | AiError.AiError>()
|
|
173
|
+
const prompt = opts.disableHistory ? MutableRef.make(Prompt.empty) : history
|
|
174
|
+
|
|
175
|
+
MutableRef.update(prompt, Prompt.concat(opts.prompt))
|
|
176
|
+
|
|
177
|
+
const generateSystem =
|
|
178
|
+
typeof opts.system === "function" ? opts.system : defaultSystem
|
|
184
179
|
|
|
185
|
-
const toolInstructions = generateSystemTools(
|
|
180
|
+
const toolInstructions = generateSystemTools(toolsDts, !singleToolMode)
|
|
186
181
|
let system = generateSystem({
|
|
187
182
|
toolInstructions,
|
|
188
183
|
agentsMd: Option.getOrElse(agentsMd, () => ""),
|
|
189
184
|
})
|
|
190
|
-
if (typeof
|
|
191
|
-
system += `\n${
|
|
185
|
+
if (typeof opts.system === "string") {
|
|
186
|
+
system += `\n${opts.system}\n`
|
|
192
187
|
}
|
|
193
188
|
|
|
194
189
|
function maybeSend(options: {
|
|
@@ -197,10 +192,10 @@ ${content}
|
|
|
197
192
|
readonly acquire?: boolean
|
|
198
193
|
readonly release?: boolean
|
|
199
194
|
}) {
|
|
200
|
-
if (currentOutputAgent === null || currentOutputAgent === agentId) {
|
|
195
|
+
if (currentOutputAgent === null || currentOutputAgent === opts.agentId) {
|
|
201
196
|
Queue.offerUnsafe(output, options.part)
|
|
202
197
|
if (options.acquire) {
|
|
203
|
-
currentOutputAgent = agentId
|
|
198
|
+
currentOutputAgent = opts.agentId
|
|
204
199
|
}
|
|
205
200
|
if (options.release) {
|
|
206
201
|
currentOutputAgent = null
|
|
@@ -219,83 +214,88 @@ ${content}
|
|
|
219
214
|
}
|
|
220
215
|
return
|
|
221
216
|
}
|
|
222
|
-
let state = outputBuffer.get(agentId)
|
|
217
|
+
let state = outputBuffer.get(opts.agentId)
|
|
223
218
|
if (!state) {
|
|
224
219
|
state = []
|
|
225
|
-
outputBuffer.set(agentId, state)
|
|
220
|
+
outputBuffer.set(opts.agentId, state)
|
|
226
221
|
}
|
|
227
222
|
state.push(options.part)
|
|
228
223
|
return
|
|
229
224
|
}
|
|
230
225
|
|
|
231
|
-
const
|
|
232
|
-
|
|
226
|
+
const spawnSubagent = Effect.fnUntraced(
|
|
227
|
+
function* (prompt: string) {
|
|
233
228
|
let id = agentCounter++
|
|
234
|
-
const stream = spawn(
|
|
235
|
-
id,
|
|
236
|
-
|
|
229
|
+
const stream = spawn({
|
|
230
|
+
agentId: id,
|
|
231
|
+
prompt:
|
|
232
|
+
Prompt.make(`You have been asked using the "delegate" function to complete the following task. Try to avoid using the "delegate" function yourself unless strictly necessary:
|
|
237
233
|
|
|
238
234
|
${prompt}`),
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
235
|
+
system: opts.system,
|
|
236
|
+
disableHistory: true,
|
|
237
|
+
})
|
|
238
|
+
const provider = yield* ProviderName
|
|
239
|
+
const model = yield* ModelName
|
|
240
|
+
maybeSend({
|
|
241
|
+
agentId: opts.agentId,
|
|
242
|
+
part: new SubagentStart({ id, prompt, model, provider }),
|
|
243
|
+
release: true,
|
|
244
|
+
})
|
|
245
|
+
return yield* stream.pipe(
|
|
246
|
+
Stream.runForEachArray((parts) => {
|
|
247
|
+
for (const part of parts) {
|
|
248
|
+
switch (part._tag) {
|
|
249
|
+
case "AgentStart":
|
|
250
|
+
break
|
|
251
|
+
case "SubagentStart":
|
|
252
|
+
case "SubagentComplete":
|
|
253
|
+
case "SubagentPart":
|
|
254
|
+
Queue.offerUnsafe(output, part)
|
|
255
|
+
break
|
|
257
256
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
257
|
+
default:
|
|
258
|
+
Queue.offerUnsafe(output, new SubagentPart({ id, part }))
|
|
259
|
+
break
|
|
262
260
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}).pipe(
|
|
276
|
-
options.subagentModel
|
|
277
|
-
? Effect.provide(Layer.orDie(options.subagentModel))
|
|
278
|
-
: Effect.provideServices(services),
|
|
261
|
+
}
|
|
262
|
+
return Effect.void
|
|
263
|
+
}),
|
|
264
|
+
Effect.as(""),
|
|
265
|
+
Effect.catchTag("AgentFinished", (finished) => {
|
|
266
|
+
Queue.offerUnsafe(
|
|
267
|
+
output,
|
|
268
|
+
new SubagentComplete({ id, summary: finished.summary }),
|
|
269
|
+
)
|
|
270
|
+
return Effect.succeed(finished.summary)
|
|
271
|
+
}),
|
|
272
|
+
Effect.orDie,
|
|
279
273
|
)
|
|
280
274
|
},
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
275
|
+
Option.isSome(subagentModel)
|
|
276
|
+
? Effect.provideServices(subagentModel.value)
|
|
277
|
+
: Effect.provideServices(services),
|
|
284
278
|
)
|
|
285
279
|
|
|
286
280
|
const executeScript = Effect.fnUntraced(function* (script: string) {
|
|
287
281
|
maybeSend({ agentId, part: new ScriptEnd(), release: true })
|
|
288
282
|
const output = yield* pipe(
|
|
289
|
-
executor.execute({
|
|
283
|
+
executor.execute({
|
|
284
|
+
script,
|
|
285
|
+
onSubagent: spawnSubagent,
|
|
286
|
+
onTaskComplete: (summary) =>
|
|
287
|
+
Effect.sync(() => {
|
|
288
|
+
finalSummary = Option.some(summary)
|
|
289
|
+
}),
|
|
290
|
+
}),
|
|
290
291
|
Stream.mkString,
|
|
291
|
-
Effect.provideServices(taskServices),
|
|
292
292
|
)
|
|
293
293
|
maybeSend({ agentId, part: new ScriptOutput({ output }) })
|
|
294
294
|
return output
|
|
295
295
|
})
|
|
296
296
|
|
|
297
297
|
if (!modelConfig.systemPromptTransform) {
|
|
298
|
-
prompt
|
|
298
|
+
MutableRef.update(prompt, Prompt.setSystem(system))
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
let currentScript = ""
|
|
@@ -303,33 +303,40 @@ ${prompt}`),
|
|
|
303
303
|
while (true) {
|
|
304
304
|
if (!singleToolMode && currentScript.length > 0) {
|
|
305
305
|
const result = yield* executeScript(currentScript)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
306
|
+
MutableRef.update(
|
|
307
|
+
prompt,
|
|
308
|
+
Prompt.concat([
|
|
309
|
+
{
|
|
310
|
+
role: modelConfig.supportsAssistantPrefill
|
|
311
|
+
? "assistant"
|
|
312
|
+
: "user",
|
|
313
|
+
content: `Javascript output:\n\n${result}`,
|
|
314
|
+
},
|
|
315
|
+
]),
|
|
316
|
+
)
|
|
312
317
|
currentScript = ""
|
|
313
318
|
}
|
|
314
319
|
|
|
315
|
-
if (
|
|
320
|
+
if (Option.isSome(finalSummary)) {
|
|
316
321
|
yield* Queue.fail(
|
|
317
322
|
output,
|
|
318
|
-
new AgentFinished({ summary:
|
|
323
|
+
new AgentFinished({ summary: finalSummary.value }),
|
|
319
324
|
)
|
|
320
325
|
return
|
|
321
326
|
}
|
|
322
327
|
|
|
323
328
|
if (pendingMessages.size > 0) {
|
|
324
|
-
|
|
329
|
+
MutableRef.update(
|
|
325
330
|
prompt,
|
|
326
|
-
|
|
327
|
-
resume
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
Prompt.concat(
|
|
332
|
+
Array.Array.from(pendingMessages, ({ message, resume }) => {
|
|
333
|
+
resume(Effect.void)
|
|
334
|
+
return {
|
|
335
|
+
role: "user",
|
|
336
|
+
content: message,
|
|
337
|
+
}
|
|
338
|
+
}),
|
|
339
|
+
),
|
|
333
340
|
)
|
|
334
341
|
pendingMessages.clear()
|
|
335
342
|
}
|
|
@@ -340,7 +347,9 @@ ${prompt}`),
|
|
|
340
347
|
let hadReasoningDelta = false
|
|
341
348
|
yield* pipe(
|
|
342
349
|
ai.streamText(
|
|
343
|
-
singleToolMode
|
|
350
|
+
singleToolMode
|
|
351
|
+
? { prompt: prompt.current, toolkit: singleTool }
|
|
352
|
+
: { prompt: prompt.current },
|
|
344
353
|
),
|
|
345
354
|
Stream.takeUntil((part) => {
|
|
346
355
|
if (
|
|
@@ -461,35 +470,45 @@ ${prompt}`),
|
|
|
461
470
|
? (effect) => modelConfig.systemPromptTransform!(system, effect)
|
|
462
471
|
: identity,
|
|
463
472
|
)
|
|
464
|
-
|
|
473
|
+
MutableRef.update(
|
|
474
|
+
prompt,
|
|
475
|
+
Prompt.concat(Prompt.fromResponseParts(response)),
|
|
476
|
+
)
|
|
465
477
|
currentScript = currentScript.trim()
|
|
466
478
|
}
|
|
467
479
|
}).pipe(
|
|
468
|
-
Effect.
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
return executeScript(script)
|
|
474
|
-
}),
|
|
475
|
-
),
|
|
476
|
-
),
|
|
477
|
-
Effect.provideServices(services),
|
|
480
|
+
Effect.provideService(ScriptExecutor, (script) => {
|
|
481
|
+
maybeSend({ agentId, part: new ScriptStart() })
|
|
482
|
+
maybeSend({ agentId, part: new ScriptDelta({ delta: script }) })
|
|
483
|
+
return executeScript(script)
|
|
484
|
+
}),
|
|
478
485
|
Effect.catchCause((cause) => Queue.failCause(output, cause)),
|
|
479
486
|
Effect.forkScoped,
|
|
480
487
|
)
|
|
481
488
|
|
|
489
|
+
yield* Queue.offer(
|
|
490
|
+
output,
|
|
491
|
+
new AgentStart({
|
|
492
|
+
id: opts.agentId,
|
|
493
|
+
prompt: opts.prompt,
|
|
494
|
+
provider: yield* ProviderName,
|
|
495
|
+
model: yield* ModelName,
|
|
496
|
+
}),
|
|
497
|
+
)
|
|
498
|
+
|
|
482
499
|
return Stream.fromQueue(output)
|
|
483
500
|
}, Stream.unwrap)
|
|
484
501
|
|
|
485
|
-
const
|
|
486
|
-
Stream.broadcast({
|
|
487
|
-
capacity: "unbounded",
|
|
488
|
-
}),
|
|
489
|
-
)
|
|
502
|
+
const sendLock = Semaphore.makeUnsafe(1)
|
|
490
503
|
|
|
491
|
-
return
|
|
492
|
-
|
|
504
|
+
return Agent.of({
|
|
505
|
+
[TypeId]: TypeId,
|
|
506
|
+
send: (options) =>
|
|
507
|
+
spawn({
|
|
508
|
+
agentId: agentCounter++,
|
|
509
|
+
prompt: Prompt.make(options.prompt),
|
|
510
|
+
system: options.system,
|
|
511
|
+
}).pipe(Stream.broadcast({ capacity: "unbounded" }), sendLock.withPermit),
|
|
493
512
|
steer: (message) =>
|
|
494
513
|
Effect.callback((resume) => {
|
|
495
514
|
const entry = { message, resume }
|
|
@@ -497,8 +516,7 @@ ${prompt}`),
|
|
|
497
516
|
return Effect.sync(() => pendingMessages.delete(entry))
|
|
498
517
|
}),
|
|
499
518
|
})
|
|
500
|
-
|
|
501
|
-
}) as any
|
|
519
|
+
})
|
|
502
520
|
|
|
503
521
|
const defaultSystem = (options: {
|
|
504
522
|
readonly toolInstructions: string
|
|
@@ -561,6 +579,7 @@ You have the following functions available to you:
|
|
|
561
579
|
\`\`\`ts
|
|
562
580
|
${toolsDts}
|
|
563
581
|
|
|
582
|
+
/** The global Fetch API available for making HTTP requests. */
|
|
564
583
|
declare const fetch: typeof globalThis.fetch
|
|
565
584
|
\`\`\``
|
|
566
585
|
}
|
|
@@ -578,6 +597,7 @@ You have the following functions available to you:
|
|
|
578
597
|
\`\`\`ts
|
|
579
598
|
${toolsDts}
|
|
580
599
|
|
|
600
|
+
// The global Fetch API available for making HTTP requests.
|
|
581
601
|
declare const fetch: typeof globalThis.fetch
|
|
582
602
|
\`\`\``
|
|
583
603
|
}
|
|
@@ -604,6 +624,59 @@ const SingleToolHandlers = SingleTools.toLayer({
|
|
|
604
624
|
}),
|
|
605
625
|
})
|
|
606
626
|
|
|
627
|
+
/**
|
|
628
|
+
* @since 1.0.0
|
|
629
|
+
* @category Layers
|
|
630
|
+
*/
|
|
631
|
+
export const layer: Layer.Layer<Agent, never, AgentExecutor.AgentExecutor> =
|
|
632
|
+
Layer.effect(Agent, make)
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Create an Agent layer that uses a local AgentExecutor.
|
|
636
|
+
*
|
|
637
|
+
* @since 1.0.0
|
|
638
|
+
* @category Layers
|
|
639
|
+
*/
|
|
640
|
+
export const layerLocal = <Toolkit extends Toolkit.Any = never>(options: {
|
|
641
|
+
readonly directory: string
|
|
642
|
+
readonly tools?: Toolkit | undefined
|
|
643
|
+
}): Layer.Layer<
|
|
644
|
+
Agent,
|
|
645
|
+
never,
|
|
646
|
+
| FileSystem
|
|
647
|
+
| Path
|
|
648
|
+
| ChildProcessSpawner
|
|
649
|
+
| HttpClient
|
|
650
|
+
| Exclude<
|
|
651
|
+
Toolkit extends Toolkit.Toolkit<infer T>
|
|
652
|
+
? Tool.HandlersFor<T> | Tool.HandlerServices<T[keyof T]>
|
|
653
|
+
: never,
|
|
654
|
+
CurrentDirectory | SubagentExecutor | TaskCompleter
|
|
655
|
+
>
|
|
656
|
+
> => layer.pipe(Layer.provide(AgentExecutor.layerLocal(options)))
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* @since 1.0.0
|
|
660
|
+
* @category Subagent model
|
|
661
|
+
*/
|
|
662
|
+
export class SubagentModel extends ServiceMap.Service<
|
|
663
|
+
SubagentModel,
|
|
664
|
+
ServiceMap.ServiceMap<LanguageModel.LanguageModel | ProviderName | ModelName>
|
|
665
|
+
>()("clanka/Agent/SubagentModel") {}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* @since 1.0.0
|
|
669
|
+
* @category Subagent model
|
|
670
|
+
*/
|
|
671
|
+
export const layerSubagentModel = <E, R>(
|
|
672
|
+
layer: Layer.Layer<
|
|
673
|
+
LanguageModel.LanguageModel | ProviderName | ModelName,
|
|
674
|
+
E,
|
|
675
|
+
R
|
|
676
|
+
>,
|
|
677
|
+
): Layer.Layer<SubagentModel, E, R> =>
|
|
678
|
+
Layer.effect(SubagentModel, Layer.build(layer))
|
|
679
|
+
|
|
607
680
|
/**
|
|
608
681
|
* @since 1.0.0
|
|
609
682
|
* @category System prompts
|
|
@@ -623,19 +696,19 @@ export class AgentModelConfig extends ServiceMap.Reference<{
|
|
|
623
696
|
}
|
|
624
697
|
|
|
625
698
|
/**
|
|
626
|
-
* A layer that provides most of the common services needed to run an agent.
|
|
627
|
-
*
|
|
628
699
|
* @since 1.0.0
|
|
629
|
-
* @category
|
|
700
|
+
* @category Output
|
|
630
701
|
*/
|
|
631
|
-
export
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
702
|
+
export class AgentStart extends Schema.TaggedClass<AgentStart>()("AgentStart", {
|
|
703
|
+
id: Schema.Number,
|
|
704
|
+
prompt: Prompt.Prompt,
|
|
705
|
+
provider: Schema.String,
|
|
706
|
+
model: Schema.String,
|
|
707
|
+
}) {
|
|
708
|
+
get modelAndProvider() {
|
|
709
|
+
return `${this.provider}/${this.model}`
|
|
710
|
+
}
|
|
711
|
+
}
|
|
639
712
|
|
|
640
713
|
/**
|
|
641
714
|
* @since 1.0.0
|
|
@@ -706,17 +779,6 @@ export class ScriptOutput extends Schema.TaggedClass<ScriptOutput>()(
|
|
|
706
779
|
},
|
|
707
780
|
) {}
|
|
708
781
|
|
|
709
|
-
/**
|
|
710
|
-
* @since 1.0.0
|
|
711
|
-
* @category Output
|
|
712
|
-
*/
|
|
713
|
-
export class AgentFinished extends Schema.TaggedErrorClass<AgentFinished>()(
|
|
714
|
-
"AgentFinished",
|
|
715
|
-
{
|
|
716
|
-
summary: Schema.String,
|
|
717
|
-
},
|
|
718
|
-
) {}
|
|
719
|
-
|
|
720
782
|
/**
|
|
721
783
|
* @since 1.0.0
|
|
722
784
|
* @category Output
|
|
@@ -783,6 +845,7 @@ export class SubagentPart extends Schema.TaggedClass<SubagentPart>()(
|
|
|
783
845
|
* @category Output
|
|
784
846
|
*/
|
|
785
847
|
export type Output =
|
|
848
|
+
| AgentStart
|
|
786
849
|
| ContentPart
|
|
787
850
|
| SubagentStart
|
|
788
851
|
| SubagentComplete
|
|
@@ -793,6 +856,7 @@ export type Output =
|
|
|
793
856
|
* @category Output
|
|
794
857
|
*/
|
|
795
858
|
export const Output = Schema.Union([
|
|
859
|
+
AgentStart,
|
|
796
860
|
ReasoningStart,
|
|
797
861
|
ReasoningDelta,
|
|
798
862
|
ReasoningEnd,
|
|
@@ -804,3 +868,14 @@ export const Output = Schema.Union([
|
|
|
804
868
|
SubagentComplete,
|
|
805
869
|
SubagentPart,
|
|
806
870
|
])
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* @since 1.0.0
|
|
874
|
+
* @category Output
|
|
875
|
+
*/
|
|
876
|
+
export class AgentFinished extends Schema.TaggedErrorClass<AgentFinished>()(
|
|
877
|
+
"AgentFinished",
|
|
878
|
+
{
|
|
879
|
+
summary: Schema.String,
|
|
880
|
+
},
|
|
881
|
+
) {}
|