@kindgi/cli 0.1.4-rc.5 → 0.1.5-rc.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.
Files changed (329) hide show
  1. package/README.md +16 -10
  2. package/dist/build/defaults.d.ts +3 -1
  3. package/dist/build/defaults.d.ts.map +1 -1
  4. package/dist/build/defaults.js +44 -1
  5. package/dist/build/defaults.js.map +1 -1
  6. package/dist/build/java-image.d.ts +31 -0
  7. package/dist/build/java-image.d.ts.map +1 -0
  8. package/dist/build/java-image.js +146 -0
  9. package/dist/build/java-image.js.map +1 -0
  10. package/dist/build/pack-root.d.ts +1 -31
  11. package/dist/build/pack-root.d.ts.map +1 -1
  12. package/dist/build/pack-root.js +22 -2
  13. package/dist/build/pack-root.js.map +1 -1
  14. package/dist/build/runners.d.ts +44 -0
  15. package/dist/build/runners.d.ts.map +1 -1
  16. package/dist/build/scala-image.d.ts +21 -0
  17. package/dist/build/scala-image.d.ts.map +1 -0
  18. package/dist/build/scala-image.js +150 -0
  19. package/dist/build/scala-image.js.map +1 -0
  20. package/dist/cli-pin.d.ts +16 -0
  21. package/dist/cli-pin.d.ts.map +1 -0
  22. package/dist/cli-pin.js +66 -0
  23. package/dist/cli-pin.js.map +1 -0
  24. package/dist/commands/agents.d.ts.map +1 -1
  25. package/dist/commands/agents.js +9 -8
  26. package/dist/commands/agents.js.map +1 -1
  27. package/dist/commands/approvals.d.ts.map +1 -1
  28. package/dist/commands/approvals.js +30 -4
  29. package/dist/commands/approvals.js.map +1 -1
  30. package/dist/commands/artifacts.d.ts.map +1 -1
  31. package/dist/commands/artifacts.js +100 -37
  32. package/dist/commands/artifacts.js.map +1 -1
  33. package/dist/commands/auth.js +2 -2
  34. package/dist/commands/blocks.d.ts.map +1 -1
  35. package/dist/commands/blocks.js +5 -4
  36. package/dist/commands/blocks.js.map +1 -1
  37. package/dist/commands/build.d.ts +10 -2
  38. package/dist/commands/build.d.ts.map +1 -1
  39. package/dist/commands/build.js +109 -16
  40. package/dist/commands/build.js.map +1 -1
  41. package/dist/commands/capabilities.d.ts.map +1 -1
  42. package/dist/commands/capabilities.js +37 -10
  43. package/dist/commands/capabilities.js.map +1 -1
  44. package/dist/commands/console.d.ts +21 -0
  45. package/dist/commands/console.d.ts.map +1 -0
  46. package/dist/commands/console.js +87 -0
  47. package/dist/commands/console.js.map +1 -0
  48. package/dist/commands/conversations.d.ts.map +1 -1
  49. package/dist/commands/conversations.js +13 -2
  50. package/dist/commands/conversations.js.map +1 -1
  51. package/dist/commands/deploy.d.ts.map +1 -1
  52. package/dist/commands/deploy.js +2 -2
  53. package/dist/commands/deploy.js.map +1 -1
  54. package/dist/commands/dev.d.ts +11 -0
  55. package/dist/commands/dev.d.ts.map +1 -1
  56. package/dist/commands/dev.js +211 -39
  57. package/dist/commands/dev.js.map +1 -1
  58. package/dist/commands/doctor.d.ts +18 -5
  59. package/dist/commands/doctor.d.ts.map +1 -1
  60. package/dist/commands/doctor.js +421 -21
  61. package/dist/commands/doctor.js.map +1 -1
  62. package/dist/commands/env-scoped.d.ts +44 -0
  63. package/dist/commands/env-scoped.d.ts.map +1 -0
  64. package/dist/commands/env-scoped.js +222 -0
  65. package/dist/commands/env-scoped.js.map +1 -0
  66. package/dist/commands/env.d.ts.map +1 -1
  67. package/dist/commands/env.js +85 -123
  68. package/dist/commands/env.js.map +1 -1
  69. package/dist/commands/eval-runs.d.ts +9 -0
  70. package/dist/commands/eval-runs.d.ts.map +1 -1
  71. package/dist/commands/eval-runs.js +20 -19
  72. package/dist/commands/eval-runs.js.map +1 -1
  73. package/dist/commands/eval-suites.d.ts.map +1 -1
  74. package/dist/commands/eval-suites.js +16 -8
  75. package/dist/commands/eval-suites.js.map +1 -1
  76. package/dist/commands/exports.d.ts +3 -0
  77. package/dist/commands/exports.d.ts.map +1 -0
  78. package/dist/commands/exports.js +82 -0
  79. package/dist/commands/exports.js.map +1 -0
  80. package/dist/commands/feedback.d.ts.map +1 -1
  81. package/dist/commands/feedback.js +6 -5
  82. package/dist/commands/feedback.js.map +1 -1
  83. package/dist/commands/flows.d.ts.map +1 -1
  84. package/dist/commands/flows.js +2 -1
  85. package/dist/commands/flows.js.map +1 -1
  86. package/dist/commands/gate-policies.d.ts.map +1 -1
  87. package/dist/commands/gate-policies.js +2 -1
  88. package/dist/commands/gate-policies.js.map +1 -1
  89. package/dist/commands/guardrails.d.ts.map +1 -1
  90. package/dist/commands/guardrails.js +3 -2
  91. package/dist/commands/guardrails.js.map +1 -1
  92. package/dist/commands/helpers.js +5 -5
  93. package/dist/commands/helpers.js.map +1 -1
  94. package/dist/commands/index.d.ts.map +1 -1
  95. package/dist/commands/index.js +14 -0
  96. package/dist/commands/index.js.map +1 -1
  97. package/dist/commands/init.d.ts +1 -1
  98. package/dist/commands/init.d.ts.map +1 -1
  99. package/dist/commands/init.js +254 -18
  100. package/dist/commands/init.js.map +1 -1
  101. package/dist/commands/judge-classes.d.ts.map +1 -1
  102. package/dist/commands/judge-classes.js +11 -10
  103. package/dist/commands/judge-classes.js.map +1 -1
  104. package/dist/commands/judgments.d.ts.map +1 -1
  105. package/dist/commands/judgments.js +7 -6
  106. package/dist/commands/judgments.js.map +1 -1
  107. package/dist/commands/key.js +4 -4
  108. package/dist/commands/memory.d.ts.map +1 -1
  109. package/dist/commands/memory.js +277 -25
  110. package/dist/commands/memory.js.map +1 -1
  111. package/dist/commands/people.d.ts +3 -0
  112. package/dist/commands/people.d.ts.map +1 -0
  113. package/dist/commands/people.js +166 -0
  114. package/dist/commands/people.js.map +1 -0
  115. package/dist/commands/proposals.d.ts.map +1 -1
  116. package/dist/commands/proposals.js +390 -69
  117. package/dist/commands/proposals.js.map +1 -1
  118. package/dist/commands/provenance.d.ts.map +1 -1
  119. package/dist/commands/provenance.js +6 -7
  120. package/dist/commands/provenance.js.map +1 -1
  121. package/dist/commands/providers.d.ts.map +1 -1
  122. package/dist/commands/providers.js +46 -7
  123. package/dist/commands/providers.js.map +1 -1
  124. package/dist/commands/reviewers.d.ts.map +1 -1
  125. package/dist/commands/reviewers.js +3 -2
  126. package/dist/commands/reviewers.js.map +1 -1
  127. package/dist/commands/runs.d.ts.map +1 -1
  128. package/dist/commands/runs.js +24 -14
  129. package/dist/commands/runs.js.map +1 -1
  130. package/dist/commands/schedules.d.ts +3 -0
  131. package/dist/commands/schedules.d.ts.map +1 -0
  132. package/dist/commands/schedules.js +275 -0
  133. package/dist/commands/schedules.js.map +1 -0
  134. package/dist/commands/secrets.d.ts.map +1 -1
  135. package/dist/commands/secrets.js +10 -11
  136. package/dist/commands/secrets.js.map +1 -1
  137. package/dist/commands/service-accounts.d.ts +3 -0
  138. package/dist/commands/service-accounts.d.ts.map +1 -0
  139. package/dist/commands/service-accounts.js +175 -0
  140. package/dist/commands/service-accounts.js.map +1 -0
  141. package/dist/commands/skills.d.ts +1 -1
  142. package/dist/commands/skills.d.ts.map +1 -1
  143. package/dist/commands/skills.js +11 -4
  144. package/dist/commands/skills.js.map +1 -1
  145. package/dist/commands/sso.d.ts +6 -0
  146. package/dist/commands/sso.d.ts.map +1 -0
  147. package/dist/commands/sso.js +318 -0
  148. package/dist/commands/sso.js.map +1 -0
  149. package/dist/commands/tokens.d.ts +11 -0
  150. package/dist/commands/tokens.d.ts.map +1 -1
  151. package/dist/commands/tokens.js +144 -11
  152. package/dist/commands/tokens.js.map +1 -1
  153. package/dist/commands/tools.d.ts.map +1 -1
  154. package/dist/commands/tools.js +4 -3
  155. package/dist/commands/tools.js.map +1 -1
  156. package/dist/commands/unwired.d.ts.map +1 -1
  157. package/dist/commands/unwired.js +1 -30
  158. package/dist/commands/unwired.js.map +1 -1
  159. package/dist/commands/upgrade.d.ts +11 -0
  160. package/dist/commands/upgrade.d.ts.map +1 -0
  161. package/dist/commands/upgrade.js +160 -0
  162. package/dist/commands/upgrade.js.map +1 -0
  163. package/dist/context.d.ts +7 -0
  164. package/dist/context.d.ts.map +1 -1
  165. package/dist/context.js +1 -0
  166. package/dist/context.js.map +1 -1
  167. package/dist/dev/defaults.d.ts +28 -11
  168. package/dist/dev/defaults.d.ts.map +1 -1
  169. package/dist/dev/defaults.js +114 -35
  170. package/dist/dev/defaults.js.map +1 -1
  171. package/dist/dev/google-credentials.d.ts +50 -0
  172. package/dist/dev/google-credentials.d.ts.map +1 -0
  173. package/dist/dev/google-credentials.js +157 -0
  174. package/dist/dev/google-credentials.js.map +1 -0
  175. package/dist/dev/java-builder.d.ts +56 -0
  176. package/dist/dev/java-builder.d.ts.map +1 -0
  177. package/dist/dev/java-builder.js +204 -0
  178. package/dist/dev/java-builder.js.map +1 -0
  179. package/dist/dev/jvm-run-files.d.ts +29 -0
  180. package/dist/dev/jvm-run-files.d.ts.map +1 -0
  181. package/dist/dev/jvm-run-files.js +94 -0
  182. package/dist/dev/jvm-run-files.js.map +1 -0
  183. package/dist/dev/lines.d.ts +13 -0
  184. package/dist/dev/lines.d.ts.map +1 -0
  185. package/dist/dev/lines.js +24 -0
  186. package/dist/dev/lines.js.map +1 -0
  187. package/dist/dev/log-view.d.ts +116 -0
  188. package/dist/dev/log-view.d.ts.map +1 -0
  189. package/dist/dev/log-view.js +233 -0
  190. package/dist/dev/log-view.js.map +1 -0
  191. package/dist/dev/pack-code.d.ts +79 -4
  192. package/dist/dev/pack-code.d.ts.map +1 -1
  193. package/dist/dev/pack-code.js +262 -3
  194. package/dist/dev/pack-code.js.map +1 -1
  195. package/dist/dev/pack-env.d.ts.map +1 -1
  196. package/dist/dev/pack-env.js +4 -0
  197. package/dist/dev/pack-env.js.map +1 -1
  198. package/dist/dev/pack-service.d.ts +11 -1
  199. package/dist/dev/pack-service.d.ts.map +1 -1
  200. package/dist/dev/pack-service.js +56 -20
  201. package/dist/dev/pack-service.js.map +1 -1
  202. package/dist/dev/paths.d.ts +6 -0
  203. package/dist/dev/paths.d.ts.map +1 -1
  204. package/dist/dev/paths.js +8 -0
  205. package/dist/dev/paths.js.map +1 -1
  206. package/dist/dev/project-database.js +1 -1
  207. package/dist/dev/project-database.js.map +1 -1
  208. package/dist/dev/runners.d.ts +35 -9
  209. package/dist/dev/runners.d.ts.map +1 -1
  210. package/dist/dev/runtime-container.d.ts +10 -2
  211. package/dist/dev/runtime-container.d.ts.map +1 -1
  212. package/dist/dev/runtime-container.js +48 -20
  213. package/dist/dev/runtime-container.js.map +1 -1
  214. package/dist/dev/runtime-env.d.ts +10 -0
  215. package/dist/dev/runtime-env.d.ts.map +1 -1
  216. package/dist/dev/runtime-env.js +8 -4
  217. package/dist/dev/runtime-env.js.map +1 -1
  218. package/dist/dev/runtime-image.d.ts +1 -1
  219. package/dist/dev/runtime-image.js +1 -1
  220. package/dist/dev/scala-builder.d.ts +72 -0
  221. package/dist/dev/scala-builder.d.ts.map +1 -0
  222. package/dist/dev/scala-builder.js +347 -0
  223. package/dist/dev/scala-builder.js.map +1 -0
  224. package/dist/env/project-env.d.ts.map +1 -1
  225. package/dist/env/project-env.js +3 -1
  226. package/dist/env/project-env.js.map +1 -1
  227. package/dist/errors.d.ts +9 -0
  228. package/dist/errors.d.ts.map +1 -1
  229. package/dist/errors.js +15 -0
  230. package/dist/errors.js.map +1 -1
  231. package/dist/help.d.ts +14 -0
  232. package/dist/help.d.ts.map +1 -1
  233. package/dist/help.js +55 -0
  234. package/dist/help.js.map +1 -1
  235. package/dist/init/dependency-specs.d.ts +26 -0
  236. package/dist/init/dependency-specs.d.ts.map +1 -1
  237. package/dist/init/dependency-specs.js +38 -0
  238. package/dist/init/dependency-specs.js.map +1 -1
  239. package/dist/init/java-augment.d.ts +24 -0
  240. package/dist/init/java-augment.d.ts.map +1 -0
  241. package/dist/init/java-augment.js +198 -0
  242. package/dist/init/java-augment.js.map +1 -0
  243. package/dist/init/mode-detect.d.ts +2 -2
  244. package/dist/init/mode-detect.d.ts.map +1 -1
  245. package/dist/init/mode-detect.js +12 -1
  246. package/dist/init/mode-detect.js.map +1 -1
  247. package/dist/init/scala-augment.d.ts +23 -0
  248. package/dist/init/scala-augment.d.ts.map +1 -0
  249. package/dist/init/scala-augment.js +213 -0
  250. package/dist/init/scala-augment.js.map +1 -0
  251. package/dist/init/template-files.d.ts +40 -2
  252. package/dist/init/template-files.d.ts.map +1 -1
  253. package/dist/init/template-files.js +56 -5
  254. package/dist/init/template-files.js.map +1 -1
  255. package/dist/main.d.ts +3 -0
  256. package/dist/main.d.ts.map +1 -1
  257. package/dist/main.js +30 -4
  258. package/dist/main.js.map +1 -1
  259. package/dist/open-url.d.ts +15 -0
  260. package/dist/open-url.d.ts.map +1 -0
  261. package/dist/open-url.js +41 -0
  262. package/dist/open-url.js.map +1 -0
  263. package/dist/package-manager.d.ts +10 -3
  264. package/dist/package-manager.d.ts.map +1 -1
  265. package/dist/package-manager.js +19 -1
  266. package/dist/package-manager.js.map +1 -1
  267. package/dist/providers/preset-loader.d.ts.map +1 -1
  268. package/dist/providers/preset-loader.js +9 -1
  269. package/dist/providers/preset-loader.js.map +1 -1
  270. package/dist/providers/presets/anthropic.json +35 -4
  271. package/dist/providers/presets/gemini-api.json +3 -0
  272. package/dist/providers/presets/gemini.json +3 -0
  273. package/dist/providers/presets/groq.json +1 -0
  274. package/dist/providers/presets/openai.json +36 -4
  275. package/dist/providers/presets/openrouter.json +6 -2
  276. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +28 -4
  277. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +1 -1
  278. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +47 -3
  279. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +7 -5
  280. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +81 -52
  281. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +27 -1
  282. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +5 -4
  283. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +1 -1
  284. package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +220 -0
  285. package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +390 -0
  286. package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +209 -0
  287. package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +334 -0
  288. package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +270 -0
  289. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +23 -5
  290. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
  291. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +10 -3
  292. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +36 -5
  293. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +2 -2
  294. package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +217 -0
  295. package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +357 -0
  296. package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +199 -0
  297. package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +302 -0
  298. package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +302 -0
  299. package/dist/templates/java/.mvn/wrapper/maven-wrapper.properties +3 -0
  300. package/dist/templates/java/AGENTS.md +31 -0
  301. package/dist/templates/java/README.md.tmpl +69 -0
  302. package/dist/templates/java/gitignore +9 -0
  303. package/dist/templates/java/kindgi.config.json.tmpl +8 -0
  304. package/dist/templates/java/kindgiw +33 -0
  305. package/dist/templates/java/kindgiw.cmd +28 -0
  306. package/dist/templates/java/mvnw +295 -0
  307. package/dist/templates/java/pom.xml.tmpl +65 -0
  308. package/dist/templates/java/src/main/java/__PACKAGE__/agents/EchoAgent.java.tmpl +27 -0
  309. package/dist/templates/java/src/main/java/__PACKAGE__/flows/EchoFlow.java.tmpl +18 -0
  310. package/dist/templates/java/src/main/java/__PACKAGE__/guardrails/ResponseNotEmpty.java.tmpl +28 -0
  311. package/dist/templates/java/src/main/java/__PACKAGE__/tools/Echo.java.tmpl +22 -0
  312. package/dist/templates/java/src/main/java/__PACKAGE__/tools/Greet.java.tmpl +23 -0
  313. package/dist/templates/java/src/test/java/__PACKAGE__/ToolsTest.java.tmpl +30 -0
  314. package/dist/templates/minimal/README.md.tmpl +8 -14
  315. package/dist/templates/python/README.md.tmpl +6 -6
  316. package/dist/templates/sample/README.md.tmpl +7 -13
  317. package/dist/templates/scala/AGENTS.md +32 -0
  318. package/dist/templates/scala/README.md.tmpl +75 -0
  319. package/dist/templates/scala/build.sbt.tmpl +16 -0
  320. package/dist/templates/scala/gitignore +13 -0
  321. package/dist/templates/scala/kindgi.config.json.tmpl +8 -0
  322. package/dist/templates/scala/project/build.properties +1 -0
  323. package/dist/templates/scala/src/main/scala/__PACKAGE__/agents/EchoAgent.scala.tmpl +23 -0
  324. package/dist/templates/scala/src/main/scala/__PACKAGE__/flows/EchoFlow.scala.tmpl +16 -0
  325. package/dist/templates/scala/src/main/scala/__PACKAGE__/guardrails/ResponseNotEmpty.scala.tmpl +21 -0
  326. package/dist/templates/scala/src/main/scala/__PACKAGE__/tools/Echo.scala.tmpl +16 -0
  327. package/dist/templates/scala/src/main/scala/__PACKAGE__/tools/Greet.scala.tmpl +17 -0
  328. package/dist/templates/scala/src/test/scala/__PACKAGE__/ToolsSuite.scala.tmpl +23 -0
  329. package/package.json +13 -12
@@ -0,0 +1,302 @@
1
+ ---
2
+ name: kindgi-scala-authoring-tools
3
+ description: >
4
+ Covers writing tools for a Kindgi pack in Scala (`kindgi-pack-scala`,
5
+ `com.kindgi.pack.scaladsl`): `Tool[Input, Output](id)` as a `val` of an
6
+ object named like its file, schemas from case classes (Option, defaults,
7
+ collections, Jakarta constraints) or `Tool.json` with maps, `handler` and
8
+ `handlerAsync` (a Future), `ToolContext` and cancellation, secrets
9
+ (`needsSpec`) and configuration, errors, `readOnly` and effects, munit
10
+ tests with `tool.call`, and wiring a tool onto an agent. Load this
11
+ whenever you are authoring or editing code in a Scala pack's tools
12
+ packages (a pack whose `kindgi.config.json` says `"language": "scala"`),
13
+ defining a tool, or wiring one onto an agent. Scala agents are covered by
14
+ kindgi-scala-authoring-agents, getting started by
15
+ kindgi-scala-getting-started.
16
+ type: core
17
+ library: "kindgi-pack-scala"
18
+ version: "0.1.0"
19
+ sdk_version: "0.1.5-rc.0"
20
+ pack_languages: [scala]
21
+ sources:
22
+ - sdks/scala/README.md
23
+ - sdks/scala/kindgi-pack-scala/src/main/scala/com/kindgi/pack/scaladsl/Tool.scala
24
+ - sdks/java/kindgi-pack/README.md
25
+ ---
26
+
27
+ # Authoring Kindgi tools in Scala
28
+
29
+ > **Running `kindgi`:** the pack pins its CLI (`"cli"` in
30
+ > `kindgi.config.json`), and `./kindgiw` runs that version, so every
31
+ > `kindgi <command>` below runs as `./kindgiw <command>`. sbt is the one on
32
+ > your `PATH`.
33
+ >
34
+ > Scala support is in preview: tested and supported, but the API may still
35
+ > change in 0.1.6 without the usual deprecation period.
36
+
37
+ A **tool** is a unit of work an agent (or a flow step) calls: typed input,
38
+ typed output, your code in between. In a Scala pack it is a `val` of type
39
+ `Tool[I, O]` in an object named like its file (`VerifyCitation.scala` holds
40
+ `object VerifyCitation`), in a `tools` package
41
+ (`src/main/scala/**/tools/**/*.scala`; in an app, `**/kindgi/tools/**`).
42
+ Kindgi runs it in the pack's own JVM (the pack service) and calls it over
43
+ HTTP. The model sees its id, description and input schema.
44
+
45
+ Before writing one, establish what it should **do**: what it computes or
46
+ fetches, what the caller provides, what it returns. "Add a tool" is a
47
+ conversation opener. The pack's sample tools prove the runtime works; they
48
+ are not the shape to copy unless the user asks.
49
+
50
+ ## A tool
51
+
52
+ ```scala
53
+ // src/main/scala/acme/tools/VerifyCitation.scala
54
+ package acme.tools
55
+
56
+ import com.kindgi.pack.scaladsl._
57
+ import jakarta.validation.constraints.{Pattern, Size}
58
+
59
+ /** acme.verify-citation: checks a legal citation against the citator. */
60
+ object VerifyCitation {
61
+ final case class Input(
62
+ @Size(min = 1) citation: String,
63
+ @Pattern(regexp = "^(US|UK|EU)$") jurisdiction: String)
64
+
65
+ final case class Output(found: Boolean, canonicalCite: Option[String])
66
+
67
+ val tool: Tool[Input, Output] = Tool[Input, Output]("acme.verify-citation")
68
+ .description("Verifies a legal citation against the citator; returns whether it resolves and its canonical form.")
69
+ .readOnly
70
+ .set("needsSpec", Map("secrets" -> Map("CITATOR_KEY" -> Map("type" -> "string", "minLength" -> 20))))
71
+ .handler((in, ctx) =>
72
+ verify(in, String.valueOf(ctx.secrets.get("CITATOR_KEY")), sys.env.getOrElse("CITATOR_URL", "")))
73
+
74
+ /** The tool's work, with what it reads from its context and the environment passed in: a test calls it. */
75
+ def verify(in: Input, key: String, citatorUrl: String): Output = {
76
+ val hit = Citator.lookup(citatorUrl, key, in.citation, in.jurisdiction)
77
+ Output(hit.isDefined, hit)
78
+ }
79
+ }
80
+ ```
81
+
82
+ ```scala
83
+ // src/main/scala/acme/tools/Citator.scala
84
+ package acme.tools
85
+
86
+ import java.net.URI
87
+ import java.net.URLEncoder
88
+ import java.net.http.{HttpClient, HttpRequest, HttpResponse}
89
+ import java.nio.charset.StandardCharsets
90
+
91
+ /** The citator's API: an object with no tools in it is a helper, not a primitive. */
92
+ object Citator {
93
+ private val http = HttpClient.newHttpClient()
94
+
95
+ def lookup(baseUrl: String, key: String, citation: String, jurisdiction: String): Option[String] = {
96
+ val query = s"q=${URLEncoder.encode(citation, StandardCharsets.UTF_8)}&j=$jurisdiction"
97
+ val request = HttpRequest.newBuilder(URI.create(s"$baseUrl/lookup?$query"))
98
+ .header("Authorization", s"Bearer $key")
99
+ .build()
100
+ val response = http.send(request, HttpResponse.BodyHandlers.ofString())
101
+ if (response.statusCode() == 200) Some(response.body()) else None
102
+ }
103
+ }
104
+ ```
105
+
106
+ - **Where it lives:** a `val` of the object named like the file. The
107
+ indexer reads the object's vals, and only the primitives that object
108
+ defined. A tool defined as a `def` or a `lazy val` is a file error that
109
+ says to make it a `val`: the indexer can't read one without running it.
110
+ An object with no tools in it is a helper. So is a file with no object
111
+ (a case class, a trait).
112
+ - **Id:** `<pack-id>.<tool-name>`, kebab-case, dot-namespaced.
113
+ - **Description:** what it does and returns. The model reads it to decide
114
+ when to call the tool. It isn't enforced, so never leave it out.
115
+ - **Version:** the pack's (`pack.version`), or `.version("1.2.0")` (an exact
116
+ semver).
117
+ - **Schemas:** from the case classes `Tool[Input, Output]` names. A
118
+ parameter is a property, by its Jackson name
119
+ (`@JsonProperty("canonical_cite")` renames one). The input must be an
120
+ **object**: a model calls a tool with an object of arguments.
121
+
122
+ | In Scala | In the schema |
123
+ |---|---|
124
+ | `String`, `Int`/`Long`, `Double`/`BigDecimal`, `Boolean`; `BigInt` | `string`, `integer`, `number`, `boolean`; `integer` |
125
+ | `Option[T]` | not required; `null` allowed |
126
+ | a parameter's default (`greeting: String = "Hello"`) | `default`, not required; the service fills it in |
127
+ | `Seq[T]`, `List[T]`, `Vector[T]`; `Set[T]` | `array`; `array` with `uniqueItems` |
128
+ | `Map[String, T]` | `object` with `additionalProperties` |
129
+ | a Scala 3 simple enum (`enum Scale { case C, F }`) | `string`, `enum` of its case names |
130
+ | `@Size`, `@Min`, `@Max`, `@Pattern`, `@Email`, `@NotBlank`, `@Positive`, … | the matching keywords |
131
+
132
+ **In Scala 3, name a Java annotation's arguments:** `@Min(value = 0)`, not
133
+ `@Min(0)`. Scala 3 passes a positional argument to the wrong element.
134
+ When a type can't say it, `Tool.json(id).inputSchema(Map(…))` takes the
135
+ schema as Scala maps, and the handler gets a `Map[String, Any]`.
136
+ - **Handler:** `(in, ctx) => output`. It may throw. It runs on a thread of
137
+ its own, so blocking I/O is fine. `handlerAsync((in, ctx) => future)`
138
+ returns a `Future[O]`, and the service awaits it.
139
+ - **Validation:** before the handler runs, the input is checked against the
140
+ schema (its defaults filled in). Then what the handler returns is checked
141
+ against the output schema. A bad input comes back as
142
+ `input-validation-failed`, naming the field (a bad output as
143
+ `output-validation-failed`). The agent's `toolErrors` policy decides
144
+ whether the model gets to fix the call.
145
+
146
+ ## `ToolContext`
147
+
148
+ - `ctx.tenantId`: the tenant the call is for. Key per-tenant state by it.
149
+ - `ctx.runId`: the run (an agent turn or a flow step) the call belongs to.
150
+ - `ctx.requestId`: this call, such as the model's tool-call id. Useful for
151
+ logs and idempotency keys.
152
+ - `ctx.projectId`, `ctx.orgId`: the run's project, and its org (`null` when
153
+ it has none). The runtime sets them from the run, never from the input.
154
+ To check an id the input names, compare it with these.
155
+ - `ctx.cancellation` fires when the call's deadline passes (120 s by
156
+ default) or the caller goes away. A blocking handler's thread is
157
+ interrupted too. A loop checks `ctx.cancellation.isCancelled`. A `Future`
158
+ has no way to stop, so stop the work behind it with
159
+ `ctx.cancellation.onCancel(() => …)`.
160
+ - `ctx.secrets`: the secrets the tool declares (below), as a Java map.
161
+ Printing the context shows their names, never their values.
162
+ - `ctx.env`, `ctx.config`: **reserved, empty today**.
163
+
164
+ ## Configuration and secrets
165
+
166
+ A secret that belongs to the tenant, such as an API key a customer gives
167
+ you, is declared with `set("needsSpec", …)` and read from `ctx.secrets`, as
168
+ above. The runtime resolves every declared secret on every call, for the
169
+ call's tenant, in its env (`KINDGI_ENV`; under `kindgi dev`, `local`: the
170
+ pack's `.env` and `.env.local`). It checks each against its schema, and fails
171
+ the call, naming the secret, when one is missing or doesn't match. Every
172
+ declared secret is required.
173
+
174
+ Everything else comes from the process environment: `sys.env("CITATOR_URL")`.
175
+ Under `kindgi dev`, the pack service gets the pack's `.env` and `.env.local`,
176
+ and restarts when they change. Nothing else from your shell reaches it
177
+ except `PATH`, `HOME` and `TMPDIR`; `SBT_OPTS` reaches sbt only. Put a secret
178
+ there by hand, or with `./kindgiw secrets set NAME --env=local --scope=tenant`
179
+ (a no-echo prompt), and keep the env files out of git. A deployed service
180
+ names the variables it needs in `kindgi.config.json`:
181
+ `"env": {"required": ["DATABASE_URL"], "optional": ["SENTRY_DSN"]}`. Without
182
+ a required one it isn't ready. `KINDGI_*` names are Kindgi's own and never
183
+ reach pack code.
184
+
185
+ ## Errors and output
186
+
187
+ - Throw for a failure, or fail the `Future`: the call fails with
188
+ `handler-throw` and the exception's message. In an agent turn, the model
189
+ sees the failure only when the agent's `toolErrors` policy includes
190
+ `tool-error`, so retrying must be safe for that tool.
191
+ - What the handler logs goes to the pack service's output (`kindgi dev`
192
+ shows it as `[pack] …`), never into a result.
193
+
194
+ ## Other declarations
195
+
196
+ **`readOnly`** declares a tool that changes nothing outside itself (a lookup,
197
+ a search, a calculation): it's `mutating(false)`. A dry run
198
+ (`./kindgiw runs start --dry-run`) runs it. Leave it off for anything that
199
+ writes, sends, charges or deletes: such a tool stops a dry run. It's also
200
+ the tool's approval default: an agent that turns approval gates on
201
+ (`conversationPolicy.hitl`) asks before any tool that isn't read-only on its
202
+ first use.
203
+
204
+ `effect(kind, resource)` declares a side effect, such as
205
+ `.effect("writes", "db:ledger")`. A dry run also stops at a tool with a
206
+ `writes`, `deletes`, `spawns-run`, `emits-event` or `external-side-effect`
207
+ effect. `set(field, value)` sets the index entry's other fields (`needs`,
208
+ `needsSpec`, `sandbox`, `limits`, `network`), with Scala maps and lists. They
209
+ are recorded for policy and review, so declare what the tool really does.
210
+
211
+ There is no HTTP-tool form (TypeScript's `kind: 'http'`). A tool that calls
212
+ an HTTP API is a handler with `java.net.http.HttpClient`, as above.
213
+
214
+ ## Testing
215
+
216
+ `tool.call(input, ctx)` runs the handler with the input as given (no schema
217
+ check). `ToolContext.forTest()` is a context with a test tenant and run and
218
+ nothing else. A handler that reads the environment and calls a service is
219
+ tested through the method it calls, with a stub server:
220
+
221
+ ```scala
222
+ // src/test/scala/acme/VerifyCitationSuite.scala
223
+ package acme
224
+
225
+ import acme.tools.VerifyCitation
226
+ import com.sun.net.httpserver.HttpServer
227
+ import java.net.InetSocketAddress
228
+
229
+ class VerifyCitationSuite extends munit.FunSuite {
230
+ test("an unknown citation is not found") {
231
+ val citator = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0)
232
+ citator.createContext("/lookup", exchange => {
233
+ exchange.sendResponseHeaders(404, -1)
234
+ exchange.close()
235
+ })
236
+ citator.start()
237
+ try {
238
+ val url = s"http://127.0.0.1:${citator.getAddress.getPort}"
239
+ assert(!VerifyCitation.verify(VerifyCitation.Input("1 U.S. 1", "US"), "test-key", url).found)
240
+ } finally citator.stop(0)
241
+ }
242
+ }
243
+ ```
244
+
245
+ `sbt test` runs the tests (anything under `src/test/` is never indexed). To
246
+ see the schemas Kindgi derives:
247
+
248
+ ```sh
249
+ java -cp "$(sbt -batch -error 'export Runtime/fullClasspath')" com.kindgi.pack.Main index --pack-dir .
250
+ ```
251
+
252
+ ## Wiring the tool onto an agent
253
+
254
+ Pass the `Tool`, which pins that tool's version:
255
+
256
+ ```scala
257
+ Agent("acme.brief-writer")
258
+ // …
259
+ .tool(VerifyCitation.tool)
260
+ ```
261
+
262
+ A tool of another pack is `.tool("other.lookup", "^1.0.0")`: its id and a
263
+ semver **range**, and the highest active version matching it is picked at
264
+ turn start. In a flow, `toolNode("verify", VerifyCitation.tool)` runs it.
265
+
266
+ ## Iterating
267
+
268
+ Save the file. `kindgi dev` recompiles through sbt's server, and the next
269
+ call runs the new code. A compile error is reported as `file:line:col`, and
270
+ the last good code keeps serving. Bump the version when callers' contract
271
+ changes (a removed field, a narrower type), not on every save.
272
+
273
+ ## Common mistakes
274
+
275
+ 1. **Copying the sample tool's shape without asking what the tool should do.**
276
+ 2. **A tool as a `def` or a `lazy val`.** It's a file error: make it a `val`.
277
+ 3. **An object not named like its file.** The indexer reads `Greet.scala`'s
278
+ `object Greet`, and a file without one is an error.
279
+ 4. **No description.** The model can't tell when to call the tool.
280
+ 5. **`@Min(0)` in Scala 3.** Name the argument: `@Min(value = 0)`.
281
+ 6. **A primitive inside a type parameter** (`Seq[Int]`, `Option[Long]`). On
282
+ the JVM it's `Object`, so the schema allows any JSON value there. Use a
283
+ case class (`Seq[Item]`), or say the schema with `Tool.json`.
284
+ 7. **Reading `ctx.env` or `ctx.config`, or an undeclared secret.** The first
285
+ two are empty, and `ctx.secrets` holds only what `needsSpec` declares.
286
+ Use `sys.env` for the rest.
287
+ 8. **A library the tool uses as `% Test` or `% Provided`.** It works under
288
+ `kindgi dev` and fails in the image, which ships the runtime classpath
289
+ only.
290
+ 9. **A read-only tool without `readOnly`.** A dry run stops at it, and an
291
+ approval gate asks before it on first use.
292
+ 10. **`readOnly` on a tool that writes.** A dry run then runs it for real.
293
+ 11. **A jackson-module-scala that doesn't match your app's
294
+ `jackson-databind` minor version.** It refuses to load: depend on the
295
+ matching one.
296
+
297
+ ## When the framework itself is the problem
298
+
299
+ If the bug is in Kindgi, kindgi-pack or the Scala layer (a schema derived
300
+ wrong, a misleading error, the pack service misbehaving) and not in the
301
+ tool's code, load `kindgi-framework-feedback` and file it with
302
+ `./kindgiw feedback write`.
@@ -0,0 +1,302 @@
1
+ ---
2
+ name: kindgi-scala-getting-started
3
+ description: >
4
+ Getting a Scala Kindgi pack running: what a pack is, scaffolding one
5
+ (`kindgi init <name> --template=scala`) or adding Kindgi to an existing
6
+ sbt app (`kindgi.config.json`, discovery under `kindgi` packages),
7
+ `./kindgiw dev` through sbt's server, the first agent run, connecting a
8
+ real model, flows, calling the Kindgi API from Scala, building an image,
9
+ and the Scala layer's known limits. Load this when an sbt project has no
10
+ `kindgi.config.json` yet and the user asks to "add Kindgi", "make an
11
+ agent", "set up a pack", or when you are orienting in a Scala pack
12
+ (`kindgi.config.json` with `"language": "scala"`) for the first time.
13
+ Authoring tools, guardrails, agents and flows is covered by
14
+ kindgi-scala-authoring-tools, kindgi-scala-authoring-guardrails,
15
+ kindgi-scala-authoring-agents and kindgi-scala-authoring-flows; models by
16
+ kindgi-authoring-providers.
17
+ type: core
18
+ library: "kindgi-pack-scala"
19
+ version: "0.1.0"
20
+ sdk_version: "0.1.5-rc.0"
21
+ pack_languages: [scala]
22
+ sources:
23
+ - sdks/scala/README.md
24
+ - site/src/content/docs/start/quickstart-scala.md
25
+ ---
26
+
27
+ # Getting started with Kindgi in Scala
28
+
29
+ > **Running `kindgi`:** the pack pins its CLI (`"cli"` in
30
+ > `kindgi.config.json`), and `./kindgiw` runs that version (`kindgiw.cmd` on
31
+ > Windows): through Node's `npx` when Node is installed, else `uvx`. So every
32
+ > `kindgi <command>` below runs as `./kindgiw <command>`. `./kindgiw upgrade`
33
+ > moves the pin, and kindgi-pack-scala's version in `build.sbt` with it.
34
+ >
35
+ > **Preview:** Java and Scala support is tested and supported, but its API
36
+ > may still change in 0.1.6 without the usual deprecation period.
37
+
38
+ ## What a pack is
39
+
40
+ A **pack** is a project Kindgi indexes and runs. Its config is
41
+ `kindgi.config.json` (`"language": "scala"`). Its primitives are the `val`s
42
+ of an object named like its file (`Greet.scala` holds `object Greet`), in
43
+ four kinds of packages:
44
+
45
+ - **Tools** (`…/tools/…`, `Tool[Input, Output](id)`): your Scala code an
46
+ agent or flow calls.
47
+ - **Guardrails** (`…/guardrails/…`, `Guardrail[Config](id)`): checks over an
48
+ agent's turn.
49
+ - **Agents** (`…/agents/…`, `Agent(id)`): data. Instructions, tools,
50
+ capabilities. The model runs in Kindgi.
51
+ - **Flows** (`…/flows/…`, `Flow(id)`): data. Steps (tool or agent nodes) and
52
+ the edges between them.
53
+
54
+ The Scala layer (`com.kindgi %% kindgi-pack-scala`, package
55
+ `com.kindgi.pack.scaladsl`) is thin, over the Java SDK: kindgi-pack's
56
+ indexer reads the pack, and its pack service runs the tools and checks in
57
+ the pack's own JVM, called over HTTP. Everything else runs in the Kindgi
58
+ runtime. It's built for Scala 2.13 and 3.3. In those packages:
59
+ - An object with no primitives, or a file with no object (a case class, a
60
+ trait), is a helper.
61
+ - A primitive defined as a `def` or a `lazy val` is an error: make it a
62
+ `val`.
63
+ - Tests (`src/test/`) are never primitives.
64
+
65
+ ## Scaffold a new pack
66
+
67
+ You need a JDK 17 or later (`JAVA_HOME`) and sbt.
68
+
69
+ ```sh
70
+ npx --yes @kindgi/cli@0.1 init my-pack --template=scala # or: uvx --from "kindgi-cli>=0.1,<0.2" kindgi init …
71
+ cd my-pack
72
+ sbt test # the template's tests: the tools, called directly
73
+ ./kindgiw dev # boots Kindgi locally and runs this pack, recompiling on save
74
+ ```
75
+
76
+ `kindgi dev` needs Docker and Postgres. It starts Postgres in Docker unless
77
+ `KINDGI_DATABASE_URL` points at yours. It compiles through sbt's server
78
+ (`sbt --client`), so a save compiles in about a second once it's warm.
79
+ - When no sbt server is running, it starts one, and stops it when it stops.
80
+ - A server you already run (your IDE's) is used and left running.
81
+ - A compile error is reported as `file:line:col`, and the last good code
82
+ keeps serving.
83
+ - It uses `JAVA_HOME`'s JDK (or `dev.javaHome` in `kindgi.config.json`) and
84
+ the `sbt` on your `PATH` (or `dev.sbt`, such as `["sbt", "-mem", "2048"]`).
85
+ - `SBT_OPTS` reaches sbt, never the pack.
86
+
87
+ ## Add Kindgi to an existing sbt app
88
+
89
+ In the app's directory (where its `build.sbt` is):
90
+
91
+ ```sh
92
+ npx --yes @kindgi/cli@0.1 init # --pack-id=<id> if the build's name doesn't make one
93
+ ./kindgiw dev
94
+ ```
95
+
96
+ `init` writes `kindgi.config.json`:
97
+ - the pack id, from the build's `name`, and its version;
98
+ - the CLI version it pins (`"cli"`, which `./kindgiw` runs, also written);
99
+ - discovery under `kindgi` packages (`src/main/scala/**/kindgi/tools/**/*.scala`
100
+ and so on), so the app's own `tools` packages are never taken for
101
+ Kindgi's.
102
+
103
+ It leaves `build.sbt` alone, and prints the dependency to add (from Maven
104
+ Central, at the CLI's version):
105
+
106
+ ```scala
107
+ libraryDependencies += "com.kindgi" %% "kindgi-pack-scala" % "…"
108
+ ```
109
+
110
+ It also adds these skills and `.gitignore` entries. An app with a
111
+ `build.sbt` next to a `package.json` or a `pom.xml` gets a TypeScript or Java
112
+ pack unless you pass `--template=scala`.
113
+
114
+ A tool there is a `val` of an object in a `kindgi.tools` package under the
115
+ app's own (`com.acme.app.kindgi.tools`), and calls the app's code directly. A
116
+ library a tool uses must be on the runtime classpath (not `% Test` or
117
+ `% Provided`): the image ships the runtime classpath only. `kindgi dev` reads
118
+ the app's `.env` and `.env.local`: keys already there reach the tools as
119
+ environment variables.
120
+
121
+ ## Layout of the template
122
+
123
+ ```
124
+ my-pack/
125
+ ├── kindgi.config.json # "language": "scala", the pack's id and version, the CLI it pins
126
+ ├── build.sbt # kindgi-pack-scala, Scala 3.3, Java 17
127
+ ├── project/build.properties # the sbt version
128
+ ├── kindgiw, kindgiw.cmd # the Kindgi CLI wrapper
129
+ ├── src/main/scala/mypack/
130
+ │ ├── tools/Echo.scala, tools/Greet.scala # Tool[Input, Output](...)
131
+ │ ├── guardrails/ResponseNotEmpty.scala # Guardrail[Config](...)
132
+ │ ├── agents/EchoAgent.scala # Agent(...)
133
+ │ └── flows/EchoFlow.scala # Flow(...)
134
+ ├── src/test/scala/mypack/ToolsSuite.scala # the tools, called directly (munit)
135
+ └── .claude/skills/ # these skills (`./kindgiw skills sync` refreshes them)
136
+ ```
137
+
138
+ The package comes from the pack's id, with Java's and Scala's keywords
139
+ escaped (`my-pack` becomes `mypack`). `kindgi.config.json` also takes
140
+ `discovery`, `dev`, `env`, `environments`, `image` and `providers`.
141
+
142
+ ## First run
143
+
144
+ With `kindgi dev` running, from another terminal in the pack directory:
145
+
146
+ ```sh
147
+ ./kindgiw runs start --agent=my-pack.echo-agent --input='{"userMessage":"Ada"}'
148
+ ./kindgiw runs start --flow=my-pack.echo-flow --input='{"message":"Ada"}'
149
+ ```
150
+
151
+ The agent's answer comes from `dev-echo`, a **fallback** provider a new pack
152
+ gets: no model, no key. It calls the agent's first tool with
153
+ `{"message": <userMessage>}` and replies "⚠ dev-echo isn't a real model: …",
154
+ then "Tool responded: …". The turn carries the `fallback-provider` and
155
+ `dev-echo-not-a-model` warnings. It can't fill in any other tool's input,
156
+ and it can't give a typed answer. For a real model, store an LLM provider's
157
+ key and register its preset (Anthropic below; `./kindgiw providers presets`
158
+ lists OpenAI, Gemini, Groq and OpenRouter too):
159
+
160
+ ```sh
161
+ ./kindgiw secrets set ANTHROPIC_API_KEY --env=local --scope=tenant # no-echo prompt; writes .env.local
162
+ ./kindgiw providers register --preset=anthropic
163
+ ```
164
+
165
+ It takes over at the next turn. That registration is in this project's dev
166
+ database only. To have `kindgi dev` register it on every boot, in every
167
+ worktree and after `--reset`, declare it in `kindgi.config.json`:
168
+ `"providers": [{"preset": "anthropic"}]` (its key, `ANTHROPIC_API_KEY`, comes
169
+ from the env files). Details and other providers: `kindgi-authoring-providers`.
170
+
171
+ To see what Kindgi sees (the index), with no runtime:
172
+
173
+ ```sh
174
+ java -cp "$(sbt -batch -error 'export Runtime/fullClasspath')" com.kindgi.pack.Main index --pack-dir .
175
+ ```
176
+
177
+ ## Flows
178
+
179
+ A flow is data: nodes and edges (`flow.schema.json`). A node's ref may be
180
+ the `Tool` itself:
181
+
182
+ ```scala
183
+ val flow: Flow = Flow("acme.ledger.record-flow")
184
+ .version("0.1.0")
185
+ .toolNode("record", RecordExpense.tool)
186
+ .edge("e-start", "$start", "record")
187
+ .edge("e-end", "record", "$end")
188
+ .build()
189
+ ```
190
+
191
+ A node gets the output of its single upstream node (the run input after
192
+ `$start`), or what its `inputMapping` says. Run one with
193
+ `./kindgiw runs start --flow=<id> --input='{…}'`. For branches, loops and
194
+ agent steps, see `kindgi-scala-authoring-flows`.
195
+
196
+ ## Calling Kindgi from Scala
197
+
198
+ The Java client, `com.kindgi:kindgi-client` (on Maven Central, at the same
199
+ version as the CLI), covers the whole API, with typed models and errors,
200
+ and works from Scala as it is:
201
+
202
+ ```scala
203
+ import com.kindgi.client.Kindgi
204
+ import com.kindgi.client.models.StartRunBody
205
+ import scala.jdk.CollectionConverters._
206
+
207
+ val client = Kindgi.create() // KINDGI_API_URL + KINDGI_API_TOKEN; in dev, the running kindgi dev
208
+ val run = client.runs().start(StartRunBody.WithAgent.builder()
209
+ .agent("my-pack.echo-agent")
210
+ .input(Map[String, AnyRef]("userMessage" -> "Ada").asJava)
211
+ .build())
212
+ val events = client.runs().follow(run.id())
213
+ try events.asScala.foreach(event => println(event.kind()))
214
+ finally events.close()
215
+ ```
216
+
217
+ The methods follow the API's operations: `approvals.reviewers.list` is
218
+ `client.approvals().reviewers().list()`. `client.async()` has the same ones,
219
+ answering `CompletableFuture`s (`scala.jdk.FutureConverters` turns them into
220
+ `Future`s). A refused call throws a typed `KindgiApiException`. The client
221
+ shades its own Jackson, so the app's Jackson is left alone. In production it
222
+ never reads `.kindgirc.json`: set `KINDGI_API_URL` and `KINDGI_API_TOKEN`.
223
+
224
+ ## Your app and Kindgi's data
225
+
226
+ When the app keeps something a run did (a ticket a flow triaged, an answer
227
+ an agent gave), its own row stores the run's id, in a column such as
228
+ `kindgi_run_id`. The app reads the rest through the API, server side:
229
+
230
+ - **Status, output, timing:** `client.runs().get(runId)`.
231
+ - **The audit, step by step:** `client.runs().journal(runId)`.
232
+ - **What it cost:** `client.cost().records().list(…)`, filtered by the run.
233
+ - **When a run finished:** the `run.finished` webhook, not polling.
234
+
235
+ Show it in the app's own UI. **Never:**
236
+
237
+ - **query Kindgi's database**, even on the app's own Postgres server, or map
238
+ its tables in Slick, Doobie or Quill. Its schema is private and changes
239
+ with every release, row-level security guards every tenant query, and a
240
+ runtime Kindgi hosts gives no database access.
241
+ - **link users to Kindgi's console**, or any Kindgi UI, for this data.
242
+
243
+ Docs: https://docs.kindgi.com/v0.1/guides/runs/show-runs-in-your-app/
244
+
245
+ ## Build an image
246
+
247
+ `./kindgiw build --env=<name>` builds the pack's image for an
248
+ `environments.<name>` block of `kindgi.config.json`; `--local` builds it with
249
+ this machine's Docker. sbt builds it in a pinned sbt + JDK 17 image, fetching
250
+ kindgi-pack-scala and kindgi-pack from Maven Central, and copies the runtime
251
+ classpath as jars. The index is built in the image, and the pack service
252
+ runs on a JRE 17 as its entrypoint, as user 65532.
253
+
254
+ Debian packages the code needs are declared in `kindgi.config.json`, and the
255
+ image installs them: `"image": {"systemPackages": ["tesseract-ocr"]}`
256
+ (names, or `name=version`). So are the variables the code reads, names only:
257
+ `"env": {"required": ["DATABASE_URL"], "optional": ["SENTRY_DSN"]}`. A
258
+ deployed pack service missing a required one isn't ready, and its `/readyz`
259
+ names it.
260
+
261
+ ## Known limits
262
+
263
+ - **Scala's primitives inside a type parameter** (`Seq[Int]`,
264
+ `Option[Long]`) are `Object` on the JVM, so the schema allows any JSON
265
+ value there. Use a case class (`Seq[Item]`), or give the schema with
266
+ `Tool.json`.
267
+ - **In Scala 3, name a Java annotation's arguments:** `@Min(value = 0)`, not
268
+ `@Min(0)`.
269
+ - **A Scala 3 enum whose cases take parameters** is a sealed hierarchy, not
270
+ a string: describe it with `@JsonTypeInfo` and `@JsonSubTypes`. A simple
271
+ enum is a string of its case names.
272
+ - **jackson-module-scala must match your app's `jackson-databind` minor
273
+ version.** If your app uses a newer Jackson, depend on the matching
274
+ `jackson-module-scala` yourself.
275
+
276
+ ## Two things need the human
277
+
278
+ - **The pack id and version** in `kindgi.config.json`. The id prefixes every
279
+ primitive (`<pack-id>.<name>`): pick it once.
280
+ - **Model credentials.** Ask for the key; never invent or hard-code one.
281
+
282
+ ## Next
283
+
284
+ - A tool: `kindgi-scala-authoring-tools`.
285
+ - A guardrail: `kindgi-scala-authoring-guardrails`.
286
+ - An agent: `kindgi-scala-authoring-agents`.
287
+ - A flow: `kindgi-scala-authoring-flows`.
288
+ - A real model: `kindgi-authoring-providers`.
289
+ - An external resource (a database) for the coding agent:
290
+ `kindgi-authoring-mcp-servers`.
291
+
292
+ ## Keeping skills up to date
293
+
294
+ `./kindgiw skills sync` refreshes `.claude/skills/` from the CLI's copy
295
+ (local edits are kept unless `--force`). `kindgi dev` says when they are out
296
+ of date.
297
+
298
+ ## When the framework itself is the problem
299
+
300
+ If the bug is in Kindgi, kindgi-pack or the Scala layer and not in the
301
+ pack's code, load `kindgi-framework-feedback` and file it with
302
+ `./kindgiw feedback write`.
@@ -0,0 +1,3 @@
1
+ wrapperVersion=3.3.4
2
+ distributionType=only-script
3
+ distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
@@ -0,0 +1,31 @@
1
+ # AGENTS.md
2
+
3
+ This directory is a Kindgi pack written in Java (`com.kindgi:kindgi-pack`).
4
+ Tools (`Tool.define(...)`) and guardrail checks (`Guardrail.define(...)`) are
5
+ `public static final` fields of classes under `src/main/java/**/tools/` and
6
+ `…/guardrails/`; agents (`Agent.define(...)`) and flows (`Flow.define(...)`) are
7
+ data, under `…/agents/` and `…/flows/`. A tool's input and output schemas come
8
+ from its record types (Jakarta Validation constraints become their keywords). A
9
+ helper class there is package-private, or a record, an enum or an interface.
10
+ The config is `kindgi.config.json`.
11
+
12
+ - `kindgi dev` boots Kindgi locally, compiles this pack with Maven and runs it
13
+ with its JDK (17 or later), recompiling on every save.
14
+ - `./mvnw test` runs the tests; `Tool.call(input, ToolContext.forTest())` calls
15
+ a handler directly.
16
+ - `java -cp "target/classes:$(cat target/classpath.txt)" com.kindgi.pack.Main index --pack-dir .`
17
+ shows what Kindgi sees, after
18
+ `./mvnw -q compile dependency:build-classpath -Dmdep.outputFile=target/classpath.txt`.
19
+ - Agents answer through a model provider. `kindgi dev` gives a new pack
20
+ `dev-echo`, a fallback that isn't a model: it calls the first tool and
21
+ replies "Tool responded: …" after a warning line, while no other provider
22
+ fits. For a real model, put one LLM provider's key in `.env`
23
+ (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `GROQ_API_KEY` or
24
+ `OPENROUTER_API_KEY`) and add a `providers` list with its preset
25
+ (`[{"preset": "anthropic"}]`, or `"openai"`, `"gemini-api"`, `"groq"`,
26
+ `"openrouter"`) to `kindgi.config.json`: `kindgi dev` then registers it on
27
+ every boot, in every worktree.
28
+
29
+ When you diagnose a framework bug (something in Kindgi itself, not in this
30
+ pack's code), append an entry to `FEEDBACK.md` at the pack root with
31
+ `kindgi feedback write`.