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.
Files changed (39) hide show
  1. package/dist/Acp.d.ts +21 -2
  2. package/dist/Acp.d.ts.map +1 -1
  3. package/dist/Acp.js +66 -13
  4. package/dist/Acp.js.map +1 -1
  5. package/dist/Acp.test.js +56 -10
  6. package/dist/Acp.test.js.map +1 -1
  7. package/dist/AcpImage.test.js +1 -0
  8. package/dist/AcpImage.test.js.map +1 -1
  9. package/dist/AgentTools.d.ts.map +1 -1
  10. package/dist/AgentTools.js +22 -7
  11. package/dist/AgentTools.js.map +1 -1
  12. package/dist/AgentTools.test.d.ts +2 -0
  13. package/dist/AgentTools.test.d.ts.map +1 -0
  14. package/dist/AgentTools.test.js +63 -0
  15. package/dist/AgentTools.test.js.map +1 -0
  16. package/dist/bin/{Effect-DdkIoNCD.mjs → Effect-CeAMoJlg.mjs} +7 -2
  17. package/dist/bin/Effect-CeAMoJlg.mjs.map +1 -0
  18. package/dist/bin/{McpClient-0f-vTQC-.mjs → McpClient-zQibhsnA.mjs} +3 -3
  19. package/dist/bin/{McpClient-0f-vTQC-.mjs.map → McpClient-zQibhsnA.mjs.map} +1 -1
  20. package/dist/bin/{OutputFormatter-DN8OGwuK.mjs → OutputFormatter-C7Awn0DS.mjs} +3 -3
  21. package/dist/bin/{OutputFormatter-DN8OGwuK.mjs.map → OutputFormatter-C7Awn0DS.mjs.map} +1 -1
  22. package/dist/bin/{Schema-gTtf66A-.mjs → Schema-Bc06DxcV.mjs} +2 -2
  23. package/dist/bin/{Schema-gTtf66A-.mjs.map → Schema-Bc06DxcV.mjs.map} +1 -1
  24. package/dist/bin/{SemanticSearch-CBs6yELV.mjs → SemanticSearch-BPxQoRSC.mjs} +4 -4
  25. package/dist/bin/{SemanticSearch-CBs6yELV.mjs.map → SemanticSearch-BPxQoRSC.mjs.map} +1 -1
  26. package/dist/bin/{Stream-B5ebASRi.mjs → Stream-DlGXvw0L.mjs} +2 -2
  27. package/dist/bin/{Stream-B5ebASRi.mjs.map → Stream-DlGXvw0L.mjs.map} +1 -1
  28. package/dist/bin/cli.mjs +94 -37
  29. package/dist/bin/cli.mjs.map +1 -1
  30. package/dist/cli.js +17 -8
  31. package/dist/cli.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/Acp.test.ts +86 -9
  34. package/src/Acp.ts +90 -17
  35. package/src/AcpImage.test.ts +1 -0
  36. package/src/AgentTools.test.ts +116 -0
  37. package/src/AgentTools.ts +32 -12
  38. package/src/cli.ts +22 -9
  39. package/dist/bin/Effect-DdkIoNCD.mjs.map +0 -1
package/src/AgentTools.ts CHANGED
@@ -82,6 +82,12 @@ export class ImageAttacher extends Context.Service<
82
82
  (image: ImageAttachment) => Effect.Effect<void>
83
83
  >()("clanka/AgentTools/ImageAttacher") {}
84
84
 
85
+ const globNamesDirectory = (glob: string) =>
86
+ glob
87
+ .split("/")
88
+ .slice(0, -1)
89
+ .some((segment) => segment.length > 0 && !/[*?[\]{}]/.test(segment))
90
+
85
91
  /**
86
92
  * @since 1.0.0
87
93
  * @category Context
@@ -440,24 +446,38 @@ export const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(
440
446
  if (options.filesOnly) {
441
447
  args.push("--files-with-matches")
442
448
  }
449
+ const searchesIgnoredFiles =
450
+ options.glob !== undefined && !options.glob.startsWith("*")
443
451
  if (options.glob) {
444
452
  args.push("--glob", options.glob)
445
- if (!options.glob.startsWith("*")) {
453
+ if (searchesIgnoredFiles) {
446
454
  args.push("-uu")
447
455
  }
448
456
  }
449
457
  args.push(options.pattern)
450
- let stream = spawner.streamLines(
451
- ChildProcess.make("rg", args, {
452
- cwd,
453
- stdin: "ignore",
454
- }),
455
- )
456
- stream = Stream.take(stream, options.maxLines ?? 500)
457
- return yield* Stream.runCollect(stream).pipe(
458
- Effect.map(Array.join("\n")),
459
- Effect.orDie,
460
- )
458
+ const run = Effect.fnUntraced(function* (args: Array<string>) {
459
+ let stream = spawner.streamLines(
460
+ ChildProcess.make("rg", args, {
461
+ cwd,
462
+ stdin: "ignore",
463
+ }),
464
+ )
465
+ stream = Stream.take(stream, options.maxLines ?? 500)
466
+ return yield* Stream.runCollect(stream).pipe(
467
+ Effect.map(Array.join("\n")),
468
+ Effect.orDie,
469
+ )
470
+ })
471
+ const output = yield* run(args)
472
+ if (
473
+ output.length > 0 ||
474
+ searchesIgnoredFiles ||
475
+ options.glob === undefined ||
476
+ !globNamesDirectory(options.glob)
477
+ ) {
478
+ return output
479
+ }
480
+ return yield* run(args.slice(0, -1).concat("-uu", options.pattern))
461
481
  }),
462
482
  glob: Effect.fn("AgentTools.glob")(function* (pattern) {
463
483
  yield* Effect.logInfo(`Calling "glob"`).pipe(
package/src/cli.ts CHANGED
@@ -64,14 +64,25 @@ const modelLayer = (provider: Provider, model: string, effort: string) =>
64
64
  Layer.provide(Copilot.layerClient),
65
65
  )
66
66
 
67
+ const isProvider = (provider: string | undefined): provider is Provider =>
68
+ providers.includes(provider as Provider)
69
+
70
+ // `<provider>/<model>/<effort>` as accepted by the `acp` --model flag.
67
71
  const parseModelId = (modelId: string) => {
68
72
  const [provider, model, effort, ...rest] = modelId.split("/")
69
- return provider !== undefined &&
70
- providers.includes(provider as Provider) &&
73
+ return isProvider(provider) &&
71
74
  model !== undefined &&
72
- effort !== undefined &&
75
+ Schema.is(Acp.ThoughtLevel)(effort) &&
73
76
  rest.length === 0
74
- ? Option.some({ provider: provider as Provider, model, effort })
77
+ ? Option.some({ model: `${provider}:${model}`, thoughtLevel: effort })
78
+ : Option.none()
79
+ }
80
+
81
+ // `<provider>:<model>` as advertised over ACP.
82
+ const parseAcpModelId = (modelId: string) => {
83
+ const [provider, model, ...rest] = modelId.split(":")
84
+ return isProvider(provider) && model !== undefined && rest.length === 0
85
+ ? Option.some({ provider, model })
75
86
  : Option.none()
76
87
  }
77
88
 
@@ -80,7 +91,7 @@ const ModelId = Schema.String.pipe(
80
91
  Schema.makeFilter(
81
92
  (modelId: string) =>
82
93
  Option.isSome(parseModelId(modelId)) ||
83
- `Invalid model "${modelId}", expected <provider>/<model>/<effort>`,
94
+ `Invalid model "${modelId}", expected <provider>/<model>/<effort> with effort one of ${Acp.ThoughtLevel.literals.join(", ")}`,
84
95
  ),
85
96
  ),
86
97
  )
@@ -192,6 +203,7 @@ const acpModel = Flag.String("model").pipe(
192
203
  ),
193
204
  Flag.withSchema(ModelId),
194
205
  Flag.withDefault("openai/gpt-6-astra/medium"),
206
+ Flag.map((modelId) => Option.getOrThrow(parseModelId(modelId))),
195
207
  )
196
208
 
197
209
  const acp = Command.make("acp", { model: acpModel, compaction }).pipe(
@@ -201,14 +213,15 @@ const acp = Command.make("acp", { model: acpModel, compaction }).pipe(
201
213
  Command.withHandler(({ model }) =>
202
214
  Acp.runStdio({
203
215
  version,
204
- defaultModel: model,
216
+ defaultModel: model.model,
217
+ defaultThoughtLevel: model.thoughtLevel,
205
218
  makeAgent: (cwd) =>
206
219
  Agent.make.pipe(
207
220
  Effect.provide(AgentExecutor.layerLocal({ directory: cwd })),
208
221
  ),
209
- makeModel: (modelId) =>
210
- Option.map(parseModelId(modelId), ({ provider, model, effort }) =>
211
- modelLayer(provider, model, effort),
222
+ makeModel: (modelId, thoughtLevel) =>
223
+ Option.map(parseAcpModelId(modelId), ({ provider, model }) =>
224
+ modelLayer(provider, model, thoughtLevel),
212
225
  ),
213
226
  }),
214
227
  ),