clanka 0.7.6 → 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/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 +94 -37
- 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/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,54 @@ describe("Acp", () => {
|
|
|
150
154
|
),
|
|
151
155
|
)
|
|
152
156
|
|
|
157
|
+
it.effect("applies model and thought-level changes to the next turn", () =>
|
|
158
|
+
withStore(
|
|
159
|
+
Effect.scoped(
|
|
160
|
+
Effect.gen(function* () {
|
|
161
|
+
const resolved: Array<[string, string]> = []
|
|
162
|
+
const server = yield* makeServer(
|
|
163
|
+
() => assistantSays("done"),
|
|
164
|
+
executor,
|
|
165
|
+
(modelId, thoughtLevel) => resolved.push([modelId, thoughtLevel]),
|
|
166
|
+
)
|
|
167
|
+
const created = yield* server.request(1, "session/new", {
|
|
168
|
+
cwd: "/tmp",
|
|
169
|
+
})
|
|
170
|
+
const sessionId: string = created.result.sessionId
|
|
171
|
+
|
|
172
|
+
yield* server.request(2, "session/set_model", {
|
|
173
|
+
sessionId,
|
|
174
|
+
modelId: "other:model",
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
const configured = yield* server.request(
|
|
178
|
+
3,
|
|
179
|
+
"session/set_config_option",
|
|
180
|
+
{ sessionId, configId: "thought_level", value: "high" },
|
|
181
|
+
)
|
|
182
|
+
assert.strictEqual(
|
|
183
|
+
configured.result.configOptions[0].currentValue,
|
|
184
|
+
"high",
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
const rejected = yield* server.request(
|
|
188
|
+
4,
|
|
189
|
+
"session/set_config_option",
|
|
190
|
+
{ sessionId, configId: "thought_level", value: "turbo" },
|
|
191
|
+
)
|
|
192
|
+
assert.strictEqual(rejected.error?.code, -32602)
|
|
193
|
+
|
|
194
|
+
resolved.length = 0
|
|
195
|
+
yield* server.request(5, "session/prompt", {
|
|
196
|
+
sessionId,
|
|
197
|
+
prompt: [{ type: "text", text: "use the selected model" }],
|
|
198
|
+
})
|
|
199
|
+
assert.deepStrictEqual(resolved, [["other:model", "high"]])
|
|
200
|
+
}),
|
|
201
|
+
),
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
|
|
153
205
|
for (const script of [
|
|
154
206
|
"console.log(1)",
|
|
155
207
|
'console.log("' + "x".repeat(200) + '")',
|
|
@@ -313,7 +365,7 @@ describe("Acp", () => {
|
|
|
313
365
|
),
|
|
314
366
|
)
|
|
315
367
|
|
|
316
|
-
it.effect("
|
|
368
|
+
it.effect("reports canonical state for new and loaded sessions", () =>
|
|
317
369
|
withStore(
|
|
318
370
|
Effect.gen(function* () {
|
|
319
371
|
const sessionId = yield* Effect.scoped(
|
|
@@ -322,7 +374,27 @@ describe("Acp", () => {
|
|
|
322
374
|
const created = yield* server.request(1, "session/new", {
|
|
323
375
|
cwd: "/tmp",
|
|
324
376
|
})
|
|
325
|
-
|
|
377
|
+
assert.deepStrictEqual(created.result.models, {
|
|
378
|
+
availableModels: [{ modelId: "test:model", name: "test:model" }],
|
|
379
|
+
currentModelId: "test:model",
|
|
380
|
+
})
|
|
381
|
+
assert.deepInclude(created.result.configOptions[0], {
|
|
382
|
+
id: "thought_level",
|
|
383
|
+
currentValue: "medium",
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
const legacy = yield* server.request(2, "session/new", {
|
|
387
|
+
cwd: "/tmp",
|
|
388
|
+
model: "test/model/high",
|
|
389
|
+
})
|
|
390
|
+
assert.strictEqual(legacy.error?.code, -32602)
|
|
391
|
+
|
|
392
|
+
yield* server.request(3, "session/set_config_option", {
|
|
393
|
+
sessionId: created.result.sessionId,
|
|
394
|
+
configId: "thought_level",
|
|
395
|
+
value: "high",
|
|
396
|
+
})
|
|
397
|
+
yield* server.request(4, "session/prompt", {
|
|
326
398
|
sessionId: created.result.sessionId,
|
|
327
399
|
prompt: [{ type: "text", text: "hello" }],
|
|
328
400
|
})
|
|
@@ -340,7 +412,11 @@ describe("Acp", () => {
|
|
|
340
412
|
})
|
|
341
413
|
assert.strictEqual(
|
|
342
414
|
loaded.result.models.currentModelId,
|
|
343
|
-
"test
|
|
415
|
+
"test:model",
|
|
416
|
+
)
|
|
417
|
+
assert.strictEqual(
|
|
418
|
+
loaded.result.configOptions[0].currentValue,
|
|
419
|
+
"high",
|
|
344
420
|
)
|
|
345
421
|
assert.deepStrictEqual(
|
|
346
422
|
server.updates(sessionId).map((u) => u.sessionUpdate),
|
|
@@ -393,7 +469,8 @@ describe("Acp", () => {
|
|
|
393
469
|
sessionId,
|
|
394
470
|
new Acp.SessionRecord({
|
|
395
471
|
cwd: "/tmp",
|
|
396
|
-
model: "test
|
|
472
|
+
model: "test:model",
|
|
473
|
+
thoughtLevel: "medium",
|
|
397
474
|
history,
|
|
398
475
|
}),
|
|
399
476
|
)
|
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,
|
|
@@ -658,13 +711,19 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
658
711
|
const newSession = Effect.fnUntraced(function* (params: unknown) {
|
|
659
712
|
const { cwd, model } = yield* decodeParams(NewSessionParams, params)
|
|
660
713
|
const modelId = model ?? options.defaultModel
|
|
661
|
-
|
|
714
|
+
const thoughtLevel = options.defaultThoughtLevel
|
|
715
|
+
yield* requireModel(modelId, thoughtLevel)
|
|
662
716
|
const session = yield* openSession(
|
|
663
717
|
crypto.randomUUID(),
|
|
664
|
-
new SessionRecord({
|
|
718
|
+
new SessionRecord({
|
|
719
|
+
cwd,
|
|
720
|
+
model: modelId,
|
|
721
|
+
thoughtLevel,
|
|
722
|
+
history: Prompt.empty,
|
|
723
|
+
}),
|
|
665
724
|
)
|
|
666
725
|
yield* persist(session)
|
|
667
|
-
return { sessionId: session.id,
|
|
726
|
+
return { sessionId: session.id, ...sessionState(session) }
|
|
668
727
|
})
|
|
669
728
|
|
|
670
729
|
const loadSession = Effect.fnUntraced(function* (
|
|
@@ -677,7 +736,7 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
677
736
|
)
|
|
678
737
|
const existing = sessions.get(sessionId)
|
|
679
738
|
if (existing !== undefined) {
|
|
680
|
-
return
|
|
739
|
+
return sessionState(existing)
|
|
681
740
|
}
|
|
682
741
|
const record = yield* store
|
|
683
742
|
.get(sessionId)
|
|
@@ -690,30 +749,43 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
690
749
|
return yield* sessionNotFound(sessionId)
|
|
691
750
|
}
|
|
692
751
|
const modelId = model ?? record.value.model
|
|
693
|
-
yield* requireModel(modelId)
|
|
752
|
+
yield* requireModel(modelId, record.value.thoughtLevel)
|
|
694
753
|
const session = yield* openSession(
|
|
695
754
|
sessionId,
|
|
696
755
|
new SessionRecord({
|
|
697
756
|
cwd: cwd ?? record.value.cwd,
|
|
698
757
|
model: modelId,
|
|
758
|
+
thoughtLevel: record.value.thoughtLevel,
|
|
699
759
|
history: record.value.history,
|
|
700
760
|
}),
|
|
701
761
|
)
|
|
702
762
|
if (replay) {
|
|
703
763
|
yield* replayHistory(session)
|
|
704
764
|
}
|
|
705
|
-
return
|
|
765
|
+
return sessionState(session)
|
|
706
766
|
})
|
|
707
767
|
|
|
708
768
|
const setModel = Effect.fnUntraced(function* (params: unknown) {
|
|
709
769
|
const { sessionId, modelId } = yield* decodeParams(SetModelParams, params)
|
|
710
770
|
const session = yield* getSession(sessionId)
|
|
711
|
-
yield* requireModel(modelId)
|
|
771
|
+
yield* requireModel(modelId, session.thoughtLevel)
|
|
712
772
|
session.model = modelId
|
|
713
773
|
yield* persist(session)
|
|
714
774
|
return {}
|
|
715
775
|
})
|
|
716
776
|
|
|
777
|
+
const setConfigOption = Effect.fnUntraced(function* (params: unknown) {
|
|
778
|
+
const { sessionId, value } = yield* decodeParams(
|
|
779
|
+
SetConfigOptionParams,
|
|
780
|
+
params,
|
|
781
|
+
)
|
|
782
|
+
const session = yield* getSession(sessionId)
|
|
783
|
+
yield* requireModel(session.model, value)
|
|
784
|
+
session.thoughtLevel = value
|
|
785
|
+
yield* persist(session)
|
|
786
|
+
return { configOptions: configOptions(session) }
|
|
787
|
+
})
|
|
788
|
+
|
|
717
789
|
const prompt = Effect.fnUntraced(function* (params: unknown) {
|
|
718
790
|
const { sessionId, prompt } = yield* decodeParams(PromptParams, params)
|
|
719
791
|
const session = yield* getSession(sessionId)
|
|
@@ -723,7 +795,7 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
723
795
|
message: `Session ${sessionId} already has a prompt in progress`,
|
|
724
796
|
})
|
|
725
797
|
}
|
|
726
|
-
const model = yield* requireModel(session.model)
|
|
798
|
+
const model = yield* requireModel(session.model, session.thoughtLevel)
|
|
727
799
|
// Resolve images before the turn starts, so a bad block rejects the
|
|
728
800
|
// request without a model call.
|
|
729
801
|
const input = yield* promptFromBlocks(session.cwd, prompt)
|
|
@@ -757,8 +829,9 @@ export const make = Effect.fnUntraced(function* <RAgent, RModel>(
|
|
|
757
829
|
return initialize
|
|
758
830
|
case "authenticate":
|
|
759
831
|
case "session/set_mode":
|
|
760
|
-
case "session/set_config_option":
|
|
761
832
|
return Effect.succeed({})
|
|
833
|
+
case "session/set_config_option":
|
|
834
|
+
return setConfigOption(params)
|
|
762
835
|
case "session/new":
|
|
763
836
|
return newSession(params)
|
|
764
837
|
case "session/load":
|
package/src/AcpImage.test.ts
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { assert, describe, it } from "@effect/vitest"
|
|
2
|
+
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient"
|
|
3
|
+
import * as NodeServices from "@effect/platform-node/NodeServices"
|
|
4
|
+
import * as Effect from "effect/Effect"
|
|
5
|
+
import * as FileSystem from "effect/FileSystem"
|
|
6
|
+
import * as Layer from "effect/Layer"
|
|
7
|
+
import * as Path from "effect/Path"
|
|
8
|
+
import * as AgentExecutor from "./AgentExecutor.ts"
|
|
9
|
+
|
|
10
|
+
const match = "ignored-directory-regression-match"
|
|
11
|
+
|
|
12
|
+
const withProject = <A, E, R>(f: Effect.Effect<A, E, R>) =>
|
|
13
|
+
Effect.gen(function* () {
|
|
14
|
+
const fs = yield* FileSystem.FileSystem
|
|
15
|
+
const path = yield* Path.Path
|
|
16
|
+
const project = yield* fs.makeTempDirectoryScoped()
|
|
17
|
+
yield* fs.makeDirectory(path.join(project, ".git"))
|
|
18
|
+
yield* fs.writeFileString(
|
|
19
|
+
path.join(project, ".gitignore"),
|
|
20
|
+
"node_modules/\n",
|
|
21
|
+
)
|
|
22
|
+
yield* fs.makeDirectory(path.join(project, "src"))
|
|
23
|
+
yield* fs.makeDirectory(path.join(project, ".git", "src"))
|
|
24
|
+
yield* fs.makeDirectory(path.join(project, "node_modules", "dependency"), {
|
|
25
|
+
recursive: true,
|
|
26
|
+
})
|
|
27
|
+
yield* fs.makeDirectory(
|
|
28
|
+
path.join(project, "node_modules", "dependency", "src"),
|
|
29
|
+
)
|
|
30
|
+
yield* fs.writeFileString(
|
|
31
|
+
path.join(project, "src", "visible.ts"),
|
|
32
|
+
`${match} visible`,
|
|
33
|
+
)
|
|
34
|
+
yield* fs.writeFileString(
|
|
35
|
+
path.join(project, "node_modules", "dependency", "ignored.ts"),
|
|
36
|
+
`${match} ignored`,
|
|
37
|
+
)
|
|
38
|
+
yield* fs.writeFileString(
|
|
39
|
+
path.join(project, "node_modules", "dependency", "src", "inner.ts"),
|
|
40
|
+
`${match} ignored dependency source`,
|
|
41
|
+
)
|
|
42
|
+
yield* fs.writeFileString(
|
|
43
|
+
path.join(project, ".git", "src", "hidden.ts"),
|
|
44
|
+
`${match} hidden git source`,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return yield* f.pipe(
|
|
48
|
+
Effect.provide(
|
|
49
|
+
AgentExecutor.layerLocal({ directory: project }).pipe(
|
|
50
|
+
Layer.provide(NodeHttpClient.layerUndici),
|
|
51
|
+
),
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
}).pipe(Effect.provide(NodeServices.layer), Effect.scoped)
|
|
55
|
+
|
|
56
|
+
const rg = (glob?: string) =>
|
|
57
|
+
Effect.gen(function* () {
|
|
58
|
+
const executor = yield* AgentExecutor.AgentExecutor
|
|
59
|
+
const output = yield* executor.executeUnsafe({
|
|
60
|
+
tool: "rg",
|
|
61
|
+
params: { pattern: match, glob },
|
|
62
|
+
})
|
|
63
|
+
assert.isString(output)
|
|
64
|
+
return output
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
describe("rg", () => {
|
|
68
|
+
it.effect("does not search ignored directories by default", () =>
|
|
69
|
+
withProject(
|
|
70
|
+
Effect.gen(function* () {
|
|
71
|
+
const output = yield* rg()
|
|
72
|
+
assert.include(output, "src/visible.ts")
|
|
73
|
+
assert.notInclude(output, "node_modules/dependency/ignored.ts")
|
|
74
|
+
}),
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
it.effect("does not search ignored directories for an ordinary glob", () =>
|
|
79
|
+
withProject(
|
|
80
|
+
Effect.gen(function* () {
|
|
81
|
+
const output = yield* rg("**/*.ts")
|
|
82
|
+
assert.include(output, "src/visible.ts")
|
|
83
|
+
assert.notInclude(output, "node_modules/dependency/ignored.ts")
|
|
84
|
+
}),
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
it.effect("does not search ignored paths for an ordinary scoped glob", () =>
|
|
89
|
+
withProject(
|
|
90
|
+
Effect.gen(function* () {
|
|
91
|
+
const output = yield* rg("**/src/*.ts")
|
|
92
|
+
assert.include(output, "src/visible.ts")
|
|
93
|
+
assert.notInclude(output, "node_modules/dependency/src/inner.ts")
|
|
94
|
+
assert.notInclude(output, ".git/src/hidden.ts")
|
|
95
|
+
}),
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
it.effect("searches an ignored directory explicitly named in the glob", () =>
|
|
100
|
+
withProject(
|
|
101
|
+
Effect.gen(function* () {
|
|
102
|
+
const output = yield* rg("**/node_modules/**")
|
|
103
|
+
assert.include(output, "node_modules/dependency/ignored.ts")
|
|
104
|
+
}),
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
it.effect("searches a root-relative ignored directory glob", () =>
|
|
109
|
+
withProject(
|
|
110
|
+
Effect.gen(function* () {
|
|
111
|
+
const output = yield* rg("node_modules/**")
|
|
112
|
+
assert.include(output, "node_modules/dependency/ignored.ts")
|
|
113
|
+
}),
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
})
|