clanka 0.7.6 → 0.8.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 +21 -2
- package/dist/Acp.d.ts.map +1 -1
- package/dist/Acp.js +68 -13
- package/dist/Acp.js.map +1 -1
- package/dist/Acp.test.js +118 -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 +10 -0
- package/dist/Agent.js.map +1 -1
- package/dist/Agent.test.js +47 -2
- package/dist/Agent.test.js.map +1 -1
- package/dist/AgentOutput.d.ts +8 -0
- package/dist/AgentOutput.d.ts.map +1 -1
- package/dist/AgentOutput.js +8 -0
- package/dist/AgentOutput.js.map +1 -1
- package/dist/AgentTools.d.ts.map +1 -1
- package/dist/AgentTools.js +22 -7
- 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-0f-vTQC-.mjs → McpClient-zQibhsnA.mjs} +3 -3
- package/dist/bin/{McpClient-0f-vTQC-.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-gTtf66A-.mjs → Schema-Bc06DxcV.mjs} +2 -2
- package/dist/bin/{Schema-gTtf66A-.mjs.map → Schema-Bc06DxcV.mjs.map} +1 -1
- package/dist/bin/{SemanticSearch-CBs6yELV.mjs → SemanticSearch-BPxQoRSC.mjs} +4 -4
- package/dist/bin/{SemanticSearch-CBs6yELV.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 +107 -40
- 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 +188 -9
- package/src/Acp.ts +92 -17
- package/src/AcpImage.test.ts +1 -0
- package/src/Agent.test.ts +54 -2
- package/src/Agent.ts +10 -0
- package/src/AgentOutput.ts +8 -0
- package/src/AgentTools.test.ts +116 -0
- package/src/AgentTools.ts +32 -12
- package/src/cli.ts +22 -9
- package/dist/bin/Effect-DdkIoNCD.mjs.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -39,18 +39,26 @@ const modelLayer = (provider, model, effort) => provider === "openai"
|
|
|
39
39
|
: provider === "xai"
|
|
40
40
|
? withSubagentModel(Xai.model(model, { reasoning: { effort: effort } })).pipe(Layer.provide(Xai.layerClient))
|
|
41
41
|
: withSubagentModel(Copilot.model(model, { reasoning: { effort } })).pipe(Layer.provide(Copilot.layerClient));
|
|
42
|
+
const isProvider = (provider) => providers.includes(provider);
|
|
43
|
+
// `<provider>/<model>/<effort>` as accepted by the `acp` --model flag.
|
|
42
44
|
const parseModelId = (modelId) => {
|
|
43
45
|
const [provider, model, effort, ...rest] = modelId.split("/");
|
|
44
|
-
return provider
|
|
45
|
-
providers.includes(provider) &&
|
|
46
|
+
return isProvider(provider) &&
|
|
46
47
|
model !== undefined &&
|
|
47
|
-
effort
|
|
48
|
+
Schema.is(Acp.ThoughtLevel)(effort) &&
|
|
48
49
|
rest.length === 0
|
|
49
|
-
? Option.some({
|
|
50
|
+
? Option.some({ model: `${provider}:${model}`, thoughtLevel: effort })
|
|
51
|
+
: Option.none();
|
|
52
|
+
};
|
|
53
|
+
// `<provider>:<model>` as advertised over ACP.
|
|
54
|
+
const parseAcpModelId = (modelId) => {
|
|
55
|
+
const [provider, model, ...rest] = modelId.split(":");
|
|
56
|
+
return isProvider(provider) && model !== undefined && rest.length === 0
|
|
57
|
+
? Option.some({ provider, model })
|
|
50
58
|
: Option.none();
|
|
51
59
|
};
|
|
52
60
|
const ModelId = Schema.String.pipe(Schema.check(Schema.makeFilter((modelId) => Option.isSome(parseModelId(modelId)) ||
|
|
53
|
-
`Invalid model "${modelId}", expected <provider>/<model>/<effort
|
|
61
|
+
`Invalid model "${modelId}", expected <provider>/<model>/<effort> with effort one of ${Acp.ThoughtLevel.literals.join(", ")}`)));
|
|
54
62
|
const provider = Flag.Literals("provider", providers).pipe(Flag.withAlias("p"), Flag.withFallbackPrompt(Prompt.Select({
|
|
55
63
|
message: "Select a provider",
|
|
56
64
|
choices: [
|
|
@@ -96,12 +104,13 @@ const Search = (directory) => Layer.unwrap(Effect.gen(function* () {
|
|
|
96
104
|
apiKey: apiKey.value,
|
|
97
105
|
})));
|
|
98
106
|
})).pipe(Layer.provide([NodeServices.layer, HttpClientLive]));
|
|
99
|
-
const acpModel = Flag.String("model").pipe(Flag.withAlias("m"), Flag.withDescription("Default model as <provider>/<model>/<effort>, e.g. openai/gpt-6-astra/medium"), Flag.withSchema(ModelId), Flag.withDefault("openai/gpt-6-astra/medium"));
|
|
107
|
+
const acpModel = Flag.String("model").pipe(Flag.withAlias("m"), Flag.withDescription("Default model as <provider>/<model>/<effort>, e.g. openai/gpt-6-astra/medium"), Flag.withSchema(ModelId), Flag.withDefault("openai/gpt-6-astra/medium"), Flag.map((modelId) => Option.getOrThrow(parseModelId(modelId))));
|
|
100
108
|
const acp = Command.make("acp", { model: acpModel, compaction }).pipe(Command.withDescription("Run as an Agent Client Protocol (ACP) server over stdio"), Command.withHandler(({ model }) => Acp.runStdio({
|
|
101
109
|
version,
|
|
102
|
-
defaultModel: model,
|
|
110
|
+
defaultModel: model.model,
|
|
111
|
+
defaultThoughtLevel: model.thoughtLevel,
|
|
103
112
|
makeAgent: (cwd) => Agent.make.pipe(Effect.provide(AgentExecutor.layerLocal({ directory: cwd }))),
|
|
104
|
-
makeModel: (modelId) => Option.map(
|
|
113
|
+
makeModel: (modelId, thoughtLevel) => Option.map(parseAcpModelId(modelId), ({ provider, model }) => modelLayer(provider, model, thoughtLevel)),
|
|
105
114
|
})), Command.provide(({ compaction }) => Layer.mergeAll(Agent.ConversationMode.layer(true), Layer.succeed(Logger.LogToStderr, true), DeviceCodeHandler.layerLog, Compaction.CompactionConfig.layer({ enabled: compaction }))));
|
|
106
115
|
Command.make("clanka", {
|
|
107
116
|
provider,
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/Acp.test.ts
CHANGED
|
@@ -38,6 +38,7 @@ const executor = AgentExecutor.AgentExecutor.of({
|
|
|
38
38
|
const makeServer = (
|
|
39
39
|
streamText: Parameters<typeof LanguageModel.make>[0]["streamText"],
|
|
40
40
|
agentExecutor = executor,
|
|
41
|
+
onMakeModel?: (modelId: string, thoughtLevel: string) => void,
|
|
41
42
|
) =>
|
|
42
43
|
Effect.gen(function* () {
|
|
43
44
|
const sent: Array<Message> = []
|
|
@@ -52,7 +53,8 @@ const makeServer = (
|
|
|
52
53
|
)
|
|
53
54
|
const server = yield* Acp.make({
|
|
54
55
|
version: "test",
|
|
55
|
-
defaultModel: "test
|
|
56
|
+
defaultModel: "test:model",
|
|
57
|
+
defaultThoughtLevel: "medium",
|
|
56
58
|
send: (message) =>
|
|
57
59
|
Effect.sync(() => {
|
|
58
60
|
sent.push(message as Message)
|
|
@@ -61,12 +63,14 @@ const makeServer = (
|
|
|
61
63
|
Agent.make.pipe(
|
|
62
64
|
Effect.provideService(AgentExecutor.AgentExecutor, agentExecutor),
|
|
63
65
|
),
|
|
64
|
-
makeModel: (modelId) =>
|
|
65
|
-
modelId
|
|
66
|
+
makeModel: (modelId, thoughtLevel) => {
|
|
67
|
+
onMakeModel?.(modelId, thoughtLevel)
|
|
68
|
+
return modelId === "test:model" || modelId === "other:model"
|
|
66
69
|
? Option.some(
|
|
67
70
|
Layer.merge(modelLayer, Agent.layerSubagentModel(modelLayer)),
|
|
68
71
|
)
|
|
69
|
-
: Option.none()
|
|
72
|
+
: Option.none()
|
|
73
|
+
},
|
|
70
74
|
})
|
|
71
75
|
const request = (id: number, method: string, params?: unknown) =>
|
|
72
76
|
server
|
|
@@ -123,7 +127,7 @@ describe("Acp", () => {
|
|
|
123
127
|
mcpServers: [],
|
|
124
128
|
})
|
|
125
129
|
const sessionId: string = created.result.sessionId
|
|
126
|
-
assert.strictEqual(created.result.models.currentModelId, "test
|
|
130
|
+
assert.strictEqual(created.result.models.currentModelId, "test:model")
|
|
127
131
|
|
|
128
132
|
const done = yield* server.request(3, "session/prompt", {
|
|
129
133
|
sessionId,
|
|
@@ -150,6 +154,156 @@ describe("Acp", () => {
|
|
|
150
154
|
),
|
|
151
155
|
)
|
|
152
156
|
|
|
157
|
+
it.effect("reports cache usage in the ACP usage extension", () =>
|
|
158
|
+
withStore(
|
|
159
|
+
Effect.scoped(
|
|
160
|
+
Effect.gen(function* () {
|
|
161
|
+
const server = yield* makeServer(() =>
|
|
162
|
+
parts(
|
|
163
|
+
{ type: "text-start", id: "1" },
|
|
164
|
+
{ type: "text-delta", id: "1", delta: "done" },
|
|
165
|
+
{ type: "text-end", id: "1" },
|
|
166
|
+
{
|
|
167
|
+
type: "finish",
|
|
168
|
+
reason: "stop",
|
|
169
|
+
usage: {
|
|
170
|
+
inputTokens: {
|
|
171
|
+
total: 120,
|
|
172
|
+
cacheRead: 30,
|
|
173
|
+
cacheWrite: 6,
|
|
174
|
+
},
|
|
175
|
+
outputTokens: { total: 12 },
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
const created = yield* server.request(1, "session/new", {
|
|
181
|
+
cwd: "/tmp",
|
|
182
|
+
})
|
|
183
|
+
const sessionId: string = created.result.sessionId
|
|
184
|
+
|
|
185
|
+
yield* server.request(2, "session/prompt", {
|
|
186
|
+
sessionId,
|
|
187
|
+
prompt: [{ type: "text", text: "hello" }],
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
assert.deepStrictEqual(
|
|
191
|
+
server
|
|
192
|
+
.updates(sessionId)
|
|
193
|
+
.find((update) => update.sessionUpdate === "usage_update"),
|
|
194
|
+
{
|
|
195
|
+
sessionUpdate: "usage_update",
|
|
196
|
+
usage: {
|
|
197
|
+
inputTokens: 120,
|
|
198
|
+
outputTokens: 12,
|
|
199
|
+
cacheRead: 30,
|
|
200
|
+
cacheWrite: 6,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
)
|
|
204
|
+
}),
|
|
205
|
+
),
|
|
206
|
+
),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
it.effect(
|
|
210
|
+
"reports zero cache usage when the provider omits cache fields",
|
|
211
|
+
() =>
|
|
212
|
+
withStore(
|
|
213
|
+
Effect.scoped(
|
|
214
|
+
Effect.gen(function* () {
|
|
215
|
+
const server = yield* makeServer(() =>
|
|
216
|
+
parts(
|
|
217
|
+
{ type: "text-start", id: "1" },
|
|
218
|
+
{ type: "text-delta", id: "1", delta: "done" },
|
|
219
|
+
{ type: "text-end", id: "1" },
|
|
220
|
+
{
|
|
221
|
+
type: "finish",
|
|
222
|
+
reason: "stop",
|
|
223
|
+
usage: {
|
|
224
|
+
inputTokens: { total: 120 },
|
|
225
|
+
outputTokens: { total: 12 },
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
),
|
|
229
|
+
)
|
|
230
|
+
const created = yield* server.request(1, "session/new", {
|
|
231
|
+
cwd: "/tmp",
|
|
232
|
+
})
|
|
233
|
+
const sessionId: string = created.result.sessionId
|
|
234
|
+
|
|
235
|
+
yield* server.request(2, "session/prompt", {
|
|
236
|
+
sessionId,
|
|
237
|
+
prompt: [{ type: "text", text: "hello" }],
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
assert.deepStrictEqual(
|
|
241
|
+
server
|
|
242
|
+
.updates(sessionId)
|
|
243
|
+
.find((update) => update.sessionUpdate === "usage_update"),
|
|
244
|
+
{
|
|
245
|
+
sessionUpdate: "usage_update",
|
|
246
|
+
usage: {
|
|
247
|
+
inputTokens: 120,
|
|
248
|
+
outputTokens: 12,
|
|
249
|
+
cacheRead: 0,
|
|
250
|
+
cacheWrite: 0,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
)
|
|
254
|
+
}),
|
|
255
|
+
),
|
|
256
|
+
),
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
it.effect("applies model and thought-level changes to the next turn", () =>
|
|
260
|
+
withStore(
|
|
261
|
+
Effect.scoped(
|
|
262
|
+
Effect.gen(function* () {
|
|
263
|
+
const resolved: Array<[string, string]> = []
|
|
264
|
+
const server = yield* makeServer(
|
|
265
|
+
() => assistantSays("done"),
|
|
266
|
+
executor,
|
|
267
|
+
(modelId, thoughtLevel) => resolved.push([modelId, thoughtLevel]),
|
|
268
|
+
)
|
|
269
|
+
const created = yield* server.request(1, "session/new", {
|
|
270
|
+
cwd: "/tmp",
|
|
271
|
+
})
|
|
272
|
+
const sessionId: string = created.result.sessionId
|
|
273
|
+
|
|
274
|
+
yield* server.request(2, "session/set_model", {
|
|
275
|
+
sessionId,
|
|
276
|
+
modelId: "other:model",
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
const configured = yield* server.request(
|
|
280
|
+
3,
|
|
281
|
+
"session/set_config_option",
|
|
282
|
+
{ sessionId, configId: "thought_level", value: "high" },
|
|
283
|
+
)
|
|
284
|
+
assert.strictEqual(
|
|
285
|
+
configured.result.configOptions[0].currentValue,
|
|
286
|
+
"high",
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
const rejected = yield* server.request(
|
|
290
|
+
4,
|
|
291
|
+
"session/set_config_option",
|
|
292
|
+
{ sessionId, configId: "thought_level", value: "turbo" },
|
|
293
|
+
)
|
|
294
|
+
assert.strictEqual(rejected.error?.code, -32602)
|
|
295
|
+
|
|
296
|
+
resolved.length = 0
|
|
297
|
+
yield* server.request(5, "session/prompt", {
|
|
298
|
+
sessionId,
|
|
299
|
+
prompt: [{ type: "text", text: "use the selected model" }],
|
|
300
|
+
})
|
|
301
|
+
assert.deepStrictEqual(resolved, [["other:model", "high"]])
|
|
302
|
+
}),
|
|
303
|
+
),
|
|
304
|
+
),
|
|
305
|
+
)
|
|
306
|
+
|
|
153
307
|
for (const script of [
|
|
154
308
|
"console.log(1)",
|
|
155
309
|
'console.log("' + "x".repeat(200) + '")',
|
|
@@ -313,7 +467,7 @@ describe("Acp", () => {
|
|
|
313
467
|
),
|
|
314
468
|
)
|
|
315
469
|
|
|
316
|
-
it.effect("
|
|
470
|
+
it.effect("reports canonical state for new and loaded sessions", () =>
|
|
317
471
|
withStore(
|
|
318
472
|
Effect.gen(function* () {
|
|
319
473
|
const sessionId = yield* Effect.scoped(
|
|
@@ -322,7 +476,27 @@ describe("Acp", () => {
|
|
|
322
476
|
const created = yield* server.request(1, "session/new", {
|
|
323
477
|
cwd: "/tmp",
|
|
324
478
|
})
|
|
325
|
-
|
|
479
|
+
assert.deepStrictEqual(created.result.models, {
|
|
480
|
+
availableModels: [{ modelId: "test:model", name: "test:model" }],
|
|
481
|
+
currentModelId: "test:model",
|
|
482
|
+
})
|
|
483
|
+
assert.deepInclude(created.result.configOptions[0], {
|
|
484
|
+
id: "thought_level",
|
|
485
|
+
currentValue: "medium",
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
const legacy = yield* server.request(2, "session/new", {
|
|
489
|
+
cwd: "/tmp",
|
|
490
|
+
model: "test/model/high",
|
|
491
|
+
})
|
|
492
|
+
assert.strictEqual(legacy.error?.code, -32602)
|
|
493
|
+
|
|
494
|
+
yield* server.request(3, "session/set_config_option", {
|
|
495
|
+
sessionId: created.result.sessionId,
|
|
496
|
+
configId: "thought_level",
|
|
497
|
+
value: "high",
|
|
498
|
+
})
|
|
499
|
+
yield* server.request(4, "session/prompt", {
|
|
326
500
|
sessionId: created.result.sessionId,
|
|
327
501
|
prompt: [{ type: "text", text: "hello" }],
|
|
328
502
|
})
|
|
@@ -340,7 +514,11 @@ describe("Acp", () => {
|
|
|
340
514
|
})
|
|
341
515
|
assert.strictEqual(
|
|
342
516
|
loaded.result.models.currentModelId,
|
|
343
|
-
"test
|
|
517
|
+
"test:model",
|
|
518
|
+
)
|
|
519
|
+
assert.strictEqual(
|
|
520
|
+
loaded.result.configOptions[0].currentValue,
|
|
521
|
+
"high",
|
|
344
522
|
)
|
|
345
523
|
assert.deepStrictEqual(
|
|
346
524
|
server.updates(sessionId).map((u) => u.sessionUpdate),
|
|
@@ -393,7 +571,8 @@ describe("Acp", () => {
|
|
|
393
571
|
sessionId,
|
|
394
572
|
new Acp.SessionRecord({
|
|
395
573
|
cwd: "/tmp",
|
|
396
|
-
model: "test
|
|
574
|
+
model: "test:model",
|
|
575
|
+
thoughtLevel: "medium",
|
|
397
576
|
history,
|
|
398
577
|
}),
|
|
399
578
|
)
|
package/src/Acp.ts
CHANGED
|
@@ -55,6 +55,10 @@ export interface Options<RAgent, RModel> {
|
|
|
55
55
|
* the server and resolved with `makeModel`.
|
|
56
56
|
*/
|
|
57
57
|
readonly defaultModel: string
|
|
58
|
+
/**
|
|
59
|
+
* Thought level used for new sessions.
|
|
60
|
+
*/
|
|
61
|
+
readonly defaultThoughtLevel: ThoughtLevel
|
|
58
62
|
/**
|
|
59
63
|
* Write one JSON-RPC message to the client.
|
|
60
64
|
*/
|
|
@@ -66,10 +70,12 @@ export interface Options<RAgent, RModel> {
|
|
|
66
70
|
cwd: string,
|
|
67
71
|
) => Effect.Effect<Agent.Agent, never, Scope.Scope | RAgent>
|
|
68
72
|
/**
|
|
69
|
-
* Resolve a model id to the services an Agent needs.
|
|
73
|
+
* Resolve a model id and thought level to the services an Agent needs.
|
|
74
|
+
* `None` rejects the combination.
|
|
70
75
|
*/
|
|
71
76
|
readonly makeModel: (
|
|
72
77
|
modelId: string,
|
|
78
|
+
thoughtLevel: ThoughtLevel,
|
|
73
79
|
) => Option.Option<Layer.Layer<ModelServices, never, RModel>>
|
|
74
80
|
}
|
|
75
81
|
|
|
@@ -85,6 +91,29 @@ export interface Server<R = never> {
|
|
|
85
91
|
readonly handle: (line: string) => Effect.Effect<void, never, R>
|
|
86
92
|
}
|
|
87
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Reasoning effort levels offered through the ACP `thought_level` config
|
|
96
|
+
* option.
|
|
97
|
+
*
|
|
98
|
+
* @since 1.0.0
|
|
99
|
+
* @category Models
|
|
100
|
+
*/
|
|
101
|
+
export const ThoughtLevel = Schema.Literals([
|
|
102
|
+
"none",
|
|
103
|
+
"minimal",
|
|
104
|
+
"low",
|
|
105
|
+
"medium",
|
|
106
|
+
"high",
|
|
107
|
+
"xhigh",
|
|
108
|
+
"max",
|
|
109
|
+
])
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @since 1.0.0
|
|
113
|
+
* @category Models
|
|
114
|
+
*/
|
|
115
|
+
export type ThoughtLevel = typeof ThoughtLevel.Type
|
|
116
|
+
|
|
88
117
|
/**
|
|
89
118
|
* @since 1.0.0
|
|
90
119
|
* @category Models
|
|
@@ -94,6 +123,7 @@ export class SessionRecord extends Schema.Class<SessionRecord>(
|
|
|
94
123
|
)({
|
|
95
124
|
cwd: Schema.String,
|
|
96
125
|
model: Schema.String,
|
|
126
|
+
thoughtLevel: ThoughtLevel,
|
|
97
127
|
history: Prompt.Prompt,
|
|
98
128
|
}) {}
|
|
99
129
|
|
|
@@ -138,6 +168,12 @@ const SetModelParams = Schema.Struct({
|
|
|
138
168
|
modelId: Schema.String,
|
|
139
169
|
})
|
|
140
170
|
|
|
171
|
+
const SetConfigOptionParams = Schema.Struct({
|
|
172
|
+
sessionId: Schema.String,
|
|
173
|
+
configId: Schema.Literal("thought_level"),
|
|
174
|
+
value: ThoughtLevel,
|
|
175
|
+
})
|
|
176
|
+
|
|
141
177
|
const TextBlock = Schema.Struct({
|
|
142
178
|
type: Schema.Literal("text"),
|
|
143
179
|
text: Schema.String,
|
|
@@ -257,6 +293,7 @@ interface Session {
|
|
|
257
293
|
readonly id: string
|
|
258
294
|
readonly cwd: string
|
|
259
295
|
model: string
|
|
296
|
+
thoughtLevel: ThoughtLevel
|
|
260
297
|
readonly agent: Agent.Agent
|
|
261
298
|
running: Fiber.Fiber<void, unknown> | undefined
|
|
262
299
|
toolCalls: number
|
|
@@ -298,18 +335,32 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
298
335
|
sessionNotFound(sessionId),
|
|
299
336
|
)
|
|
300
337
|
|
|
301
|
-
const requireModel = (modelId: string) =>
|
|
338
|
+
const requireModel = (modelId: string, thoughtLevel: ThoughtLevel) =>
|
|
302
339
|
Effect.fromOption(
|
|
303
|
-
options.makeModel(modelId),
|
|
340
|
+
options.makeModel(modelId, thoughtLevel),
|
|
304
341
|
() =>
|
|
305
342
|
new RpcError({ code: -32602, message: `Unknown model: ${modelId}` }),
|
|
306
343
|
)
|
|
307
344
|
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
345
|
+
const configOptions = (session: Session) => [
|
|
346
|
+
{
|
|
347
|
+
id: "thought_level",
|
|
348
|
+
name: "Thought level",
|
|
349
|
+
category: "thought_level",
|
|
350
|
+
type: "select",
|
|
351
|
+
currentValue: session.thoughtLevel,
|
|
352
|
+
options: ThoughtLevel.literals.map((value) => ({ value, name: value })),
|
|
353
|
+
},
|
|
354
|
+
]
|
|
355
|
+
|
|
356
|
+
const sessionState = (session: Session) => ({
|
|
357
|
+
models: {
|
|
358
|
+
availableModels: [...new Set([session.model, options.defaultModel])].map(
|
|
359
|
+
(modelId) => ({ modelId, name: modelId }),
|
|
360
|
+
),
|
|
361
|
+
currentModelId: session.model,
|
|
362
|
+
},
|
|
363
|
+
configOptions: configOptions(session),
|
|
313
364
|
})
|
|
314
365
|
|
|
315
366
|
const persist = (session: Session) =>
|
|
@@ -319,6 +370,7 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
319
370
|
new SessionRecord({
|
|
320
371
|
cwd: session.cwd,
|
|
321
372
|
model: session.model,
|
|
373
|
+
thoughtLevel: session.thoughtLevel,
|
|
322
374
|
history: session.agent.history.current,
|
|
323
375
|
}),
|
|
324
376
|
)
|
|
@@ -338,6 +390,7 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
338
390
|
id,
|
|
339
391
|
cwd: record.cwd,
|
|
340
392
|
model: record.model,
|
|
393
|
+
thoughtLevel: record.thoughtLevel,
|
|
341
394
|
agent,
|
|
342
395
|
running: undefined,
|
|
343
396
|
toolCalls: 0,
|
|
@@ -602,6 +655,8 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
602
655
|
usage: {
|
|
603
656
|
inputTokens: part.inputTokens,
|
|
604
657
|
outputTokens: part.outputTokens,
|
|
658
|
+
cacheRead: part.cacheRead,
|
|
659
|
+
cacheWrite: part.cacheWrite,
|
|
605
660
|
},
|
|
606
661
|
})
|
|
607
662
|
case "ErrorRetry":
|
|
@@ -658,13 +713,19 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
658
713
|
const newSession = Effect.fnUntraced(function* (params: unknown) {
|
|
659
714
|
const { cwd, model } = yield* decodeParams(NewSessionParams, params)
|
|
660
715
|
const modelId = model ?? options.defaultModel
|
|
661
|
-
|
|
716
|
+
const thoughtLevel = options.defaultThoughtLevel
|
|
717
|
+
yield* requireModel(modelId, thoughtLevel)
|
|
662
718
|
const session = yield* openSession(
|
|
663
719
|
crypto.randomUUID(),
|
|
664
|
-
new SessionRecord({
|
|
720
|
+
new SessionRecord({
|
|
721
|
+
cwd,
|
|
722
|
+
model: modelId,
|
|
723
|
+
thoughtLevel,
|
|
724
|
+
history: Prompt.empty,
|
|
725
|
+
}),
|
|
665
726
|
)
|
|
666
727
|
yield* persist(session)
|
|
667
|
-
return { sessionId: session.id,
|
|
728
|
+
return { sessionId: session.id, ...sessionState(session) }
|
|
668
729
|
})
|
|
669
730
|
|
|
670
731
|
const loadSession = Effect.fnUntraced(function* (
|
|
@@ -677,7 +738,7 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
677
738
|
)
|
|
678
739
|
const existing = sessions.get(sessionId)
|
|
679
740
|
if (existing !== undefined) {
|
|
680
|
-
return
|
|
741
|
+
return sessionState(existing)
|
|
681
742
|
}
|
|
682
743
|
const record = yield* store
|
|
683
744
|
.get(sessionId)
|
|
@@ -690,30 +751,43 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
690
751
|
return yield* sessionNotFound(sessionId)
|
|
691
752
|
}
|
|
692
753
|
const modelId = model ?? record.value.model
|
|
693
|
-
yield* requireModel(modelId)
|
|
754
|
+
yield* requireModel(modelId, record.value.thoughtLevel)
|
|
694
755
|
const session = yield* openSession(
|
|
695
756
|
sessionId,
|
|
696
757
|
new SessionRecord({
|
|
697
758
|
cwd: cwd ?? record.value.cwd,
|
|
698
759
|
model: modelId,
|
|
760
|
+
thoughtLevel: record.value.thoughtLevel,
|
|
699
761
|
history: record.value.history,
|
|
700
762
|
}),
|
|
701
763
|
)
|
|
702
764
|
if (replay) {
|
|
703
765
|
yield* replayHistory(session)
|
|
704
766
|
}
|
|
705
|
-
return
|
|
767
|
+
return sessionState(session)
|
|
706
768
|
})
|
|
707
769
|
|
|
708
770
|
const setModel = Effect.fnUntraced(function* (params: unknown) {
|
|
709
771
|
const { sessionId, modelId } = yield* decodeParams(SetModelParams, params)
|
|
710
772
|
const session = yield* getSession(sessionId)
|
|
711
|
-
yield* requireModel(modelId)
|
|
773
|
+
yield* requireModel(modelId, session.thoughtLevel)
|
|
712
774
|
session.model = modelId
|
|
713
775
|
yield* persist(session)
|
|
714
776
|
return {}
|
|
715
777
|
})
|
|
716
778
|
|
|
779
|
+
const setConfigOption = Effect.fnUntraced(function* (params: unknown) {
|
|
780
|
+
const { sessionId, value } = yield* decodeParams(
|
|
781
|
+
SetConfigOptionParams,
|
|
782
|
+
params,
|
|
783
|
+
)
|
|
784
|
+
const session = yield* getSession(sessionId)
|
|
785
|
+
yield* requireModel(session.model, value)
|
|
786
|
+
session.thoughtLevel = value
|
|
787
|
+
yield* persist(session)
|
|
788
|
+
return { configOptions: configOptions(session) }
|
|
789
|
+
})
|
|
790
|
+
|
|
717
791
|
const prompt = Effect.fnUntraced(function* (params: unknown) {
|
|
718
792
|
const { sessionId, prompt } = yield* decodeParams(PromptParams, params)
|
|
719
793
|
const session = yield* getSession(sessionId)
|
|
@@ -723,7 +797,7 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
723
797
|
message: `Session ${sessionId} already has a prompt in progress`,
|
|
724
798
|
})
|
|
725
799
|
}
|
|
726
|
-
const model = yield* requireModel(session.model)
|
|
800
|
+
const model = yield* requireModel(session.model, session.thoughtLevel)
|
|
727
801
|
// Resolve images before the turn starts, so a bad block rejects the
|
|
728
802
|
// request without a model call.
|
|
729
803
|
const input = yield* promptFromBlocks(session.cwd, prompt)
|
|
@@ -757,8 +831,9 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
757
831
|
return initialize
|
|
758
832
|
case "authenticate":
|
|
759
833
|
case "session/set_mode":
|
|
760
|
-
case "session/set_config_option":
|
|
761
834
|
return Effect.succeed({})
|
|
835
|
+
case "session/set_config_option":
|
|
836
|
+
return setConfigOption(params)
|
|
762
837
|
case "session/new":
|
|
763
838
|
return newSession(params)
|
|
764
839
|
case "session/load":
|
package/src/AcpImage.test.ts
CHANGED