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.
Files changed (73) hide show
  1. package/dist/Agent.d.ts +87 -40
  2. package/dist/Agent.d.ts.map +1 -1
  3. package/dist/Agent.js +154 -94
  4. package/dist/Agent.js.map +1 -1
  5. package/dist/AgentExecutor.d.ts +165 -0
  6. package/dist/AgentExecutor.d.ts.map +1 -0
  7. package/dist/AgentExecutor.js +121 -0
  8. package/dist/AgentExecutor.js.map +1 -0
  9. package/dist/AgentTools.d.ts +14 -132
  10. package/dist/AgentTools.d.ts.map +1 -1
  11. package/dist/AgentTools.js +10 -12
  12. package/dist/AgentTools.js.map +1 -1
  13. package/dist/OutputFormatter.d.ts.map +1 -1
  14. package/dist/OutputFormatter.js +18 -0
  15. package/dist/OutputFormatter.js.map +1 -1
  16. package/dist/WebToMarkdown.d.ts.map +1 -1
  17. package/dist/WebToMarkdown.js +1 -1
  18. package/dist/WebToMarkdown.js.map +1 -1
  19. package/dist/WebToMarkdown.test.d.ts +2 -0
  20. package/dist/WebToMarkdown.test.d.ts.map +1 -0
  21. package/dist/WebToMarkdown.test.js +37 -0
  22. package/dist/WebToMarkdown.test.js.map +1 -0
  23. package/dist/index.d.ts +4 -4
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +4 -4
  26. package/dist/index.js.map +1 -1
  27. package/package.json +3 -3
  28. package/src/Agent.ts +290 -215
  29. package/src/AgentExecutor.ts +245 -0
  30. package/src/AgentTools.ts +25 -22
  31. package/src/OutputFormatter.ts +18 -0
  32. package/src/WebToMarkdown.test.ts +65 -0
  33. package/src/WebToMarkdown.ts +1 -0
  34. package/src/index.ts +4 -4
  35. package/dist/Agent.test.d.ts +0 -2
  36. package/dist/Agent.test.d.ts.map +0 -1
  37. package/dist/Agent.test.js +0 -111
  38. package/dist/Agent.test.js.map +0 -1
  39. package/dist/AgentTools.test.d.ts +0 -2
  40. package/dist/AgentTools.test.d.ts.map +0 -1
  41. package/dist/AgentTools.test.js +0 -714
  42. package/dist/AgentTools.test.js.map +0 -1
  43. package/dist/DuckDuckGo.d.ts +0 -28
  44. package/dist/DuckDuckGo.d.ts.map +0 -1
  45. package/dist/DuckDuckGo.js +0 -131
  46. package/dist/DuckDuckGo.js.map +0 -1
  47. package/dist/Executor.d.ts +0 -20
  48. package/dist/Executor.d.ts.map +0 -1
  49. package/dist/Executor.js +0 -98
  50. package/dist/Executor.js.map +0 -1
  51. package/dist/GithubCopilot.d.ts +0 -11
  52. package/dist/GithubCopilot.d.ts.map +0 -1
  53. package/dist/GithubCopilot.js +0 -14
  54. package/dist/GithubCopilot.js.map +0 -1
  55. package/dist/GithubCopilotAuth.d.ts +0 -57
  56. package/dist/GithubCopilotAuth.d.ts.map +0 -1
  57. package/dist/GithubCopilotAuth.js +0 -218
  58. package/dist/GithubCopilotAuth.js.map +0 -1
  59. package/dist/GithubCopilotAuth.test.d.ts +0 -2
  60. package/dist/GithubCopilotAuth.test.d.ts.map +0 -1
  61. package/dist/GithubCopilotAuth.test.js +0 -267
  62. package/dist/GithubCopilotAuth.test.js.map +0 -1
  63. package/dist/MockSearch.d.ts +0 -12
  64. package/dist/MockSearch.d.ts.map +0 -1
  65. package/dist/MockSearch.js +0 -4
  66. package/dist/MockSearch.js.map +0 -1
  67. package/dist/ai.d.ts +0 -2
  68. package/dist/ai.d.ts.map +0 -1
  69. package/dist/ai.js +0 -29
  70. package/dist/ai.js.map +0 -1
  71. package/dist/examples/cli.mjs +0 -68514
  72. package/src/Agent.test.ts +0 -159
  73. package/src/Executor.ts +0 -151
package/src/Agent.test.ts DELETED
@@ -1,159 +0,0 @@
1
- import { NodeServices } from "@effect/platform-node"
2
- import { Effect, Layer, Stream } from "effect"
3
- import { describe, it } from "@effect/vitest"
4
- import { expect } from "vitest"
5
- import { AgentModelConfig, make } from "./Agent.ts"
6
- import { pretty } from "./OutputFormatter.ts"
7
- import { LanguageModel, Prompt } from "effect/unstable/ai"
8
- import * as Model from "effect/unstable/ai/Model"
9
- import { Executor } from "./Executor.ts"
10
- import { ToolkitRenderer } from "./ToolkitRenderer.ts"
11
- import { AgentToolHandlersTest } from "./AgentTools.ts"
12
-
13
- const usage = {
14
- inputTokens: {
15
- uncached: undefined,
16
- total: undefined,
17
- cacheRead: undefined,
18
- cacheWrite: undefined,
19
- },
20
- outputTokens: {
21
- total: undefined,
22
- text: undefined,
23
- reasoning: undefined,
24
- },
25
- }
26
-
27
- const promptText = (prompt: Prompt.Prompt) =>
28
- prompt.content
29
- .flatMap((message) => {
30
- if (typeof message.content === "string") {
31
- return [message.content]
32
- }
33
- return message.content.flatMap((part) => {
34
- switch (part.type) {
35
- case "text":
36
- case "reasoning":
37
- return [part.text]
38
-
39
- default:
40
- return []
41
- }
42
- })
43
- })
44
- .join("\n")
45
-
46
- const scriptResponse = (script: string) =>
47
- Stream.fromIterable([
48
- { type: "text-start", id: "script" } as const,
49
- { type: "text-delta", id: "script", delta: script } as const,
50
- { type: "text-end", id: "script" } as const,
51
- {
52
- type: "finish",
53
- reason: "stop",
54
- usage,
55
- response: undefined,
56
- } as const,
57
- ])
58
-
59
- const TestModel = Model.make(
60
- "test-provider",
61
- "test-model",
62
- Layer.effect(
63
- LanguageModel.LanguageModel,
64
- LanguageModel.make({
65
- generateText: () => Effect.succeed([]),
66
- streamText: ({ prompt }) => {
67
- const text = promptText(prompt)
68
-
69
- if (text.includes("grandchild task")) {
70
- return scriptResponse(
71
- [
72
- 'console.log("grandchild output")',
73
- 'await taskComplete("grandchild summary")',
74
- ].join("\n"),
75
- )
76
- }
77
-
78
- if (text.includes("child task")) {
79
- return scriptResponse(
80
- [
81
- 'const result = await delegate("grandchild task")',
82
- "await taskComplete(`child summary: ${result}`)",
83
- ].join("\n"),
84
- )
85
- }
86
-
87
- return scriptResponse(
88
- [
89
- 'const result = await delegate("child task")',
90
- "await taskComplete(`root summary: ${result}`)",
91
- ].join("\n"),
92
- )
93
- },
94
- }),
95
- ),
96
- )
97
-
98
- describe("Agent", () => {
99
- it.effect("forwards nested subagent output", () =>
100
- Effect.gen(function* () {
101
- const seen = [] as Array<string>
102
- const agent = yield* make({
103
- directory: process.cwd(),
104
- prompt: "root task",
105
- })
106
-
107
- const output = yield* agent.output.pipe(
108
- Stream.tap((part) =>
109
- Effect.sync(() => {
110
- switch (part._tag) {
111
- case "SubagentStart":
112
- case "SubagentComplete":
113
- seen.push(`${part._tag}:${part.id}`)
114
- break
115
-
116
- case "SubagentPart":
117
- seen.push(`${part._tag}:${part.id}:${part.part._tag}`)
118
- break
119
-
120
- default:
121
- seen.push(part._tag)
122
- break
123
- }
124
- }),
125
- ),
126
- pretty,
127
- Stream.mkString,
128
- )
129
-
130
- expect(seen).toContain("SubagentStart:1")
131
- expect(seen).toContain("SubagentStart:2")
132
- expect(seen).toContain("SubagentPart:2:ScriptStart")
133
- expect(seen).toContain("SubagentPart:2:ScriptOutput")
134
- expect(seen).toContain("SubagentComplete:2")
135
- expect(seen).toContain("SubagentComplete:1")
136
-
137
- expect(output).toContain("Subagent #1 starting")
138
- expect(output).toContain("Subagent #2 starting")
139
- expect(output).toContain("grandchild output")
140
- expect(output).toContain("Subagent #2 complete")
141
- expect(output).toContain("Task complete:")
142
- expect(output).toContain(
143
- "root summary: child summary: grandchild summary",
144
- )
145
- }).pipe(
146
- Effect.provide(
147
- Layer.mergeAll(
148
- AgentToolHandlersTest,
149
- TestModel,
150
- AgentModelConfig.layer({
151
- supportsNoTools: true,
152
- }),
153
- Executor.layer,
154
- ToolkitRenderer.layer,
155
- ).pipe(Layer.provideMerge(NodeServices.layer)),
156
- ),
157
- ),
158
- )
159
- })
package/src/Executor.ts DELETED
@@ -1,151 +0,0 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import {
5
- Cause,
6
- Console,
7
- Effect,
8
- Exit,
9
- Fiber,
10
- Layer,
11
- Queue,
12
- Scope,
13
- ServiceMap,
14
- Stream,
15
- } from "effect"
16
- import { Tool, Toolkit } from "effect/unstable/ai"
17
- import * as NodeConsole from "node:console"
18
- import * as NodeVm from "node:vm"
19
- import { Writable } from "node:stream"
20
-
21
- /**
22
- * @since 1.0.0
23
- * @category Services
24
- */
25
- export class Executor extends ServiceMap.Service<
26
- Executor,
27
- {
28
- execute<Tools extends Record<string, Tool.Any>>(options: {
29
- readonly tools: Toolkit.WithHandler<Tools>
30
- readonly script: string
31
- }): Stream.Stream<string, never, Tool.HandlerServices<Tools[keyof Tools]>>
32
- }
33
- >()("clanka/Executor") {
34
- static readonly layer = Layer.effect(
35
- Executor,
36
- // oxlint-disable-next-line require-yield
37
- Effect.gen(function* () {
38
- const execute = Effect.fnUntraced(function* <
39
- Tools extends Record<string, Tool.Any>,
40
- >(options: {
41
- readonly tools: Toolkit.WithHandler<Tools>
42
- readonly script: string
43
- }) {
44
- const output = yield* Queue.unbounded<string, Cause.Done>()
45
- const console = yield* makeConsole(output)
46
- const handlerScope = Scope.makeUnsafe("parallel")
47
- const trackFiber = Fiber.runIn(handlerScope)
48
-
49
- yield* Effect.gen(function* () {
50
- const console = yield* Console.Console
51
- const services = yield* Effect.services()
52
- let running = 0
53
-
54
- const script = new NodeVm.Script(`async function main() {
55
- ${options.script}
56
- }`)
57
- const sandbox: ScriptSandbox = {
58
- main: defaultMain,
59
- console,
60
- fetch,
61
- process: undefined,
62
- }
63
-
64
- for (const [name, tool] of Object.entries(options.tools.tools)) {
65
- const handler = services.mapUnsafe.get(
66
- tool.id,
67
- ) as Tool.Handler<string>
68
-
69
- const handlerServices = ServiceMap.merge(services, handler.services)
70
- const runFork = Effect.runForkWith(handlerServices)
71
-
72
- // oxlint-disable-next-line typescript/no-explicit-any
73
- sandbox[name] = function (params: any) {
74
- running++
75
- const fiber = trackFiber(runFork(handler.handler(params, {})))
76
- return new Promise((resolve, reject) => {
77
- fiber.addObserver((exit) => {
78
- running--
79
- if (exit._tag === "Success") {
80
- resolve(exit.value)
81
- } else {
82
- if (Cause.hasInterruptsOnly(exit.cause)) return
83
- reject(Cause.squash(exit.cause))
84
- }
85
- })
86
- })
87
- }
88
- }
89
-
90
- script.runInNewContext(sandbox, {
91
- timeout: 1000,
92
- })
93
- yield* Effect.promise(sandbox.main)
94
- while (true) {
95
- yield* Effect.yieldNow
96
- if (running === 0) break
97
- }
98
- }).pipe(
99
- Effect.ensuring(Scope.close(handlerScope, Exit.void)),
100
- Effect.catchCause(Effect.logFatal),
101
- Effect.provideService(Console.Console, console),
102
- Effect.ensuring(Queue.end(output)),
103
- Effect.forkScoped,
104
- )
105
-
106
- return Stream.fromQueue(output)
107
- }, Stream.unwrap)
108
-
109
- return Executor.of({
110
- execute,
111
- })
112
- }),
113
- )
114
- }
115
-
116
- interface ScriptSandbox {
117
- main: () => Promise<void>
118
- console: Console.Console
119
- [toolName: string]: unknown
120
- }
121
-
122
- const defaultMain = () => Promise.resolve()
123
-
124
- const makeConsole = Effect.fn(function* (
125
- queue: Queue.Queue<string, Cause.Done>,
126
- ) {
127
- const writable = new QueueWriteStream(queue)
128
- const newConsole = new NodeConsole.Console(writable)
129
- yield* Effect.addFinalizer(() => {
130
- writable.end()
131
- return Effect.void
132
- })
133
- return newConsole
134
- })
135
-
136
- class QueueWriteStream extends Writable {
137
- readonly queue: Queue.Enqueue<string, Cause.Done>
138
- constructor(queue: Queue.Enqueue<string, Cause.Done>) {
139
- super()
140
- this.queue = queue
141
- }
142
- _write(
143
- // oxlint-disable-next-line typescript/no-explicit-any
144
- chunk: any,
145
- _encoding: BufferEncoding,
146
- callback: (error?: Error | null) => void,
147
- ): void {
148
- Queue.offerUnsafe(this.queue, chunk.toString())
149
- callback()
150
- }
151
- }