clanka 0.7.5 → 0.7.7
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/Acp.d.ts +21 -2
- package/dist/Acp.d.ts.map +1 -1
- package/dist/Acp.js +66 -13
- package/dist/Acp.js.map +1 -1
- package/dist/Acp.test.js +56 -10
- package/dist/Acp.test.js.map +1 -1
- package/dist/AcpImage.test.js +1 -0
- package/dist/AcpImage.test.js.map +1 -1
- package/dist/Agent.d.ts.map +1 -1
- package/dist/Agent.js +1 -2
- package/dist/Agent.js.map +1 -1
- package/dist/AgentExecutor.d.ts +0 -172
- package/dist/AgentExecutor.d.ts.map +1 -1
- package/dist/AgentTools.d.ts +0 -123
- package/dist/AgentTools.d.ts.map +1 -1
- package/dist/AgentTools.js +22 -60
- package/dist/AgentTools.js.map +1 -1
- package/dist/AgentTools.test.d.ts +2 -0
- package/dist/AgentTools.test.d.ts.map +1 -0
- package/dist/AgentTools.test.js +63 -0
- package/dist/AgentTools.test.js.map +1 -0
- package/dist/bin/{Effect-DdkIoNCD.mjs → Effect-CeAMoJlg.mjs} +7 -2
- package/dist/bin/Effect-CeAMoJlg.mjs.map +1 -0
- package/dist/bin/{McpClient-CJ0Vugoi.mjs → McpClient-zQibhsnA.mjs} +3 -3
- package/dist/bin/{McpClient-CJ0Vugoi.mjs.map → McpClient-zQibhsnA.mjs.map} +1 -1
- package/dist/bin/{OutputFormatter-DN8OGwuK.mjs → OutputFormatter-C7Awn0DS.mjs} +3 -3
- package/dist/bin/{OutputFormatter-DN8OGwuK.mjs.map → OutputFormatter-C7Awn0DS.mjs.map} +1 -1
- package/dist/bin/{Schema-BALIXGp7.mjs → Schema-Bc06DxcV.mjs} +3 -6
- package/dist/bin/{Schema-BALIXGp7.mjs.map → Schema-Bc06DxcV.mjs.map} +1 -1
- package/dist/bin/{SemanticSearch-O6PZBRfd.mjs → SemanticSearch-BPxQoRSC.mjs} +4 -4
- package/dist/bin/{SemanticSearch-O6PZBRfd.mjs.map → SemanticSearch-BPxQoRSC.mjs.map} +1 -1
- package/dist/bin/{Stream-B5ebASRi.mjs → Stream-DlGXvw0L.mjs} +2 -2
- package/dist/bin/{Stream-B5ebASRi.mjs.map → Stream-DlGXvw0L.mjs.map} +1 -1
- package/dist/bin/cli.mjs +95 -91
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/cli.js +17 -8
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/src/Acp.test.ts +86 -9
- package/src/Acp.ts +90 -17
- package/src/AcpImage.test.ts +1 -0
- package/src/Agent.ts +1 -2
- package/src/AgentTools.test.ts +116 -0
- package/src/AgentTools.ts +32 -76
- package/src/cli.ts +22 -9
- package/dist/bin/Effect-DdkIoNCD.mjs.map +0 -1
package/src/AgentTools.ts
CHANGED
|
@@ -82,6 +82,12 @@ export class ImageAttacher extends Context.Service<
|
|
|
82
82
|
(image: ImageAttachment) => Effect.Effect<void>
|
|
83
83
|
>()("clanka/AgentTools/ImageAttacher") {}
|
|
84
84
|
|
|
85
|
+
const globNamesDirectory = (glob: string) =>
|
|
86
|
+
glob
|
|
87
|
+
.split("/")
|
|
88
|
+
.slice(0, -1)
|
|
89
|
+
.some((segment) => segment.length > 0 && !/[*?[\]{}]/.test(segment))
|
|
90
|
+
|
|
85
91
|
/**
|
|
86
92
|
* @since 1.0.0
|
|
87
93
|
* @category Context
|
|
@@ -94,14 +100,6 @@ export const makeContextNoop = (cwd?: string) =>
|
|
|
94
100
|
Context.add(ImageAttacher, () => Effect.void),
|
|
95
101
|
)
|
|
96
102
|
|
|
97
|
-
class TodoItem extends Schema.Opaque<TodoItem>()(
|
|
98
|
-
Schema.Struct({
|
|
99
|
-
id: Schema.Number,
|
|
100
|
-
text: Schema.String,
|
|
101
|
-
completed: Schema.Boolean,
|
|
102
|
-
}),
|
|
103
|
-
) {}
|
|
104
|
-
|
|
105
103
|
/**
|
|
106
104
|
* @since 1.0.0
|
|
107
105
|
* @category Toolkit
|
|
@@ -169,29 +167,6 @@ export const AgentTools = Toolkit.make(
|
|
|
169
167
|
success: Schema.String,
|
|
170
168
|
dependencies: [CurrentDirectory],
|
|
171
169
|
}),
|
|
172
|
-
Tool.make("listTodos", {
|
|
173
|
-
description: "Read your todo list",
|
|
174
|
-
parameters: Schema.Void,
|
|
175
|
-
success: Schema.Array(TodoItem),
|
|
176
|
-
}),
|
|
177
|
-
Tool.make("addTodo", {
|
|
178
|
-
description: "Add an item to your todo list",
|
|
179
|
-
parameters: Schema.String.annotate({
|
|
180
|
-
identifier: "text",
|
|
181
|
-
}),
|
|
182
|
-
}),
|
|
183
|
-
Tool.make("updateTodo", {
|
|
184
|
-
description: "Update an item in your todo list",
|
|
185
|
-
parameters: Schema.Struct({
|
|
186
|
-
id: Schema.Number,
|
|
187
|
-
text: Schema.optional(Schema.String),
|
|
188
|
-
completed: Schema.optional(Schema.Boolean),
|
|
189
|
-
}),
|
|
190
|
-
}),
|
|
191
|
-
Tool.make("clearTodos", {
|
|
192
|
-
description: "Clear all items in your todo list",
|
|
193
|
-
parameters: Schema.Void,
|
|
194
|
-
}),
|
|
195
170
|
Tool.make("bash", {
|
|
196
171
|
description: "Run a bash command and return the output",
|
|
197
172
|
parameters: Schema.Struct({
|
|
@@ -305,9 +280,6 @@ export const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(
|
|
|
305
280
|
const pathService = yield* Path.Path
|
|
306
281
|
const webSearch = yield* ExaSearch.ExaSearch
|
|
307
282
|
const fetchMarkdown = yield* WebToMarkdown.WebToMarkdown
|
|
308
|
-
const todoMap = new Map<number, TodoItem>()
|
|
309
|
-
let todoIdCounter = 0
|
|
310
|
-
|
|
311
283
|
const execute = Effect.fn(function* (command: ChildProcess.Command) {
|
|
312
284
|
const handle = yield* spawner.spawn(command)
|
|
313
285
|
return yield* handle.all.pipe(
|
|
@@ -474,24 +446,38 @@ export const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(
|
|
|
474
446
|
if (options.filesOnly) {
|
|
475
447
|
args.push("--files-with-matches")
|
|
476
448
|
}
|
|
449
|
+
const searchesIgnoredFiles =
|
|
450
|
+
options.glob !== undefined && !options.glob.startsWith("*")
|
|
477
451
|
if (options.glob) {
|
|
478
452
|
args.push("--glob", options.glob)
|
|
479
|
-
if (
|
|
453
|
+
if (searchesIgnoredFiles) {
|
|
480
454
|
args.push("-uu")
|
|
481
455
|
}
|
|
482
456
|
}
|
|
483
457
|
args.push(options.pattern)
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
458
|
+
const run = Effect.fnUntraced(function* (args: Array<string>) {
|
|
459
|
+
let stream = spawner.streamLines(
|
|
460
|
+
ChildProcess.make("rg", args, {
|
|
461
|
+
cwd,
|
|
462
|
+
stdin: "ignore",
|
|
463
|
+
}),
|
|
464
|
+
)
|
|
465
|
+
stream = Stream.take(stream, options.maxLines ?? 500)
|
|
466
|
+
return yield* Stream.runCollect(stream).pipe(
|
|
467
|
+
Effect.map(Array.join("\n")),
|
|
468
|
+
Effect.orDie,
|
|
469
|
+
)
|
|
470
|
+
})
|
|
471
|
+
const output = yield* run(args)
|
|
472
|
+
if (
|
|
473
|
+
output.length > 0 ||
|
|
474
|
+
searchesIgnoredFiles ||
|
|
475
|
+
options.glob === undefined ||
|
|
476
|
+
!globNamesDirectory(options.glob)
|
|
477
|
+
) {
|
|
478
|
+
return output
|
|
479
|
+
}
|
|
480
|
+
return yield* run(args.slice(0, -1).concat("-uu", options.pattern))
|
|
495
481
|
}),
|
|
496
482
|
glob: Effect.fn("AgentTools.glob")(function* (pattern) {
|
|
497
483
|
yield* Effect.logInfo(`Calling "glob"`).pipe(
|
|
@@ -502,36 +488,6 @@ export const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(
|
|
|
502
488
|
import("glob").then((Glob) => Glob.glob(pattern, { cwd })),
|
|
503
489
|
)
|
|
504
490
|
}),
|
|
505
|
-
listTodos: Effect.fn("AgentTools.listTodos")(function* () {
|
|
506
|
-
yield* Effect.logInfo(`Calling "listTodos"`)
|
|
507
|
-
return Array.fromIterable(todoMap.values())
|
|
508
|
-
}),
|
|
509
|
-
addTodo: Effect.fn("AgentTools.addTodo")(function* (text) {
|
|
510
|
-
yield* Effect.logInfo(`Calling "addTodo"`).pipe(
|
|
511
|
-
Effect.annotateLogs({ text }),
|
|
512
|
-
)
|
|
513
|
-
const id = ++todoIdCounter
|
|
514
|
-
const item = { id, text, completed: false }
|
|
515
|
-
todoMap.set(id, item)
|
|
516
|
-
}),
|
|
517
|
-
updateTodo: Effect.fn("AgentTools.updateTodo")(function* (options) {
|
|
518
|
-
yield* Effect.logInfo(`Calling "updateTodo"`).pipe(
|
|
519
|
-
Effect.annotateLogs(options),
|
|
520
|
-
)
|
|
521
|
-
const item = todoMap.get(options.id)
|
|
522
|
-
if (item === undefined) {
|
|
523
|
-
return yield* Effect.die(`Todo item ${options.id} not found`)
|
|
524
|
-
}
|
|
525
|
-
todoMap.set(item.id, {
|
|
526
|
-
...item,
|
|
527
|
-
text: options.text ?? item.text,
|
|
528
|
-
completed: options.completed ?? item.completed,
|
|
529
|
-
})
|
|
530
|
-
}),
|
|
531
|
-
clearTodos: Effect.fn("AgentTools.clearTodos")(function* () {
|
|
532
|
-
yield* Effect.logInfo(`Calling "clearTodos"`)
|
|
533
|
-
todoMap.clear()
|
|
534
|
-
}),
|
|
535
491
|
bash: Effect.fn("AgentTools.bash")(function* (options) {
|
|
536
492
|
const timeoutMs = Math.min(options.timeoutMs ?? 120_000, 240_000)
|
|
537
493
|
yield* Effect.logInfo(`Calling "bash"`).pipe(
|
package/src/cli.ts
CHANGED
|
@@ -64,14 +64,25 @@ const modelLayer = (provider: Provider, model: string, effort: string) =>
|
|
|
64
64
|
Layer.provide(Copilot.layerClient),
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
+
const isProvider = (provider: string | undefined): provider is Provider =>
|
|
68
|
+
providers.includes(provider as Provider)
|
|
69
|
+
|
|
70
|
+
// `<provider>/<model>/<effort>` as accepted by the `acp` --model flag.
|
|
67
71
|
const parseModelId = (modelId: string) => {
|
|
68
72
|
const [provider, model, effort, ...rest] = modelId.split("/")
|
|
69
|
-
return provider
|
|
70
|
-
providers.includes(provider as Provider) &&
|
|
73
|
+
return isProvider(provider) &&
|
|
71
74
|
model !== undefined &&
|
|
72
|
-
effort
|
|
75
|
+
Schema.is(Acp.ThoughtLevel)(effort) &&
|
|
73
76
|
rest.length === 0
|
|
74
|
-
? Option.some({
|
|
77
|
+
? Option.some({ model: `${provider}:${model}`, thoughtLevel: effort })
|
|
78
|
+
: Option.none()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// `<provider>:<model>` as advertised over ACP.
|
|
82
|
+
const parseAcpModelId = (modelId: string) => {
|
|
83
|
+
const [provider, model, ...rest] = modelId.split(":")
|
|
84
|
+
return isProvider(provider) && model !== undefined && rest.length === 0
|
|
85
|
+
? Option.some({ provider, model })
|
|
75
86
|
: Option.none()
|
|
76
87
|
}
|
|
77
88
|
|
|
@@ -80,7 +91,7 @@ const ModelId = Schema.String.pipe(
|
|
|
80
91
|
Schema.makeFilter(
|
|
81
92
|
(modelId: string) =>
|
|
82
93
|
Option.isSome(parseModelId(modelId)) ||
|
|
83
|
-
`Invalid model "${modelId}", expected <provider>/<model>/<effort
|
|
94
|
+
`Invalid model "${modelId}", expected <provider>/<model>/<effort> with effort one of ${Acp.ThoughtLevel.literals.join(", ")}`,
|
|
84
95
|
),
|
|
85
96
|
),
|
|
86
97
|
)
|
|
@@ -192,6 +203,7 @@ const acpModel = Flag.String("model").pipe(
|
|
|
192
203
|
),
|
|
193
204
|
Flag.withSchema(ModelId),
|
|
194
205
|
Flag.withDefault("openai/gpt-6-astra/medium"),
|
|
206
|
+
Flag.map((modelId) => Option.getOrThrow(parseModelId(modelId))),
|
|
195
207
|
)
|
|
196
208
|
|
|
197
209
|
const acp = Command.make("acp", { model: acpModel, compaction }).pipe(
|
|
@@ -201,14 +213,15 @@ const acp = Command.make("acp", { model: acpModel, compaction }).pipe(
|
|
|
201
213
|
Command.withHandler(({ model }) =>
|
|
202
214
|
Acp.runStdio({
|
|
203
215
|
version,
|
|
204
|
-
defaultModel: model,
|
|
216
|
+
defaultModel: model.model,
|
|
217
|
+
defaultThoughtLevel: model.thoughtLevel,
|
|
205
218
|
makeAgent: (cwd) =>
|
|
206
219
|
Agent.make.pipe(
|
|
207
220
|
Effect.provide(AgentExecutor.layerLocal({ directory: cwd })),
|
|
208
221
|
),
|
|
209
|
-
makeModel: (modelId) =>
|
|
210
|
-
Option.map(
|
|
211
|
-
modelLayer(provider, model,
|
|
222
|
+
makeModel: (modelId, thoughtLevel) =>
|
|
223
|
+
Option.map(parseAcpModelId(modelId), ({ provider, model }) =>
|
|
224
|
+
modelLayer(provider, model, thoughtLevel),
|
|
212
225
|
),
|
|
213
226
|
}),
|
|
214
227
|
),
|