clanka 0.2.72 → 0.3.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/Acp.d.ts +88 -0
- package/dist/Acp.d.ts.map +1 -0
- package/dist/Acp.js +387 -0
- package/dist/Acp.js.map +1 -0
- package/dist/Acp.test.d.ts +2 -0
- package/dist/Acp.test.d.ts.map +1 -0
- package/dist/Acp.test.js +179 -0
- package/dist/Acp.test.js.map +1 -0
- package/dist/DeviceCodeHandler.d.ts +2 -1
- package/dist/DeviceCodeHandler.d.ts.map +1 -1
- package/dist/DeviceCodeHandler.js +4 -0
- package/dist/DeviceCodeHandler.js.map +1 -1
- package/dist/cli.js +33 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/Acp.test.ts +288 -0
- package/src/Acp.ts +596 -0
- package/src/DeviceCodeHandler.ts +8 -1
- package/src/cli.ts +90 -36
- package/src/index.ts +5 -0
package/src/cli.ts
CHANGED
|
@@ -7,6 +7,8 @@ import * as Flag from "effect/unstable/cli/Flag"
|
|
|
7
7
|
import * as NodeServices from "@effect/platform-node/NodeServices"
|
|
8
8
|
import * as NodeRuntime from "@effect/platform-node/NodeRuntime"
|
|
9
9
|
import * as NodeSocket from "@effect/platform-node/NodeSocket"
|
|
10
|
+
import * as Acp from "./Acp.ts"
|
|
11
|
+
import * as AgentExecutor from "./AgentExecutor.ts"
|
|
10
12
|
import * as Codex from "./Codex.ts"
|
|
11
13
|
import * as Copilot from "./Copilot.ts"
|
|
12
14
|
import * as Agent from "./Agent.ts"
|
|
@@ -15,14 +17,62 @@ import * as OutputFormatter from "./OutputFormatter.ts"
|
|
|
15
17
|
import * as Stdio from "effect/Stdio"
|
|
16
18
|
import { pipe } from "effect/Function"
|
|
17
19
|
import * as Layer from "effect/Layer"
|
|
20
|
+
import * as Logger from "effect/Logger"
|
|
18
21
|
import * as Path from "effect/Path"
|
|
22
|
+
import * as Schema from "effect/Schema"
|
|
23
|
+
import type * as LanguageModel from "effect/unstable/ai/LanguageModel"
|
|
24
|
+
import type * as Model from "effect/unstable/ai/Model"
|
|
19
25
|
import * as Config from "effect/Config"
|
|
20
26
|
import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore"
|
|
21
27
|
import * as Option from "effect/Option"
|
|
22
28
|
import { OpenAiClient, OpenAiEmbeddingModel } from "@effect/ai-openai"
|
|
23
29
|
import { DeviceCodeHandler } from "./index.ts"
|
|
24
30
|
|
|
25
|
-
const
|
|
31
|
+
const version = "0.0.1"
|
|
32
|
+
|
|
33
|
+
type Provider = "openai" | "copilot"
|
|
34
|
+
|
|
35
|
+
const providers: ReadonlyArray<Provider> = ["openai", "copilot"]
|
|
36
|
+
|
|
37
|
+
const withSubagentModel = <E, R>(
|
|
38
|
+
model: Layer.Layer<
|
|
39
|
+
LanguageModel.LanguageModel | Model.ProviderName | Model.ModelName,
|
|
40
|
+
E,
|
|
41
|
+
R
|
|
42
|
+
>,
|
|
43
|
+
) => Layer.merge(model, Agent.layerSubagentModel(model))
|
|
44
|
+
|
|
45
|
+
const modelLayer = (provider: Provider, model: string, effort: string) =>
|
|
46
|
+
provider === "openai"
|
|
47
|
+
? withSubagentModel(
|
|
48
|
+
Codex.modelWebSocket(model, { reasoning: { effort: effort as any } }),
|
|
49
|
+
).pipe(Layer.provide(Codex.layerClient))
|
|
50
|
+
: withSubagentModel(Copilot.model(model, { reasoning: { effort } })).pipe(
|
|
51
|
+
Layer.provide(Copilot.layerClient),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
const parseModelId = (modelId: string) => {
|
|
55
|
+
const [provider, model, effort, ...rest] = modelId.split("/")
|
|
56
|
+
return provider !== undefined &&
|
|
57
|
+
providers.includes(provider as Provider) &&
|
|
58
|
+
model !== undefined &&
|
|
59
|
+
effort !== undefined &&
|
|
60
|
+
rest.length === 0
|
|
61
|
+
? Option.some({ provider: provider as Provider, model, effort })
|
|
62
|
+
: Option.none()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const ModelId = Schema.String.pipe(
|
|
66
|
+
Schema.check(
|
|
67
|
+
Schema.makeFilter(
|
|
68
|
+
(modelId: string) =>
|
|
69
|
+
Option.isSome(parseModelId(modelId)) ||
|
|
70
|
+
`Invalid model "${modelId}", expected <provider>/<model>/<effort>`,
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
const provider = Flag.Literals("provider", providers).pipe(
|
|
26
76
|
Flag.withAlias("p"),
|
|
27
77
|
Flag.withFallbackPrompt(
|
|
28
78
|
Prompt.Select({
|
|
@@ -123,6 +173,42 @@ const Search = (directory: string) =>
|
|
|
123
173
|
}),
|
|
124
174
|
).pipe(Layer.provide([NodeServices.layer, NodeHttpClient.layerUndici]))
|
|
125
175
|
|
|
176
|
+
const acpModel = Flag.String("model").pipe(
|
|
177
|
+
Flag.withAlias("m"),
|
|
178
|
+
Flag.withDescription(
|
|
179
|
+
"Default model as <provider>/<model>/<effort>, e.g. openai/gpt-6-astra/medium",
|
|
180
|
+
),
|
|
181
|
+
Flag.withSchema(ModelId),
|
|
182
|
+
Flag.withDefault("openai/gpt-6-astra/medium"),
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
const acp = Command.make("acp", { model: acpModel }).pipe(
|
|
186
|
+
Command.withDescription(
|
|
187
|
+
"Run as an Agent Client Protocol (ACP) server over stdio",
|
|
188
|
+
),
|
|
189
|
+
Command.withHandler(({ model }) =>
|
|
190
|
+
Acp.runStdio({
|
|
191
|
+
version,
|
|
192
|
+
defaultModel: model,
|
|
193
|
+
makeAgent: (cwd) =>
|
|
194
|
+
Agent.make.pipe(
|
|
195
|
+
Effect.provide(AgentExecutor.layerLocal({ directory: cwd })),
|
|
196
|
+
),
|
|
197
|
+
makeModel: (modelId) =>
|
|
198
|
+
Option.map(parseModelId(modelId), ({ provider, model, effort }) =>
|
|
199
|
+
modelLayer(provider, model, effort),
|
|
200
|
+
),
|
|
201
|
+
}),
|
|
202
|
+
),
|
|
203
|
+
Command.provide(
|
|
204
|
+
Layer.mergeAll(
|
|
205
|
+
Agent.ConversationMode.layer(true),
|
|
206
|
+
Layer.succeed(Logger.LogToStderr, true),
|
|
207
|
+
DeviceCodeHandler.layerLog,
|
|
208
|
+
),
|
|
209
|
+
),
|
|
210
|
+
)
|
|
211
|
+
|
|
126
212
|
Command.make("clanka", { provider, model, semantic, prompt }).pipe(
|
|
127
213
|
Command.withHandler(
|
|
128
214
|
Effect.fnUntraced(function* ({
|
|
@@ -133,40 +219,7 @@ Command.make("clanka", { provider, model, semantic, prompt }).pipe(
|
|
|
133
219
|
}) {
|
|
134
220
|
const stdio = yield* Stdio.Stdio
|
|
135
221
|
const [model, reasoning] = modelRaw.split("/") as [string, string]
|
|
136
|
-
const Model =
|
|
137
|
-
provider === "openai"
|
|
138
|
-
? Codex.modelWebSocket(model, {
|
|
139
|
-
reasoning: {
|
|
140
|
-
effort: reasoning as any,
|
|
141
|
-
},
|
|
142
|
-
}).pipe(
|
|
143
|
-
Layer.merge(
|
|
144
|
-
Agent.layerSubagentModel(
|
|
145
|
-
Codex.modelWebSocket(model, {
|
|
146
|
-
reasoning: {
|
|
147
|
-
effort: reasoning as any,
|
|
148
|
-
},
|
|
149
|
-
}),
|
|
150
|
-
),
|
|
151
|
-
),
|
|
152
|
-
Layer.provide(Codex.layerClient),
|
|
153
|
-
)
|
|
154
|
-
: Copilot.model(model, {
|
|
155
|
-
reasoning: {
|
|
156
|
-
effort: reasoning,
|
|
157
|
-
},
|
|
158
|
-
}).pipe(
|
|
159
|
-
Layer.merge(
|
|
160
|
-
Agent.layerSubagentModel(
|
|
161
|
-
Copilot.model(model, {
|
|
162
|
-
reasoning: {
|
|
163
|
-
effort: reasoning,
|
|
164
|
-
},
|
|
165
|
-
}),
|
|
166
|
-
),
|
|
167
|
-
),
|
|
168
|
-
Layer.provide(Copilot.layerClient),
|
|
169
|
-
)
|
|
222
|
+
const Model = modelLayer(provider, model, reasoning)
|
|
170
223
|
|
|
171
224
|
return yield* Effect.gen(function* () {
|
|
172
225
|
const agent = yield* Agent.Agent
|
|
@@ -214,8 +267,9 @@ Command.make("clanka", { provider, model, semantic, prompt }).pipe(
|
|
|
214
267
|
Command.provide(({ prompt }) =>
|
|
215
268
|
Agent.ConversationMode.layer(Option.isNone(prompt)),
|
|
216
269
|
),
|
|
270
|
+
Command.withSubcommands([acp]),
|
|
217
271
|
Command.run({
|
|
218
|
-
version
|
|
272
|
+
version,
|
|
219
273
|
}),
|
|
220
274
|
Effect.provide([
|
|
221
275
|
NodeServices.layer,
|