Skip to content

Commit 255ea94

Browse files
committed
refactor: split examples into mill submodules
1 parent 514b742 commit 255ea94

15 files changed

+88
-41
lines changed

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
- `bun install`: install JS dependencies (Bun is the preferred runtime).
1212
- `./mill agent.compile` or `bun run build`: compile the Scala.js library.
1313
- `./mill agent.test`: run the MUnit test suite.
14-
- `./mill examples.run`: run the default example; use `EXAMPLE=simple ./mill examples.run` for a specific example.
14+
- `./mill examples.run`: run the default example.
15+
- `./mill examples.simple.run`: run a specific example by submodule, e.g. `./mill examples.hook.run`.
1516
- `bun run run`: compile and execute the JS output for examples.
1617
- `./mill examples.list`: list available example entry points.
1718

build.mill

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ object agent extends ScalaJSModule with PublishModule with BunNpmModule {
258258
// Example application module
259259
// ---------------------------------------------------------------------------
260260

261-
object examples extends BunNpmModule {
261+
trait ExampleModule extends BunNpmModule {
262262
def scalaVersion = agent.scalaVersion
263263
def scalaJSVersion = agent.scalaJSVersion
264264

@@ -280,22 +280,29 @@ object examples extends BunNpmModule {
280280
override def moduleDir = build.moduleDir
281281
override def sources = Task.Sources(moduleDir / "examples")
282282

283+
def exampleMainClass: String
284+
285+
override def mainClass = Task { Some(exampleMainClass) }
286+
}
287+
288+
object examples extends ExampleModule {
289+
def exampleMainClass = "com.tjclp.scalagent.examples.MacroToolExample"
290+
283291
// Available examples - add new ones here
284-
val exampleClasses = Map(
285-
"simple" -> "com.tjclp.scalagent.examples.SimpleQuery",
286-
"macro" -> "com.tjclp.scalagent.examples.MacroToolExample",
287-
"custom" -> "com.tjclp.scalagent.examples.CustomToolExample",
288-
"hook" -> "com.tjclp.scalagent.examples.HookExample",
289-
"permission" -> "com.tjclp.scalagent.examples.PermissionExample",
290-
"session" -> "com.tjclp.scalagent.examples.SessionExample",
291-
// New examples for recent features
292-
"structured" -> "com.tjclp.scalagent.examples.StructuredOutputExample",
293-
"subagent" -> "com.tjclp.scalagent.examples.SubagentExample",
294-
"plugin" -> "com.tjclp.scalagent.examples.PluginExample",
295-
"prompt" -> "com.tjclp.scalagent.examples.SystemPromptExample",
296-
"command" -> "com.tjclp.scalagent.examples.SlashCommandExample",
297-
"a2a" -> "com.tjclp.scalagent.examples.A2AExample",
298-
"agent-hooks" -> "com.tjclp.scalagent.examples.AgentHooksExample"
292+
val exampleCommands = Map(
293+
"simple" -> "examples.simple.run",
294+
"macro" -> "examples.run",
295+
"custom" -> "examples.custom.run",
296+
"hook" -> "examples.hook.run",
297+
"permission" -> "examples.permission.run",
298+
"session" -> "examples.session.run",
299+
"structured" -> "examples.structured.run",
300+
"subagent" -> "examples.subagent.run",
301+
"plugin" -> "examples.plugin.run",
302+
"prompt" -> "examples.prompt.run",
303+
"command" -> "examples.command.run",
304+
"a2a" -> "examples.a2a.run",
305+
"agent-hooks" -> "examples.agentHooks.run"
299306
)
300307

301308
private val defaultExample = "macro"
@@ -304,25 +311,64 @@ object examples extends BunNpmModule {
304311
def list() = Task.Command {
305312
println("Available examples:")
306313
println("-------------------")
307-
exampleClasses.toSeq.sortBy(_._1).foreach { case (name, cls) =>
308-
println(s" $name -> $cls")
314+
exampleCommands.toSeq.sortBy(_._1).foreach { case (name, command) =>
315+
println(s" $name -> ./$command")
309316
}
310317
println()
311318
println("Run with:")
312319
println(s" ./mill examples.run # runs '$defaultExample' by default")
313-
println(" EXAMPLE=simple ./mill examples.run # run specific example")
314-
println(" EXAMPLE=hook ./mill examples.run # run hook example")
320+
println(" ./mill examples.simple.run # run simple example")
321+
println(" ./mill examples.hook.run # run hook example")
315322
println()
316323
println("Or run the compiled JS directly:")
317324
println(" bun out/examples/fastLinkJS.dest/main.js")
318325
}
319326

320-
// Dynamic mainClass based on environment or default
321-
// Task.Input ensures this is re-evaluated each run
322-
override def mainClass = Task.Input {
323-
val example = Task.env.get("EXAMPLE").getOrElse(defaultExample)
324-
val cls = exampleClasses.get(example)
325-
if cls.isEmpty then println(s"Warning: Unknown example '$example', using '$defaultExample'")
326-
cls.orElse(Some(exampleClasses(defaultExample)))
327+
object simple extends ExampleModule {
328+
def exampleMainClass = "com.tjclp.scalagent.examples.SimpleQuery"
329+
}
330+
331+
object custom extends ExampleModule {
332+
def exampleMainClass = "com.tjclp.scalagent.examples.CustomToolExample"
333+
}
334+
335+
object hook extends ExampleModule {
336+
def exampleMainClass = "com.tjclp.scalagent.examples.HookExample"
337+
}
338+
339+
object permission extends ExampleModule {
340+
def exampleMainClass = "com.tjclp.scalagent.examples.PermissionExample"
341+
}
342+
343+
object session extends ExampleModule {
344+
def exampleMainClass = "com.tjclp.scalagent.examples.SessionExample"
345+
}
346+
347+
object structured extends ExampleModule {
348+
def exampleMainClass = "com.tjclp.scalagent.examples.StructuredOutputExample"
349+
}
350+
351+
object subagent extends ExampleModule {
352+
def exampleMainClass = "com.tjclp.scalagent.examples.SubagentExample"
353+
}
354+
355+
object plugin extends ExampleModule {
356+
def exampleMainClass = "com.tjclp.scalagent.examples.PluginExample"
357+
}
358+
359+
object prompt extends ExampleModule {
360+
def exampleMainClass = "com.tjclp.scalagent.examples.SystemPromptExample"
361+
}
362+
363+
object command extends ExampleModule {
364+
def exampleMainClass = "com.tjclp.scalagent.examples.SlashCommandExample"
365+
}
366+
367+
object a2a extends ExampleModule {
368+
def exampleMainClass = "com.tjclp.scalagent.examples.A2AExample"
369+
}
370+
371+
object agentHooks extends ExampleModule {
372+
def exampleMainClass = "com.tjclp.scalagent.examples.AgentHooksExample"
327373
}
328374
}

examples/A2AExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import com.tjclp.scalagent.*
1818
* Claude Writer (local) --> A2ATool --> A2A Client --> A2A Server --> Claude Researcher
1919
* ```
2020
*
21-
* Run with: mill examples.runMain com.tjclp.scalagent.examples.A2AExample
21+
* Run with: ./mill examples.a2a.run
2222
*
2323
* Requires:
2424
* - ANTHROPIC_API_KEY environment variable when Claude Code auth is not already available

examples/AgentHooksExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import com.tjclp.scalagent.hooks.HookConfig
1414
* 4. Use the permissionMode field in AgentDefinition
1515
* 5. Use the fluent extension methods (withShellHook, withCallbackHook)
1616
*
17-
* Run with: EXAMPLE=agent-hooks mill examples.run
17+
* Run with: ./mill examples.agentHooks.run
1818
*
1919
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
2020
*/

examples/CustomToolExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import com.tjclp.scalagent.*
1212
* 2. Create an in-process MCP server with those tools
1313
* 3. Use the custom tools in a Claude agent query
1414
*
15-
* Run with: mill examples.runMain com.tjclp.scalagent.examples.CustomToolExample
15+
* Run with: ./mill examples.custom.run
1616
*
1717
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
1818
*/

examples/HookExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import com.tjclp.scalagent.*
1111
* 2. Block specific tools (e.g., Bash commands)
1212
* 3. Modify tool behavior based on custom logic
1313
*
14-
* Run with: mill examples.runMain com.tjclp.scalagent.examples.HookExample
14+
* Run with: ./mill examples.hook.run
1515
*
1616
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
1717
*/

examples/MacroToolExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import com.tjclp.scalagent.*
1616
* - Support for structured output with ToolResult.json()
1717
* - Support for multimodal output with ToolResult.multi
1818
*
19-
* Run with: mill examples.runMain com.tjclp.scalagent.examples.MacroToolExample
19+
* Run with: ./mill examples.run
2020
*
2121
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
2222
*/

examples/PermissionExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import com.tjclp.scalagent.permissions.{PermissionUpdate, PermissionUpdateDestin
1414
* 3. Use permission utilities for common patterns
1515
* 4. Programmatic permission updates with PermissionUpdateDestination
1616
*
17-
* Run with: mill examples.runMain com.tjclp.scalagent.examples.PermissionExample
17+
* Run with: ./mill examples.permission.run
1818
*
1919
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
2020
*/

examples/PluginExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import com.tjclp.scalagent.*
1111
* - Handle PluginError types (PathNotFound, NotADirectory, MissingManifest)
1212
* - Use convenience methods like withLocalPlugins()
1313
*
14-
* Run with: EXAMPLE=plugin mill examples.run
14+
* Run with: ./mill examples.plugin.run
1515
*
1616
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
1717
*/

examples/SessionExample.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import com.tjclp.scalagent.*
1717
* - Proper resource cleanup with `session.close`
1818
* - Validated session UUIDs with `SessionUuid`
1919
*
20-
* Run with: mill examples.runMain com.tjclp.scalagent.examples.SessionExample
20+
* Run with: ./mill examples.session.run
2121
*
2222
* Requires ANTHROPIC_API_KEY environment variable to be set when Claude Code auth is not already available.
2323
*

0 commit comments

Comments
 (0)