[03-Developer] #260 in-app tool calling (Gemma 4 multi-turn)

ADR-0005 in-process tool runtime — 6 tools (catalog 2 + tracker 2 +
habit 2), ToolDispatcher with JSON-schema validation + modal ConfirmGate
for destructive ops, multi-turn LlmChatSession abstraction wired to
flutter_gemma 0.16.5 (ToolChoice.auto), ChatSessionController with
MAX_TURNS=4 safety + 8-turn history hint, ChatScreen entry behind AI
opt-in. R3/R7/R8 enforced inside handlers. 41 new tests (envelope,
catalog/tracker/habit tools, dispatcher, controller loop) — 151 total
passing.

Refs #260
This commit is contained in:
2026-06-15 10:42:43 +09:00
parent eca097aa2c
commit b1bed4d5ca
21 changed files with 2313 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
import 'catalog_tools.dart';
import 'habit_tools.dart';
import 'tool_definition.dart';
import 'tracker_tools.dart';
/// Static registry of all tools exposed to the LLM.
///
/// Order is the order surfaced to the model (`flutter_gemma` preserves the
/// list). Read-only tools first, then destructive — mirrors a "look before
/// you leap" prompt bias.
final List<ToolDefinition> kAllTools = [
// read-only
searchCatalogTool,
queryProtocolTool,
listActiveHabitsTool,
getStreakTool,
// destructive (confirm gate)
addHabitTool,
logTrackerEntryTool,
];
class ToolRegistry {
final Map<String, ToolDefinition> _byName;
ToolRegistry(List<ToolDefinition> tools)
: _byName = {for (final t in tools) t.name: t};
factory ToolRegistry.defaults() => ToolRegistry(kAllTools);
ToolDefinition? byName(String name) => _byName[name];
Iterable<ToolDefinition> get all => _byName.values;
}