clanka 0.1.11 → 0.1.13
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 +15 -8
- package/dist/Agent.d.ts.map +1 -1
- package/dist/Agent.js +41 -122
- package/dist/Agent.js.map +1 -1
- package/dist/AgentExecutor.d.ts +26 -32
- package/dist/AgentExecutor.d.ts.map +1 -1
- package/dist/AgentTools.d.ts +78 -96
- package/dist/AgentTools.d.ts.map +1 -1
- package/dist/AgentTools.js +40 -60
- package/dist/AgentTools.js.map +1 -1
- package/dist/Codex.d.ts.map +1 -1
- package/dist/Codex.js +1 -7
- package/dist/Codex.js.map +1 -1
- package/dist/Copilot.d.ts.map +1 -1
- package/dist/Copilot.js +1 -2
- package/dist/Copilot.js.map +1 -1
- package/dist/OutputFormatter.d.ts.map +1 -1
- package/dist/OutputFormatter.js +4 -0
- package/dist/OutputFormatter.js.map +1 -1
- package/package.json +18 -18
- package/src/Agent.ts +53 -142
- package/src/AgentTools.ts +45 -71
- package/src/Codex.ts +1 -7
- package/src/Copilot.ts +1 -2
- package/src/OutputFormatter.ts +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clanka",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.13",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -23,35 +23,35 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
26
|
-
"@vscode/ripgrep": "^1.17.
|
|
26
|
+
"@vscode/ripgrep": "^1.17.1",
|
|
27
27
|
"chalk": "^5.6.2",
|
|
28
28
|
"glob": "^13.0.6",
|
|
29
29
|
"turndown": "^7.2.2"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@effect/ai-openai": "4.0.0-beta.
|
|
33
|
-
"@effect/ai-openai-compat": "4.0.0-beta.
|
|
34
|
-
"effect": "4.0.0-beta.
|
|
32
|
+
"@effect/ai-openai": "4.0.0-beta.32",
|
|
33
|
+
"@effect/ai-openai-compat": "4.0.0-beta.32",
|
|
34
|
+
"effect": "4.0.0-beta.32"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@changesets/changelog-github": "^0.
|
|
37
|
+
"@changesets/changelog-github": "^0.6.0",
|
|
38
38
|
"@changesets/cli": "^2.29.8",
|
|
39
|
-
"@effect/ai-openai": "4.0.0-beta.
|
|
40
|
-
"@effect/ai-openai-compat": "4.0.0-beta.
|
|
41
|
-
"@effect/language-service": "^0.
|
|
42
|
-
"@effect/platform-node": "4.0.0-beta.
|
|
43
|
-
"@effect/vitest": "4.0.0-beta.
|
|
44
|
-
"@linear/sdk": "^
|
|
45
|
-
"@types/node": "^25.
|
|
39
|
+
"@effect/ai-openai": "4.0.0-beta.32",
|
|
40
|
+
"@effect/ai-openai-compat": "4.0.0-beta.32",
|
|
41
|
+
"@effect/language-service": "^0.80.0",
|
|
42
|
+
"@effect/platform-node": "4.0.0-beta.32",
|
|
43
|
+
"@effect/vitest": "4.0.0-beta.32",
|
|
44
|
+
"@linear/sdk": "^77.0.0",
|
|
45
|
+
"@types/node": "^25.5.0",
|
|
46
46
|
"@types/turndown": "^5.0.6",
|
|
47
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
48
|
-
"effect": "4.0.0-beta.
|
|
47
|
+
"@typescript/native-preview": "7.0.0-dev.20260315.1",
|
|
48
|
+
"effect": "4.0.0-beta.32",
|
|
49
49
|
"husky": "^9.1.7",
|
|
50
|
-
"lint-staged": "^16.
|
|
51
|
-
"oxlint": "^1.
|
|
50
|
+
"lint-staged": "^16.4.0",
|
|
51
|
+
"oxlint": "^1.55.0",
|
|
52
52
|
"prettier": "^3.8.1",
|
|
53
53
|
"typescript": "^5.9.3",
|
|
54
|
-
"vitest": "^4.0
|
|
54
|
+
"vitest": "^4.1.0"
|
|
55
55
|
},
|
|
56
56
|
"lint-staged": {
|
|
57
57
|
"*.{ts,tsx}": [
|
package/src/Agent.ts
CHANGED
|
@@ -19,7 +19,7 @@ import * as Effect from "effect/Effect"
|
|
|
19
19
|
import * as Stream from "effect/Stream"
|
|
20
20
|
import type * as Scope from "effect/Scope"
|
|
21
21
|
import * as LanguageModel from "effect/unstable/ai/LanguageModel"
|
|
22
|
-
import
|
|
22
|
+
import * as AiError from "effect/unstable/ai/AiError"
|
|
23
23
|
import * as ServiceMap from "effect/ServiceMap"
|
|
24
24
|
import * as Option from "effect/Option"
|
|
25
25
|
import { identity, pipe } from "effect/Function"
|
|
@@ -31,6 +31,7 @@ import * as Layer from "effect/Layer"
|
|
|
31
31
|
import * as Tool from "effect/unstable/ai/Tool"
|
|
32
32
|
import * as Toolkit from "effect/unstable/ai/Toolkit"
|
|
33
33
|
import * as Semaphore from "effect/Semaphore"
|
|
34
|
+
import * as Schedule from "effect/Schedule"
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* @since 1.0.0
|
|
@@ -167,7 +168,6 @@ ${content}
|
|
|
167
168
|
>()
|
|
168
169
|
let finalSummary = Option.none<string>()
|
|
169
170
|
|
|
170
|
-
const singleToolMode = modelConfig.supportsNoTools !== true
|
|
171
171
|
const output = yield* Queue.make<Output, AgentFinished | AiError.AiError>()
|
|
172
172
|
const prompt = opts.disableHistory ? MutableRef.make(Prompt.empty) : history
|
|
173
173
|
|
|
@@ -176,7 +176,7 @@ ${content}
|
|
|
176
176
|
const generateSystem =
|
|
177
177
|
typeof opts.system === "function" ? opts.system : defaultSystem
|
|
178
178
|
|
|
179
|
-
const toolInstructions = generateSystemTools(toolsDts
|
|
179
|
+
const toolInstructions = generateSystemTools(toolsDts)
|
|
180
180
|
let system = generateSystem({
|
|
181
181
|
toolInstructions,
|
|
182
182
|
agentsMd: Option.getOrElse(agentsMd, () => ""),
|
|
@@ -295,25 +295,8 @@ ${content}
|
|
|
295
295
|
MutableRef.update(prompt, Prompt.setSystem(system))
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
let currentScript = ""
|
|
299
298
|
yield* Effect.gen(function* () {
|
|
300
299
|
while (true) {
|
|
301
|
-
if (!singleToolMode && currentScript.length > 0) {
|
|
302
|
-
const result = yield* executeScript(currentScript)
|
|
303
|
-
MutableRef.update(
|
|
304
|
-
prompt,
|
|
305
|
-
Prompt.concat([
|
|
306
|
-
{
|
|
307
|
-
role: modelConfig.supportsAssistantPrefill
|
|
308
|
-
? "assistant"
|
|
309
|
-
: "user",
|
|
310
|
-
content: `Console output from executing javascript code:\n\n${result}`,
|
|
311
|
-
},
|
|
312
|
-
]),
|
|
313
|
-
)
|
|
314
|
-
currentScript = ""
|
|
315
|
-
}
|
|
316
|
-
|
|
317
300
|
if (Option.isSome(finalSummary)) {
|
|
318
301
|
yield* Queue.fail(
|
|
319
302
|
output,
|
|
@@ -343,19 +326,8 @@ ${content}
|
|
|
343
326
|
let reasoningStarted = false
|
|
344
327
|
let hadReasoningDelta = false
|
|
345
328
|
yield* pipe(
|
|
346
|
-
ai.streamText(
|
|
347
|
-
singleToolMode
|
|
348
|
-
? { prompt: prompt.current, toolkit: singleTool }
|
|
349
|
-
: { prompt: prompt.current },
|
|
350
|
-
),
|
|
329
|
+
ai.streamText({ prompt: prompt.current, toolkit: singleTool }),
|
|
351
330
|
Stream.takeUntil((part) => {
|
|
352
|
-
if (
|
|
353
|
-
!singleToolMode &&
|
|
354
|
-
part.type === "text-end" &&
|
|
355
|
-
currentScript.trim().length > 0
|
|
356
|
-
) {
|
|
357
|
-
return true
|
|
358
|
-
}
|
|
359
331
|
if (
|
|
360
332
|
(part.type === "text-end" || part.type === "reasoning-end") &&
|
|
361
333
|
pendingMessages.size > 0
|
|
@@ -370,68 +342,10 @@ ${content}
|
|
|
370
342
|
for (const part of parts) {
|
|
371
343
|
switch (part.type) {
|
|
372
344
|
case "text-start":
|
|
373
|
-
if (singleToolMode) {
|
|
374
|
-
if (hadReasoningDelta) {
|
|
375
|
-
hadReasoningDelta = false
|
|
376
|
-
maybeSend({
|
|
377
|
-
agentId,
|
|
378
|
-
part: new ReasoningEnd(),
|
|
379
|
-
release: true,
|
|
380
|
-
})
|
|
381
|
-
}
|
|
382
|
-
reasoningStarted = true
|
|
383
|
-
break
|
|
384
|
-
}
|
|
385
|
-
currentScript = ""
|
|
386
|
-
break
|
|
387
|
-
case "text-delta": {
|
|
388
|
-
if (singleToolMode) {
|
|
389
|
-
hadReasoningDelta = true
|
|
390
|
-
if (reasoningStarted) {
|
|
391
|
-
reasoningStarted = false
|
|
392
|
-
maybeSend({
|
|
393
|
-
agentId,
|
|
394
|
-
part: new ReasoningStart(),
|
|
395
|
-
acquire: true,
|
|
396
|
-
})
|
|
397
|
-
}
|
|
398
|
-
maybeSend({
|
|
399
|
-
agentId,
|
|
400
|
-
part: new ReasoningDelta({ delta: part.delta }),
|
|
401
|
-
})
|
|
402
|
-
break
|
|
403
|
-
}
|
|
404
|
-
if (currentScript === "" && part.delta.length > 0) {
|
|
405
|
-
maybeSend({
|
|
406
|
-
agentId,
|
|
407
|
-
part: new ScriptStart(),
|
|
408
|
-
acquire: true,
|
|
409
|
-
})
|
|
410
|
-
}
|
|
411
|
-
maybeSend({
|
|
412
|
-
agentId,
|
|
413
|
-
part: new ScriptDelta({ delta: part.delta }),
|
|
414
|
-
})
|
|
415
|
-
currentScript += part.delta
|
|
416
|
-
break
|
|
417
|
-
}
|
|
418
|
-
case "text-end": {
|
|
419
|
-
if (singleToolMode) {
|
|
420
|
-
reasoningStarted = false
|
|
421
|
-
if (hadReasoningDelta) {
|
|
422
|
-
hadReasoningDelta = false
|
|
423
|
-
maybeSend({
|
|
424
|
-
agentId,
|
|
425
|
-
part: new ReasoningEnd(),
|
|
426
|
-
release: true,
|
|
427
|
-
})
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
break
|
|
431
|
-
}
|
|
432
345
|
case "reasoning-start":
|
|
433
346
|
reasoningStarted = true
|
|
434
347
|
break
|
|
348
|
+
case "text-delta":
|
|
435
349
|
case "reasoning-delta":
|
|
436
350
|
hadReasoningDelta = true
|
|
437
351
|
if (reasoningStarted) {
|
|
@@ -447,6 +361,7 @@ ${content}
|
|
|
447
361
|
part: new ReasoningDelta({ delta: part.delta }),
|
|
448
362
|
})
|
|
449
363
|
break
|
|
364
|
+
case "text-end":
|
|
450
365
|
case "reasoning-end":
|
|
451
366
|
reasoningStarted = false
|
|
452
367
|
if (hadReasoningDelta) {
|
|
@@ -468,8 +383,12 @@ ${content}
|
|
|
468
383
|
Effect.retry({
|
|
469
384
|
while: (err) => {
|
|
470
385
|
response = []
|
|
386
|
+
if (err.isRetryable) {
|
|
387
|
+
maybeSend({ agentId, part: new ErrorRetry({ error: err }) })
|
|
388
|
+
}
|
|
471
389
|
return err.isRetryable
|
|
472
390
|
},
|
|
391
|
+
schedule: retryPolicy,
|
|
473
392
|
}),
|
|
474
393
|
modelConfig.systemPromptTransform
|
|
475
394
|
? (effect) => modelConfig.systemPromptTransform!(system, effect)
|
|
@@ -479,7 +398,6 @@ ${content}
|
|
|
479
398
|
prompt,
|
|
480
399
|
Prompt.concat(Prompt.fromResponseParts(response)),
|
|
481
400
|
)
|
|
482
|
-
currentScript = currentScript.trim()
|
|
483
401
|
}
|
|
484
402
|
}).pipe(
|
|
485
403
|
Effect.provideService(ScriptExecutor, (script) => {
|
|
@@ -526,6 +444,11 @@ ${content}
|
|
|
526
444
|
})
|
|
527
445
|
})
|
|
528
446
|
|
|
447
|
+
const retryPolicy = Schedule.exponential(100, 1.5).pipe(
|
|
448
|
+
Schedule.either(Schedule.spaced(5000)),
|
|
449
|
+
Schedule.jittered,
|
|
450
|
+
)
|
|
451
|
+
|
|
529
452
|
const defaultSystem = (options: {
|
|
530
453
|
readonly toolInstructions: string
|
|
531
454
|
readonly agentsMd: string | null
|
|
@@ -540,12 +463,28 @@ ${options.toolInstructions}
|
|
|
540
463
|
${options.agentsMd}
|
|
541
464
|
`
|
|
542
465
|
|
|
543
|
-
const generateSystemTools = (
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
466
|
+
const generateSystemTools = (
|
|
467
|
+
toolsDts: string,
|
|
468
|
+
) => `**YOU ONLY HAVE ACCESS TO ONE TOOL** "execute", to run javascript code to do your work.
|
|
469
|
+
|
|
470
|
+
- Use \`console.log\` to print any output you need.
|
|
471
|
+
- Top level await is supported.
|
|
472
|
+
- AVOID passing scripts into the "bash" function, and instead write javascript.
|
|
473
|
+
- Do as much work as possible in a single script, using \`Promise.all\` to run multiple functions in parallel.
|
|
474
|
+
- Variables **are not shared** between executions, so you must include all necessary code in each script you execute.
|
|
475
|
+
|
|
476
|
+
**When you have fully completed your task**, call the "taskComplete" function with the final output.
|
|
477
|
+
DO NOT output the final result without wrapping it with "taskComplete".
|
|
478
|
+
Make sure every detail of the task is done before calling "taskComplete".
|
|
479
|
+
|
|
480
|
+
You have the following functions available to you:
|
|
547
481
|
|
|
548
|
-
|
|
482
|
+
\`\`\`ts
|
|
483
|
+
${toolsDts}
|
|
484
|
+
|
|
485
|
+
/** The global Fetch API available for making HTTP requests. */
|
|
486
|
+
declare const fetch: typeof globalThis.fetch
|
|
487
|
+
\`\`\`
|
|
549
488
|
|
|
550
489
|
For example, here is how you would read a file. First you would respond with
|
|
551
490
|
javascript code that uses the "readFile" function:
|
|
@@ -562,51 +501,12 @@ console.log(JSON.parse(content))
|
|
|
562
501
|
And then you will revieve back the console output:
|
|
563
502
|
|
|
564
503
|
\`\`\`
|
|
565
|
-
Console output from executing javascript code:
|
|
566
|
-
|
|
567
504
|
[22:44:53.054] INFO (#47): Calling "readFile" { path: 'package.json' }
|
|
568
505
|
{
|
|
569
506
|
"name": "my-project",
|
|
570
507
|
"version": "1.0.0"
|
|
571
508
|
}
|
|
572
509
|
\`\`\``
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
const generateSystemMulti = (toolsDts: string) => {
|
|
576
|
-
return `You complete your tasks by **only writing javascript code** to interact with your environment.
|
|
577
|
-
|
|
578
|
-
${systemToolsCommon(toolsDts)}`
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// oxlint-disable-next-line typescript/no-explicit-any
|
|
582
|
-
const generateSystemSingle = (toolsDts: string) => {
|
|
583
|
-
return `**YOU ONLY HAVE ACCESS TO ONE TOOL** "execute", to run javascript code to do your work.
|
|
584
|
-
|
|
585
|
-
${systemToolsCommon(toolsDts)}`
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
const systemToolsCommon = (
|
|
589
|
-
toolsDts: string,
|
|
590
|
-
) => `- Use \`console.log\` to print any output you need.
|
|
591
|
-
- Top level await is supported.
|
|
592
|
-
- AVOID passing scripts into the "bash" function, and instead write javascript.
|
|
593
|
-
- PREFER the "search" function over "rg" for finding information or code
|
|
594
|
-
- Do as much work as possible in a single script, using \`Promise.all\` to run multiple functions in parallel.
|
|
595
|
-
- Variables **are not shared** between executions, so you must include all necessary code in each script you execute.
|
|
596
|
-
- Make use of the "delegate" tool to delegate exploration and small research tasks. You can delegate multiple tasks in parallel with Promise.all
|
|
597
|
-
|
|
598
|
-
**When you have fully completed your task**, call the "taskComplete" function with the final output.
|
|
599
|
-
DO NOT output the final result without wrapping it with "taskComplete".
|
|
600
|
-
Make sure every detail of the task is done before calling "taskComplete".
|
|
601
|
-
|
|
602
|
-
You have the following functions available to you:
|
|
603
|
-
|
|
604
|
-
\`\`\`ts
|
|
605
|
-
${toolsDts}
|
|
606
|
-
|
|
607
|
-
/** The global Fetch API available for making HTTP requests. */
|
|
608
|
-
declare const fetch: typeof globalThis.fetch
|
|
609
|
-
\`\`\``
|
|
610
510
|
|
|
611
511
|
class ScriptExecutor extends ServiceMap.Service<
|
|
612
512
|
ScriptExecutor,
|
|
@@ -690,12 +590,12 @@ export const layerSubagentModel = <E, R>(
|
|
|
690
590
|
* @category System prompts
|
|
691
591
|
*/
|
|
692
592
|
export class AgentModelConfig extends ServiceMap.Reference<{
|
|
693
|
-
readonly systemPromptTransform?:
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
593
|
+
readonly systemPromptTransform?:
|
|
594
|
+
| (<A, E, R>(
|
|
595
|
+
system: string,
|
|
596
|
+
effect: Effect.Effect<A, E, R>,
|
|
597
|
+
) => Effect.Effect<A, E, R>)
|
|
598
|
+
| undefined
|
|
699
599
|
}>("clanka/Agent/SystemPromptTransform", {
|
|
700
600
|
defaultValue: () => ({}),
|
|
701
601
|
}) {
|
|
@@ -776,6 +676,14 @@ export class ScriptEnd extends Schema.TaggedClass<ScriptEnd>()(
|
|
|
776
676
|
{},
|
|
777
677
|
) {}
|
|
778
678
|
|
|
679
|
+
/**
|
|
680
|
+
* @since 1.0.0
|
|
681
|
+
* @category Output
|
|
682
|
+
*/
|
|
683
|
+
export class ErrorRetry extends Schema.TaggedClass<ErrorRetry>()("ErrorRetry", {
|
|
684
|
+
error: AiError.AiError,
|
|
685
|
+
}) {}
|
|
686
|
+
|
|
779
687
|
/**
|
|
780
688
|
* @since 1.0.0
|
|
781
689
|
* @category Output
|
|
@@ -825,6 +733,7 @@ export type ContentPart =
|
|
|
825
733
|
| ScriptDelta
|
|
826
734
|
| ScriptEnd
|
|
827
735
|
| ScriptOutput
|
|
736
|
+
| ErrorRetry
|
|
828
737
|
|
|
829
738
|
export const ContentPart = Schema.Union([
|
|
830
739
|
ReasoningStart,
|
|
@@ -834,6 +743,7 @@ export const ContentPart = Schema.Union([
|
|
|
834
743
|
ScriptDelta,
|
|
835
744
|
ScriptEnd,
|
|
836
745
|
ScriptOutput,
|
|
746
|
+
ErrorRetry,
|
|
837
747
|
])
|
|
838
748
|
|
|
839
749
|
/**
|
|
@@ -875,6 +785,7 @@ export const Output = Schema.Union([
|
|
|
875
785
|
SubagentStart,
|
|
876
786
|
SubagentComplete,
|
|
877
787
|
SubagentPart,
|
|
788
|
+
ErrorRetry,
|
|
878
789
|
])
|
|
879
790
|
|
|
880
791
|
/**
|
package/src/AgentTools.ts
CHANGED
|
@@ -20,7 +20,6 @@ import { pipe } from "effect/Function"
|
|
|
20
20
|
import * as Array from "effect/Array"
|
|
21
21
|
import * as Data from "effect/Data"
|
|
22
22
|
import * as Layer from "effect/Layer"
|
|
23
|
-
import * as Duration from "effect/Duration"
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* @since 1.0.0
|
|
@@ -75,14 +74,51 @@ export const AgentTools = Toolkit.make(
|
|
|
75
74
|
success: Schema.NullOr(Schema.String),
|
|
76
75
|
dependencies: [CurrentDirectory],
|
|
77
76
|
}),
|
|
78
|
-
Tool.make("
|
|
79
|
-
description: "
|
|
77
|
+
Tool.make("rg", {
|
|
78
|
+
description: "Search for a pattern in files using ripgrep",
|
|
79
|
+
parameters: Schema.Struct({
|
|
80
|
+
pattern: Schema.String,
|
|
81
|
+
glob: Schema.optional(Schema.String).annotate({
|
|
82
|
+
documentation: "--glob",
|
|
83
|
+
}),
|
|
84
|
+
maxLines: Schema.optional(Schema.Finite).annotate({
|
|
85
|
+
documentation:
|
|
86
|
+
"The total maximum number of lines to return across all files (default: 500)",
|
|
87
|
+
}),
|
|
88
|
+
}),
|
|
89
|
+
success: Schema.String,
|
|
90
|
+
dependencies: [CurrentDirectory],
|
|
91
|
+
}),
|
|
92
|
+
Tool.make("delegate", {
|
|
93
|
+
description:
|
|
94
|
+
"Delegate a task to another software engineer / sub-agent. Returns the result of the task.",
|
|
80
95
|
parameters: Schema.String.annotate({
|
|
81
|
-
identifier: "
|
|
96
|
+
identifier: "task",
|
|
82
97
|
}),
|
|
83
98
|
success: Schema.String,
|
|
84
99
|
dependencies: [SubagentExecutor],
|
|
85
100
|
}),
|
|
101
|
+
Tool.make("glob", {
|
|
102
|
+
description: "Find files matching a glob pattern.",
|
|
103
|
+
parameters: Schema.String.annotate({
|
|
104
|
+
identifier: "pattern",
|
|
105
|
+
}),
|
|
106
|
+
success: Schema.Array(Schema.String),
|
|
107
|
+
dependencies: [CurrentDirectory],
|
|
108
|
+
}),
|
|
109
|
+
Tool.make("bash", {
|
|
110
|
+
description: "Run a bash command and return the output",
|
|
111
|
+
parameters: Schema.Struct({
|
|
112
|
+
command: Schema.String,
|
|
113
|
+
timeoutMs: Schema.optional(Schema.Finite).annotate({
|
|
114
|
+
documentation: "Timeout in ms (default: 120000)",
|
|
115
|
+
}),
|
|
116
|
+
}).annotate({
|
|
117
|
+
identifier: "command",
|
|
118
|
+
}),
|
|
119
|
+
success: Schema.String,
|
|
120
|
+
dependencies: [CurrentDirectory],
|
|
121
|
+
}),
|
|
86
122
|
Tool.make("writeFile", {
|
|
87
123
|
description:
|
|
88
124
|
"Write content to a file, creating parent directories if needed. PREFER USING applyPatch to update existing files.",
|
|
@@ -132,43 +168,6 @@ export const AgentTools = Toolkit.make(
|
|
|
132
168
|
success: Schema.Array(Schema.String),
|
|
133
169
|
dependencies: [CurrentDirectory],
|
|
134
170
|
}),
|
|
135
|
-
Tool.make("rg", {
|
|
136
|
-
description:
|
|
137
|
-
"Search for a pattern in files using ripgrep. Prefer the search function unless finding something specific",
|
|
138
|
-
parameters: Schema.Struct({
|
|
139
|
-
pattern: Schema.String,
|
|
140
|
-
glob: Schema.optional(Schema.String).annotate({
|
|
141
|
-
documentation: "--glob",
|
|
142
|
-
}),
|
|
143
|
-
maxLines: Schema.optional(Schema.Finite).annotate({
|
|
144
|
-
documentation:
|
|
145
|
-
"The total maximum number of lines to return across all files (default: 500)",
|
|
146
|
-
}),
|
|
147
|
-
}),
|
|
148
|
-
success: Schema.String,
|
|
149
|
-
dependencies: [CurrentDirectory],
|
|
150
|
-
}),
|
|
151
|
-
Tool.make("glob", {
|
|
152
|
-
description: "Find files matching a glob pattern.",
|
|
153
|
-
parameters: Schema.String.annotate({
|
|
154
|
-
identifier: "pattern",
|
|
155
|
-
}),
|
|
156
|
-
success: Schema.Array(Schema.String),
|
|
157
|
-
dependencies: [CurrentDirectory],
|
|
158
|
-
}),
|
|
159
|
-
Tool.make("bash", {
|
|
160
|
-
description: "Run a bash command and return the output",
|
|
161
|
-
parameters: Schema.Struct({
|
|
162
|
-
command: Schema.String,
|
|
163
|
-
timeoutMs: Schema.optional(Schema.Finite).annotate({
|
|
164
|
-
documentation: "Timeout in ms (default: 120000)",
|
|
165
|
-
}),
|
|
166
|
-
}).annotate({
|
|
167
|
-
identifier: "command",
|
|
168
|
-
}),
|
|
169
|
-
success: Schema.String,
|
|
170
|
-
dependencies: [CurrentDirectory],
|
|
171
|
-
}),
|
|
172
171
|
Tool.make("gh", {
|
|
173
172
|
description: "Use the GitHub CLI to run a command and return the output",
|
|
174
173
|
parameters: Schema.Array(Schema.String).annotate({
|
|
@@ -177,15 +176,6 @@ export const AgentTools = Toolkit.make(
|
|
|
177
176
|
success: Schema.String,
|
|
178
177
|
dependencies: [CurrentDirectory],
|
|
179
178
|
}),
|
|
180
|
-
Tool.make("delegate", {
|
|
181
|
-
description:
|
|
182
|
-
"Delegate a task to another software engineer. Returns the result of the task.",
|
|
183
|
-
parameters: Schema.String.annotate({
|
|
184
|
-
identifier: "task",
|
|
185
|
-
}),
|
|
186
|
-
success: Schema.String,
|
|
187
|
-
dependencies: [SubagentExecutor],
|
|
188
|
-
}),
|
|
189
179
|
Tool.make("webSearch", {
|
|
190
180
|
description: "Search the web for recent information.",
|
|
191
181
|
parameters: ExaSearch.ExaSearchOptions,
|
|
@@ -356,11 +346,11 @@ export const AgentToolHandlersNoDeps = AgentTools.toLayer(
|
|
|
356
346
|
return yield* Effect.promise(() => Glob.glob(pattern, { cwd }))
|
|
357
347
|
}),
|
|
358
348
|
bash: Effect.fn("AgentTools.bash")(function* (options) {
|
|
359
|
-
const
|
|
349
|
+
const timeoutMs = options.timeoutMs ?? 120_000
|
|
360
350
|
yield* Effect.logInfo(`Calling "bash"`).pipe(
|
|
361
351
|
Effect.annotateLogs({
|
|
362
352
|
...options,
|
|
363
|
-
timeoutMs
|
|
353
|
+
timeoutMs,
|
|
364
354
|
}),
|
|
365
355
|
)
|
|
366
356
|
const cwd = yield* CurrentDirectory
|
|
@@ -370,13 +360,9 @@ export const AgentToolHandlersNoDeps = AgentTools.toLayer(
|
|
|
370
360
|
})
|
|
371
361
|
return yield* execute(cmd).pipe(
|
|
372
362
|
Effect.timeoutOrElse({
|
|
373
|
-
duration:
|
|
363
|
+
duration: timeoutMs,
|
|
374
364
|
onTimeout: () =>
|
|
375
|
-
Effect.die(
|
|
376
|
-
new Error(
|
|
377
|
-
`Command timed out after ${Duration.format(timeout)}`,
|
|
378
|
-
),
|
|
379
|
-
),
|
|
365
|
+
Effect.die(new Error(`Command timed out after ${timeoutMs}ms`)),
|
|
380
366
|
}),
|
|
381
367
|
)
|
|
382
368
|
}, Effect.orDie),
|
|
@@ -544,21 +530,9 @@ export const AgentToolHandlersNoDeps = AgentTools.toLayer(
|
|
|
544
530
|
delegate: Effect.fn("AgentTools.delegate")(function* (prompt) {
|
|
545
531
|
yield* Effect.logInfo(`Calling "delegate"`)
|
|
546
532
|
const spawn = yield* SubagentExecutor
|
|
547
|
-
return yield* spawn(`You have been asked using the "delegate" function to complete the following task. Try to avoid using the "delegate"
|
|
533
|
+
return yield* spawn(`You have been asked using the "delegate" function to complete the following task. Try to avoid using the "delegate" function yourself unless strictly necessary:
|
|
548
534
|
|
|
549
535
|
${prompt}`)
|
|
550
|
-
}, Effect.orDie),
|
|
551
|
-
search: Effect.fn("AgentTools.search")(function* (description) {
|
|
552
|
-
yield* Effect.logInfo(`Calling "search"`)
|
|
553
|
-
const spawn = yield* SubagentExecutor
|
|
554
|
-
return yield* spawn(`You are to find the following information as fast as possible:
|
|
555
|
-
|
|
556
|
-
${description}
|
|
557
|
-
|
|
558
|
-
Requirements:
|
|
559
|
-
- DO NOT call the "search" or "delegate" functions.
|
|
560
|
-
- Output a concise report with file names, line numbers, and code snippets.
|
|
561
|
-
- If nothing relevant is found, say so clearly.`)
|
|
562
536
|
}, Effect.orDie),
|
|
563
537
|
taskComplete: Effect.fn("AgentTools.taskComplete")(function* (message) {
|
|
564
538
|
const deferred = yield* TaskCompleter
|
package/src/Codex.ts
CHANGED
|
@@ -40,11 +40,7 @@ export const model = (
|
|
|
40
40
|
OpenAiLanguageModel.layer({
|
|
41
41
|
model,
|
|
42
42
|
config: {
|
|
43
|
-
...Struct.omit(options ?? {}, [
|
|
44
|
-
"reasoning",
|
|
45
|
-
"supportsNoTools",
|
|
46
|
-
"supportsAssistantPrefill",
|
|
47
|
-
]),
|
|
43
|
+
...Struct.omit(options ?? {}, ["reasoning"]),
|
|
48
44
|
store: false,
|
|
49
45
|
reasoning: {
|
|
50
46
|
effort: options?.reasoning?.effort ?? "medium",
|
|
@@ -57,8 +53,6 @@ export const model = (
|
|
|
57
53
|
OpenAiLanguageModel.withConfigOverride(effect, {
|
|
58
54
|
instructions: system,
|
|
59
55
|
}),
|
|
60
|
-
supportsAssistantPrefill: options?.supportsAssistantPrefill ?? true,
|
|
61
|
-
supportsNoTools: options?.supportsNoTools ?? true,
|
|
62
56
|
}),
|
|
63
57
|
).pipe(Layer.provide(layerClient)),
|
|
64
58
|
)
|
package/src/Copilot.ts
CHANGED
|
@@ -45,8 +45,7 @@ export const model = (
|
|
|
45
45
|
]),
|
|
46
46
|
}),
|
|
47
47
|
AgentModelConfig.layer({
|
|
48
|
-
|
|
49
|
-
supportsNoTools: options?.supportsNoTools ?? false,
|
|
48
|
+
systemPromptTransform: options?.systemPromptTransform,
|
|
50
49
|
}),
|
|
51
50
|
).pipe(Layer.provide(layerClient)),
|
|
52
51
|
)
|
package/src/OutputFormatter.ts
CHANGED
|
@@ -10,6 +10,7 @@ import * as Stream from "effect/Stream"
|
|
|
10
10
|
import type { AgentFinished, Output } from "./Agent.ts"
|
|
11
11
|
import chalk from "chalk"
|
|
12
12
|
import type * as Prompt from "effect/unstable/ai/Prompt"
|
|
13
|
+
import * as Cause from "effect/Cause"
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @since 1.0.0
|
|
@@ -73,6 +74,9 @@ ${output.summary}\n\n`
|
|
|
73
74
|
: output.output
|
|
74
75
|
return `${prefix}${chalkScriptHeading(`${scriptIcon} Script output`)}\n\n${chalk.dim(truncated)}\n\n`
|
|
75
76
|
}
|
|
77
|
+
case "ErrorRetry": {
|
|
78
|
+
return `${prefix}${chalk.red(`Error: ${output.error}. Retrying...`)}\n\n${chalk.dim(Cause.pretty(Cause.fail(output.error)))}\n\n`
|
|
79
|
+
}
|
|
76
80
|
}
|
|
77
81
|
}),
|
|
78
82
|
Stream.catchTag("AgentFinished", (finished) =>
|