@kindgi/cli 0.1.0 → 0.1.2

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 (151) hide show
  1. package/README.md +79 -22
  2. package/dist/build/bundle.d.ts +5 -2
  3. package/dist/build/bundle.d.ts.map +1 -1
  4. package/dist/build/bundle.js +8 -4
  5. package/dist/build/bundle.js.map +1 -1
  6. package/dist/build/containerfile.d.ts.map +1 -1
  7. package/dist/build/containerfile.js +1 -0
  8. package/dist/build/containerfile.js.map +1 -1
  9. package/dist/build/defaults.d.ts +3 -3
  10. package/dist/build/defaults.d.ts.map +1 -1
  11. package/dist/build/defaults.js +20 -12
  12. package/dist/build/defaults.js.map +1 -1
  13. package/dist/build/host-install.d.ts +52 -0
  14. package/dist/build/host-install.d.ts.map +1 -1
  15. package/dist/build/host-install.js +68 -0
  16. package/dist/build/host-install.js.map +1 -1
  17. package/dist/build/python-image.d.ts +2 -0
  18. package/dist/build/python-image.d.ts.map +1 -1
  19. package/dist/build/python-image.js +12 -1
  20. package/dist/build/python-image.js.map +1 -1
  21. package/dist/build/runners.d.ts +6 -5
  22. package/dist/build/runners.d.ts.map +1 -1
  23. package/dist/commands/auth.d.ts +22 -0
  24. package/dist/commands/auth.d.ts.map +1 -1
  25. package/dist/commands/auth.js +197 -2
  26. package/dist/commands/auth.js.map +1 -1
  27. package/dist/commands/build.d.ts +7 -0
  28. package/dist/commands/build.d.ts.map +1 -1
  29. package/dist/commands/build.js +73 -42
  30. package/dist/commands/build.js.map +1 -1
  31. package/dist/commands/dev.d.ts +1 -2
  32. package/dist/commands/dev.d.ts.map +1 -1
  33. package/dist/commands/dev.js +136 -58
  34. package/dist/commands/dev.js.map +1 -1
  35. package/dist/commands/helpers.d.ts +14 -3
  36. package/dist/commands/helpers.d.ts.map +1 -1
  37. package/dist/commands/helpers.js +20 -3
  38. package/dist/commands/helpers.js.map +1 -1
  39. package/dist/commands/init.d.ts.map +1 -1
  40. package/dist/commands/init.js +2 -3
  41. package/dist/commands/init.js.map +1 -1
  42. package/dist/commands/key.d.ts.map +1 -1
  43. package/dist/commands/key.js +143 -11
  44. package/dist/commands/key.js.map +1 -1
  45. package/dist/commands/providers.d.ts.map +1 -1
  46. package/dist/commands/providers.js +11 -1
  47. package/dist/commands/providers.js.map +1 -1
  48. package/dist/commands/runs.d.ts.map +1 -1
  49. package/dist/commands/runs.js +17 -15
  50. package/dist/commands/runs.js.map +1 -1
  51. package/dist/commands/secrets.d.ts +1 -4
  52. package/dist/commands/secrets.d.ts.map +1 -1
  53. package/dist/commands/secrets.js +7 -55
  54. package/dist/commands/secrets.js.map +1 -1
  55. package/dist/commands/test.js +1 -1
  56. package/dist/commands/test.js.map +1 -1
  57. package/dist/commands/tools.d.ts.map +1 -1
  58. package/dist/commands/tools.js +11 -2
  59. package/dist/commands/tools.js.map +1 -1
  60. package/dist/commands/unwired.d.ts +5 -0
  61. package/dist/commands/unwired.d.ts.map +1 -1
  62. package/dist/commands/unwired.js +11 -0
  63. package/dist/commands/unwired.js.map +1 -1
  64. package/dist/context.d.ts +9 -0
  65. package/dist/context.d.ts.map +1 -1
  66. package/dist/context.js +1 -0
  67. package/dist/context.js.map +1 -1
  68. package/dist/dev/bundler.d.ts +2 -0
  69. package/dist/dev/bundler.d.ts.map +1 -1
  70. package/dist/dev/bundler.js +91 -10
  71. package/dist/dev/bundler.js.map +1 -1
  72. package/dist/dev/defaults.d.ts +8 -6
  73. package/dist/dev/defaults.d.ts.map +1 -1
  74. package/dist/dev/defaults.js +78 -60
  75. package/dist/dev/defaults.js.map +1 -1
  76. package/dist/dev/dev-only-imports.d.ts +15 -0
  77. package/dist/dev/dev-only-imports.d.ts.map +1 -0
  78. package/dist/dev/dev-only-imports.js +57 -0
  79. package/dist/dev/dev-only-imports.js.map +1 -0
  80. package/dist/dev/docker-compose.dev.yml +19 -7
  81. package/dist/dev/pack-service.d.ts +8 -0
  82. package/dist/dev/pack-service.d.ts.map +1 -1
  83. package/dist/dev/pack-service.js +1 -0
  84. package/dist/dev/pack-service.js.map +1 -1
  85. package/dist/dev/postgres-container.d.ts +77 -0
  86. package/dist/dev/postgres-container.d.ts.map +1 -0
  87. package/dist/dev/postgres-container.js +346 -0
  88. package/dist/dev/postgres-container.js.map +1 -0
  89. package/dist/dev/runners.d.ts +36 -11
  90. package/dist/dev/runners.d.ts.map +1 -1
  91. package/dist/dev/runtime-container.d.ts +11 -2
  92. package/dist/dev/runtime-container.d.ts.map +1 -1
  93. package/dist/dev/runtime-container.js +16 -7
  94. package/dist/dev/runtime-container.js.map +1 -1
  95. package/dist/dev/runtime-image.d.ts +15 -2
  96. package/dist/dev/runtime-image.d.ts.map +1 -1
  97. package/dist/dev/runtime-image.js +31 -2
  98. package/dist/dev/runtime-image.js.map +1 -1
  99. package/dist/dev/runtime-registry.d.ts +73 -0
  100. package/dist/dev/runtime-registry.d.ts.map +1 -0
  101. package/dist/dev/runtime-registry.js +111 -0
  102. package/dist/dev/runtime-registry.js.map +1 -0
  103. package/dist/errors.d.ts.map +1 -1
  104. package/dist/errors.js +5 -1
  105. package/dist/errors.js.map +1 -1
  106. package/dist/init/augment-scaffolder.d.ts +12 -0
  107. package/dist/init/augment-scaffolder.d.ts.map +1 -1
  108. package/dist/init/augment-scaffolder.js +93 -14
  109. package/dist/init/augment-scaffolder.js.map +1 -1
  110. package/dist/init/pnpm-workspace-patcher.d.ts +55 -0
  111. package/dist/init/pnpm-workspace-patcher.d.ts.map +1 -0
  112. package/dist/init/pnpm-workspace-patcher.js +248 -0
  113. package/dist/init/pnpm-workspace-patcher.js.map +1 -0
  114. package/dist/init/template-files.d.ts +2 -0
  115. package/dist/init/template-files.d.ts.map +1 -1
  116. package/dist/init/template-files.js +16 -1
  117. package/dist/init/template-files.js.map +1 -1
  118. package/dist/main.d.ts +7 -0
  119. package/dist/main.d.ts.map +1 -1
  120. package/dist/main.js +1 -0
  121. package/dist/main.js.map +1 -1
  122. package/dist/parse.d.ts +6 -0
  123. package/dist/parse.d.ts.map +1 -1
  124. package/dist/parse.js +1 -0
  125. package/dist/parse.js.map +1 -1
  126. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +3 -4
  127. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +12 -9
  128. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +21 -9
  129. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +1 -1
  130. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +10 -9
  131. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +26 -5
  132. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +1 -1
  133. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +58 -8
  134. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +1 -1
  135. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +12 -9
  136. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +10 -7
  137. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +8 -2
  138. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +37 -4
  139. package/dist/templates/minimal/package.json.tmpl +1 -1
  140. package/dist/templates/minimal/pnpm-workspace.yaml +6 -4
  141. package/dist/templates/sample/guardrails/response-not-empty/index.ts.tmpl +14 -6
  142. package/dist/templates/sample/package.json.tmpl +1 -1
  143. package/dist/templates/sample/pnpm-workspace.yaml +6 -4
  144. package/dist/terminal-input.d.ts +17 -0
  145. package/dist/terminal-input.d.ts.map +1 -0
  146. package/dist/terminal-input.js +88 -0
  147. package/dist/terminal-input.js.map +1 -0
  148. package/package.json +13 -12
  149. /package/dist/templates/minimal/{.gitignore → gitignore} +0 -0
  150. /package/dist/templates/python/{.gitignore → gitignore} +0 -0
  151. /package/dist/templates/sample/{.gitignore → gitignore} +0 -0
@@ -15,8 +15,8 @@ description: >
15
15
  kindgi-authoring-agents.
16
16
  type: core
17
17
  library: "@kindgi/sdk"
18
- version: "0.3.5"
19
- sdk_version: "0.1.0"
18
+ version: "0.3.6"
19
+ sdk_version: "0.1.2"
20
20
  pack_languages: [node]
21
21
  sources:
22
22
  - packages/guardrails/src/types.ts
@@ -107,11 +107,17 @@ How the pack tooling reads this file:
107
107
  `configZod`, `configSchema` or `configJsonSchema`, or a top-level
108
108
  `configZod` / `configSchema`), and the declaration's `config` — what
109
109
  the check runs with. It does not record `description`, `budget` or
110
- `judgeCapabilities`.
110
+ `judgeCapabilities`. It checks `config` (none counts as `{}`) against
111
+ the config schema: a config that doesn't fit, or a required field with
112
+ no default left out, is a file error naming where, and `kindgi build`
113
+ refuses the pack.
111
114
  - The **pack service** loads the same module to run the check. It uses
112
115
  the module's `evaluate` export, or the `default` / `check` export when
113
116
  that is a function or has an `evaluate` method — here, the named
114
- `check` export.
117
+ `check` export. A `defineCheck` check's `evaluate` gets the config its
118
+ schema resolves: the schema's defaults applied (a guardrail that
119
+ declares no config gets them all), and a config that doesn't fit
120
+ refused, naming where.
115
121
 
116
122
  ## Validating a declaration in-process
117
123
 
@@ -167,7 +173,10 @@ available to the runtime that evaluates it.
167
173
  - **`config`** — the check's parameters, validated against the check's
168
174
  `configSchema` by `defineGuardrail`. In a pack, the declaration's
169
175
  `config` goes into the index and the check runs with it; without one
170
- it runs with `{}`. `evaluate` receives the config as declared —
176
+ it runs with `{}`. A declaration a pack file default-exports isn't run
177
+ through `defineGuardrail`, so nothing validates its `config`: keep it
178
+ valid against the schema yourself. `evaluate` receives the config as
179
+ declared —
171
180
  schema defaults are not filled in — so handle absent optional fields.
172
181
  - **`action.on-violation`** — `'halt'`, `'retry'` (with
173
182
  `retry.maxAttempts`, 1–10), `'escalate'` (with `escalateTo`),
@@ -177,7 +186,9 @@ available to the runtime that evaluates it.
177
186
  any other action are reported in `AgentTurnResult.violations` and the
178
187
  turn completes. The action handlers in `@kindgi/guardrails`
179
188
  (`retryHandler`, `escalateHandler`, `compensateHandler`, …) record the
180
- intent for callers that act on it.
189
+ intent for callers that act on it. In 0.1 the runtime acts only on
190
+ `halt`: `retry`, `escalate` and `compensate` are recorded on the
191
+ violation, with no second attempt, escalation or compensating call.
181
192
  - **`severity`** — `'info'` / `'warn'` / `'error'` (the default) /
182
193
  `'critical'`. Orthogonal to `action`: logs and dashboards group by
183
194
  severity; execution follows the action. A `log-only` guardrail can
@@ -236,8 +247,9 @@ guardrails: ['acme.no-fabricated-quotes'],
236
247
 
237
248
  At the start of each turn, the runtime resolves these ids against the
238
249
  guardrails available to the run. An id that isn't registered fails the
239
- turn with `unresolved-guardrail`, so register the guardrail before an
240
- agent references it.
250
+ turn before the model is called (`Error [invalid-request]: Agent "…"
251
+ references guardrails not in the registry: <id>`), so register the
252
+ guardrail before an agent references it.
241
253
 
242
254
  ## Changing a guardrail
243
255
 
@@ -277,7 +289,7 @@ ready for the stricter enforcement.
277
289
  - Type surface: hover any `@kindgi/sdk/define` export for full JSDoc;
278
290
  `Guardrail`, `defineGuardrail` and the built-in checks are in
279
291
  `@kindgi/guardrails`.
280
- - Companion docs: `pnpm --filter @kindgi/sdk exec typedoc`.
292
+ - API reference: https://docs.kindgi.com/v0.1/reference/typescript/sdk/kindgi/sdk/define/
281
293
  - Built-in check implementations: `packages/guardrails/src/checks.ts`.
282
294
 
283
295
  ## When the framework itself is the problem
@@ -18,7 +18,7 @@ description: >
18
18
  type: core
19
19
  library: "@kindgi/sdk"
20
20
  version: "0.3.0"
21
- sdk_version: "0.1.0"
21
+ sdk_version: "0.1.2"
22
22
  pack_languages: [node, python]
23
23
  ---
24
24
 
@@ -22,8 +22,8 @@ description: >
22
22
  kindgi-getting-started.
23
23
  type: core
24
24
  library: "@kindgi/sdk"
25
- version: "0.9.1"
26
- sdk_version: "0.1.0"
25
+ version: "0.9.2"
26
+ sdk_version: "0.1.2"
27
27
  pack_languages: [node, python]
28
28
  sources:
29
29
  - packages/adapters/model-anthropic/src/provider.ts
@@ -492,15 +492,12 @@ into one entry per model (`metadata.models[]`), filters the resulting
492
492
  tenant policy), then sorts survivors in this order:
493
493
 
494
494
  1. **Preferred provider / model.** Tuples matching the agent's
495
- `preferredProvider` (and `preferredModel`, when the `Agent` object
496
- carries one) are promoted to the front.
495
+ `preferredProvider` and `preferredModel` are promoted to the front.
497
496
  - Both set → promote the exact tuple.
498
497
  - Only `preferredModel` set → promote any provider exposing that model.
499
498
  - Only `preferredProvider` set → promote every model of that provider.
500
- `defineAgent` accepts `preferredProvider` but not `preferredModel`
501
- (`DefineAgentSpec` has no such field), so agents built with it can
502
- only express a provider preference here. A Python `Agent` takes
503
- both (`preferred_provider=`, `preferred_model=`).
499
+ `defineAgent` takes both (`preferredProvider`, `preferredModel`), and
500
+ so does a Python `Agent` (`preferred_provider=`, `preferred_model=`).
504
501
  2. **`capability.prefer[]` weights.** If the agent's capability
505
502
  declares `prefer: [{feature: 'thinking', weight: 3}, ...]`, tuples
506
503
  with matching model features (or provider attributes) get higher
@@ -597,7 +594,11 @@ defineAgent({
597
594
  be the FULL npm package name of the adapter — `"@kindgi/adapter-model-anthropic"`,
598
595
  NOT `"anthropic"`. Adapters are registered with the runtime under
599
596
  their full package names, and a short name matches none of them, so
600
- the registration fails. Confirm valid ids with `kindgi adapters list`.
597
+ the registration fails. The model adapters are
598
+ `@kindgi/adapter-model-anthropic`, `@kindgi/adapter-model-gemini`,
599
+ `@kindgi/adapter-model-openai-compat` and
600
+ `@kindgi/adapter-model-in-process`; `kindgi providers presets` shows
601
+ the id each preset uses.
601
602
 
602
603
  1. **`envName` mismatch between the setter (`kindgi secrets set` or `env set`) and `provider.json`.**
603
604
  Both writers use `--env=<name>` (default `local`): `local` is the
@@ -12,8 +12,8 @@ description: >
12
12
  authoring agents is covered by kindgi-authoring-agents.
13
13
  type: core
14
14
  library: "@kindgi/sdk"
15
- version: "0.4.1"
16
- sdk_version: "0.1.0"
15
+ version: "0.4.4"
16
+ sdk_version: "0.1.2"
17
17
  pack_languages: [node]
18
18
  sources:
19
19
  - packages/tools/src/types.ts
@@ -108,7 +108,7 @@ A handler must return a Promise; one with nothing to `await` can return `Promise
108
108
  The handler gets the **parsed** input, typed `z.infer` of `input` (Zod's output type):
109
109
 
110
110
  - **Defaults.** A `.default()` field is optional to the caller, the model included. The tool's advertised schema doesn't list it as required, and the handler always gets a value.
111
- - **Transforms and refinements.** `.transform()` results and `.refine()` checks apply before the handler runs. A failed refinement comes back as `input-validation-failed`, with the field's path.
111
+ - **Transforms and refinements.** `.transform()` results and `.refine()` checks apply before the handler runs. A failed refinement comes back as `input-validation-failed`.
112
112
  - **Extra keys.** A plain `z.object` accepts them and strips them. Use `z.strictObject` to reject them.
113
113
  - **JSON-Schema-authored tools** get each property's `default` filled in the same way.
114
114
 
@@ -268,13 +268,34 @@ run start via `semver.maxSatisfying`. No implicit `:latest`.
268
268
  changes (breaking schema shape, semantic behavior), not when you
269
269
  save. See the "Iterating on a tool" section above.
270
270
 
271
+ 9. **A package a tool imports, listed only in `devDependencies`.** The
272
+ deployed pack installs the app's production dependencies only, so the
273
+ import works under `kindgi dev` and fails in the image. When a tool
274
+ imports a new package (an ORM client such as `@prisma/client`, an API
275
+ SDK), check that the app's `package.json` lists it under
276
+ `dependencies`. Build-time tools (the `prisma` CLI, `typescript`) stay
277
+ in `devDependencies`. `kindgi dev` warns as soon as a tool imports one
278
+ ("⚠ The pack imports @prisma/client (in kindgi/tools/…), which
279
+ package.json lists only in devDependencies: …"), and `kindgi build`
280
+ refuses the pack until it moves.
281
+ 10. **A tool that needs the app's install scripts in the image.** The
282
+ image installs with scripts off, so the app's `postinstall` /
283
+ `prepare` (`prisma generate`, husky) don't run there; `kindgi build`
284
+ lists them ("✓ The app's own install scripts don't run in the image:
285
+ …"). A tool that uses Prisma's client then fails the build ("@prisma/client
286
+ did not initialize yet"). Add `prisma({ schema: 'prisma/schema.prisma' })`
287
+ (from `@kindgi/sdk/build`; add `config: 'prisma.config.ts'` when the app
288
+ has one) to `image.extensions` in `kindgi.config.ts`. Other generate
289
+ steps: `defineBuildExtension({ name, contextFiles, postInstall: [{ bin, args }] })`.
290
+ Debian packages: `image.systemPackages`. Placeholder env for those steps:
291
+ `image.buildEnv` (never secrets).
292
+
271
293
  ## References
272
294
 
273
295
  - Type surface: `hover any @kindgi/sdk/define export` in your editor
274
296
  for full JSDoc — every field on `DefineToolSpec` / `ToolManifest`
275
297
  documents purpose, when to set it, and gotchas.
276
- - Companion docs: `pnpm --filter @kindgi/sdk exec typedoc` regenerates
277
- markdown API docs at `packages/sdk/docs/`.
298
+ - API reference: https://docs.kindgi.com/v0.1/reference/typescript/sdk/kindgi/sdk/define/ (every `define*` spec, field by field).
278
299
  - Common patterns: check the `sample` template (`kindgi init
279
300
  --template=sample`) for working examples of both authoring modes.
280
301
 
@@ -15,7 +15,7 @@ description: >
15
15
  type: core
16
16
  library: "@kindgi/sdk"
17
17
  version: "0.4.0"
18
- sdk_version: "0.1.0"
18
+ sdk_version: "0.1.2"
19
19
  pack_languages: [node, python]
20
20
  ---
21
21
 
@@ -14,8 +14,8 @@ description: >
14
14
  primitive.
15
15
  type: core
16
16
  library: "@kindgi/sdk"
17
- version: "0.3.2"
18
- sdk_version: "0.1.0"
17
+ version: "0.3.5"
18
+ sdk_version: "0.1.2"
19
19
  pack_languages: [node]
20
20
  ---
21
21
 
@@ -70,7 +70,9 @@ pnpm install # or the app's own package manager
70
70
 
71
71
  This adds `kindgi.config.ts` and a `kindgi/` folder beside the app's code,
72
72
  and never creates env files: `kindgi dev` reads the app's own `.env` /
73
- `.env.local`.
73
+ `.env.local`. A package a tool imports must be in the app's `dependencies`,
74
+ not `devDependencies`: the deployed pack installs production dependencies
75
+ only (see `kindgi-authoring-tools`).
74
76
 
75
77
  Either way, `init` adds `@kindgi/sdk` and `@kindgi/cli` to the project's
76
78
  `package.json`, so the project runs the `kindgi` it pins — never a global
@@ -95,22 +97,28 @@ needs on first run), indexes the pack, registers every primitive, and
95
97
  re-registers on every save. The banner prints the API URL, the seeded
96
98
  bearer token, and (if the console is bundled) the `/console/` URL.
97
99
 
98
- The local runtime includes a built-in `demo.echo-agent` you can hit to
99
- verify the harness before authoring anything.
100
+ Until a model provider is registered, agents answer with `dev-echo`, a
101
+ stand-in that calls the agent's first tool with `{"message": <userMessage>}`
102
+ and replies with what the tool returned. It checks the wiring only: it can't
103
+ fill in any other tool input or produce a typed `output` (that turn fails
104
+ with `output-schema-violation`). Register a provider
105
+ (`kindgi-authoring-providers`) before building a real agent.
100
106
 
101
107
  ## First run
102
108
 
103
109
  From a second terminal, with `cd my-pack`:
104
110
 
105
111
  ```bash
106
- pnpm exec kindgi runs start --agent=demo.echo-agent --input='{"userMessage":"hi"}'
112
+ pnpm exec kindgi runs start --agent=my-pack.echo-agent --input='{"userMessage":"hi"}'
107
113
  ```
108
114
 
115
+ `my-pack.echo-agent` is the agent the `sample` template ships (`<pack-id>.echo-agent`);
116
+ a `minimal` pack has no agent until you write one.
117
+
109
118
  The CLI reads `.kindgirc.json` (auto-written by `kindgi dev`) for the
110
119
  API URL + token, so second-terminal commands work without flags.
111
120
 
112
- Once you author your own agent, replace `demo.echo-agent` with your
113
- own id.
121
+ Once you author your own agent, run it by its own id.
114
122
 
115
123
  ## Layout
116
124
 
@@ -153,6 +161,48 @@ Most of the setup is automatable, but two require your knowledge:
153
161
  registered — `kindgi providers register --preset=anthropic` with the
154
162
  key in `.env`; see `kindgi-authoring-providers`.
155
163
 
164
+ ## Your app and Kindgi's data
165
+
166
+ When the app keeps something a run did (a ticket a flow triaged, an answer
167
+ an agent gave), its own row stores the run's id, in a column such as
168
+ `kindgi_run_id`. The app starts the run and reads the rest through the API,
169
+ server side, with `createClient()` from `@kindgi/sdk/client`:
170
+
171
+ ```ts
172
+ import { createClient } from '@kindgi/sdk/client';
173
+
174
+ const kindgi = createClient(); // KINDGI_API_URL + KINDGI_API_TOKEN
175
+ const run = await kindgi.runs.start({
176
+ flow: 'my-pack.triage-ticket',
177
+ input: { ticketId },
178
+ options: { wait: false }, // the run id now; run.finished tells you when it ends
179
+ });
180
+ // save run.id as the ticket's kindgi_run_id
181
+ ```
182
+
183
+
184
+ - **Status, output, timing:** `kindgi.runs.get(runId)`
185
+ (`GET /v1/runs/{runId}`); status and timing only: `kindgi.runs.progress(runId)`.
186
+ - **The audit, step by step:** `kindgi.runs.journal(runId)`
187
+ (`GET /v1/runs/{runId}/journal`).
188
+ - **Where an agent's answer came from:** `kindgi.provenance.get(runId)`
189
+ (`GET /v1/provenance/{runId}`). A flow run has none of its own: each agent
190
+ step's `step.completed` entry in the flow's journal names its turn's run
191
+ (`payload.output.runId`).
192
+ - **When a run finished:** the `run.finished` webhook (the run's id and
193
+ outcome, no output; then `runs.get`), not polling.
194
+
195
+ Show it in the app's own UI. **Never:**
196
+
197
+ - **query Kindgi's database**, even on the app's own Postgres server, and
198
+ never map its tables into the app's ORM. Its schema is private and changes
199
+ with every release (migrations only go forward), row-level security guards
200
+ every tenant query, and a runtime Kindgi hosts gives no database access.
201
+ - **link users to Kindgi's console** or any Kindgi UI for this data.
202
+
203
+ To keep a copy (reporting, search), pull it through the API into the app's
204
+ own tables. Docs: https://docs.kindgi.com/v0.1/guides/runs/show-runs-in-your-app/
205
+
156
206
  ## References
157
207
 
158
208
  - Full CLI surface: `kindgi --help`.
@@ -16,7 +16,7 @@ description: >
16
16
  type: core
17
17
  library: "kindgi (Python)"
18
18
  version: "0.1.0"
19
- sdk_version: "0.1.0"
19
+ sdk_version: "0.1.2"
20
20
  pack_languages: [python]
21
21
  sources:
22
22
  - sdks/python/src/kindgi/pack/define.py
@@ -16,8 +16,8 @@ description: >
16
16
  kindgi-python-authoring-agents.
17
17
  type: core
18
18
  library: "kindgi (Python)"
19
- version: "0.1.0"
20
- sdk_version: "0.1.0"
19
+ version: "0.1.1"
20
+ sdk_version: "0.1.2"
21
21
  pack_languages: [python]
22
22
  sources:
23
23
  - sdks/python/src/kindgi/pack/define.py
@@ -200,9 +200,11 @@ the condition is true. Conditions are dicts:
200
200
  | `and` `or` | `{"op", "children": [...]}` |
201
201
  | `not` | `{"op", "child"}` |
202
202
 
203
- Each operand is `{"literal": …}` or `{"path": …}`. A comparison whose
204
- path doesn't resolve is **false**, `ne` included. So to branch on "not
205
- billing", write `not` around the `eq` (as above), not `ne`. A condition
203
+ Each operand is `{"literal": …}` or `{"path": …}`. When a path doesn't
204
+ resolve, `eq`, `lt`, `lte`, `gt` and `gte` are false and `ne` is true. So
205
+ for the "otherwise" branch, write `not` around the condition (as above),
206
+ rather than a second comparison: it covers exactly what the first edge
207
+ doesn't. A condition
206
208
  used twice is easiest as a module-level constant (`IS_BILLING`).
207
209
 
208
210
  **Joining branches.** A node with several incoming edges runs once every
@@ -227,7 +229,7 @@ A node with several incoming edges ignores them.
227
229
  Its keys are the tool's input **as it travels**: a pydantic field's name,
228
230
  or its alias if it has one (a `customer_id` field is the key
229
231
  `customer_id`; with `alias="customerId"`, it's `customerId`). Paths are
230
- dot-separated, with no array indexing, rooted at:
232
+ dot-separated (a number segment indexes an array: `items.0.sku`), rooted at:
231
233
  - `runInput.…`: the input the run was started with;
232
234
  - `nodeOutputs.<nodeId>.…`: a step's output. For an agent step, add
233
235
  `.output.<field>` to read its typed answer;
@@ -289,9 +291,10 @@ the output), not on every save.
289
291
  1. **Building a flow without asking what goes in and comes out.** The
290
292
  pack's `echo_flow` proves the runtime works. It isn't a template for
291
293
  the user's flow.
292
- 2. **`ne` on a path that may be missing, to mean "otherwise".** A missing
293
- path makes every comparison false, so neither branch fires and
294
- everything after is skipped. Use `not` around the positive condition.
294
+ 2. **A second comparison for "otherwise".** On a path that may be
295
+ missing, `eq` is false and `ne` is true, and `lt`/`gt` are both false,
296
+ so a hand-written opposite can miss a case or overlap. Use `not` around
297
+ the positive condition: it covers exactly what the first edge doesn't.
295
298
  3. **Reading an agent step's answer at `nodeOutputs.<step>.<field>`.**
296
299
  The typed answer is under `.output`: `nodeOutputs.<step>.output.<field>`.
297
300
  An agent without `output=` has only `text`.
@@ -14,8 +14,8 @@ description: >
14
14
  kindgi-python-authoring-tools.
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
- version: "0.1.0"
18
- sdk_version: "0.1.0"
17
+ version: "0.1.1"
18
+ sdk_version: "0.1.2"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/src/kindgi/pack/define.py
@@ -106,7 +106,9 @@ def no_fabricated_quotes(config: Config, trace: RunTrace) -> CheckResult:
106
106
  In an agent turn a failed `halt` guardrail fails the turn
107
107
  (`guardrail-violation`) and the answer is not stored; any other action
108
108
  reports the failure in the turn result's `violations` and the turn
109
- completes.
109
+ completes. In 0.1 the runtime acts only on `halt`: `retry`, `escalate`
110
+ and `compensate` are recorded on the violation, with no second attempt,
111
+ escalation or compensating call.
110
112
  - **`severity`** — `"info"`, `"warn"`, `"error"` (default), `"critical"`.
111
113
  Independent of the action: dashboards group by severity, execution
112
114
  follows the action.
@@ -147,8 +149,9 @@ brief_writer = Agent(..., guardrails=[no_fabricated_quotes])
147
149
  ```
148
150
 
149
151
  The `Guardrail` object (or its id). `kindgi dev` registers the pack's
150
- guardrails; an agent naming an id with no registered guardrail fails
151
- its turn (`unresolved-guardrail`).
152
+ guardrails; an agent naming an id with no registered guardrail fails the
153
+ turn before the model is called (`Error [invalid-request]: Agent "…"
154
+ references guardrails not in the registry: <id>`).
152
155
 
153
156
  ## Common mistakes
154
157
 
@@ -158,8 +161,8 @@ its turn (`unresolved-guardrail`).
158
161
  2. **Snake_case keys in `config=`.** It is keyed like the wire — the
159
162
  model's aliases (`{"minLookups": 2}`), not the field names.
160
163
  3. **Both `on_violation=` and `action=`, or neither** — `DefinitionError`.
161
- 4. **Expecting retries from `halt`.** `halt` stops the turn; use
162
- `action={"on-violation": "retry", …}` for another attempt.
164
+ 4. **Expecting another attempt.** `halt` stops the turn, and in 0.1
165
+ `retry` doesn't run the turn again: it's only recorded.
163
166
  5. **Calling a model from the check.** Not available; keep checks pure.
164
167
  6. **Raising for a broken rule.** Return `CheckResult(passed=False,
165
168
  reason=…)`; an exception is an evaluation error, not a violation.
@@ -14,8 +14,8 @@ description: >
14
14
  kindgi-python-getting-started.
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
- version: "0.1.0"
18
- sdk_version: "0.1.0"
17
+ version: "0.1.1"
18
+ sdk_version: "0.1.2"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/src/kindgi/pack/define.py
@@ -290,6 +290,12 @@ removed field, a narrower type — not on every save.
290
290
  and an agent's tool approval gate asks before it on first use.
291
291
  10. **`mutating=False` on a tool that writes.** A dry run then runs it
292
292
  for real.
293
+ 11. **A package a tool imports, only in a dev group.** The deployed pack
294
+ installs without dev dependencies (`uv sync --no-dev`, or Poetry's
295
+ main group only), so the import works under `kindgi dev` and fails in
296
+ the image. Put what tools import in `[project].dependencies` (in a
297
+ Poetry 1 app, `[tool.poetry.dependencies]`); test and build tools stay
298
+ in dev groups.
293
299
 
294
300
  ## When the framework itself is the problem
295
301
 
@@ -14,8 +14,8 @@ description: >
14
14
  kindgi-python-authoring-agents; models by kindgi-authoring-providers.
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
- version: "0.1.0"
18
- sdk_version: "0.1.0"
17
+ version: "0.1.3"
18
+ sdk_version: "0.1.2"
19
19
  pack_languages: [python]
20
20
  sources:
21
21
  - sdks/python/README.md
@@ -26,7 +26,7 @@ sources:
26
26
  # Getting started with Kindgi in Python
27
27
 
28
28
  > **Running `kindgi`:** a Python pack has no Node project, so the
29
- > `kindgi` CLI (a Node 22+ program) is the one on `PATH`. Python
29
+ > `kindgi` CLI (a Node 22.12+ program) is the one on `PATH`. Python
30
30
  > commands run in the pack's environment: `uv run …`.
31
31
 
32
32
  ## What a pack is
@@ -90,7 +90,9 @@ name (`from acme.text import normalize`); inside `kindgi/`, import the pack's
90
90
  modules relatively. Don't add an `__init__.py` to `kindgi/` — the folder
91
91
  would then shadow the `kindgi` package. `kindgi dev` reads the app's `.env`
92
92
  / `.env.local` — keys already there reach the tools as environment
93
- variables.
93
+ variables. A package a tool imports must be in the app's main dependencies,
94
+ not a dev group: the deployed pack installs without dev dependencies (see
95
+ `kindgi-python-authoring-tools`).
94
96
 
95
97
  ## Layout of the template
96
98
 
@@ -180,6 +182,37 @@ for event in client.runs.stream(str(run.id)):
180
182
  `AsyncKindgi` is the asyncio twin. `kindgi dev` prints the URL and the
181
183
  token; `.kindgirc.json` in the pack holds them for the CLI.
182
184
 
185
+ ## Your app and Kindgi's data
186
+
187
+ When the app keeps something a run did (a ticket a flow triaged, an answer
188
+ an agent gave), its own row stores the run's id, in a column such as
189
+ `kindgi_run_id` (`run = client.runs.start(flow=…, input=…, options={"wait": False})`,
190
+ then `run.id`). The app reads the rest through the API, server side, with
191
+ `Kindgi()` from `kindgi.client`:
192
+
193
+ - **Status, output, timing:** `client.runs.get(run_id)`
194
+ (`GET /v1/runs/{runId}`); status and timing only: `client.runs.progress(run_id)`.
195
+ - **The audit, step by step:** `client.runs.journal(run_id).data`
196
+ (`GET /v1/runs/{runId}/journal`).
197
+ - **Where an agent's answer came from:** `client.provenance.get(run_id)`
198
+ (`GET /v1/provenance/{runId}`). A flow run has none of its own: each agent
199
+ step's `step.completed` entry in the flow's journal names its turn's run
200
+ (`entry.payload["output"]["runId"]`).
201
+ - **When a run finished:** the `run.finished` webhook (the run's id and
202
+ outcome, no output; then `runs.get`), not polling.
203
+
204
+ Show it in the app's own UI. **Never:**
205
+
206
+ - **query Kindgi's database**, even on the app's own Postgres server, and
207
+ never map its tables into the app's ORM (SQLAlchemy, Django models). Its
208
+ schema is private and changes with every release (migrations only go
209
+ forward), row-level security guards every tenant query, and a runtime
210
+ Kindgi hosts gives no database access.
211
+ - **link users to Kindgi's console** or any Kindgi UI for this data.
212
+
213
+ To keep a copy (reporting, search), pull it through the API into the app's
214
+ own tables. Docs: https://docs.kindgi.com/v0.1/guides/runs/show-runs-in-your-app/
215
+
183
216
  ## Build an image
184
217
 
185
218
  `kindgi build --env=<name>` (an `[tool.kindgi.environments.<name>]`
@@ -6,7 +6,7 @@
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
8
8
  "engines": {
9
- "node": ">=22.0.0"
9
+ "node": ">=22.12.0"
10
10
  },
11
11
  "scripts": {
12
12
  "typecheck": "tsc --noEmit",
@@ -1,6 +1,8 @@
1
1
  # pnpm 12+ reads settings from this file, not from `package.json`'s
2
- # `pnpm` block. `allowBuilds` grants postinstall permission to
3
- # specific dependencies — esbuild ships a native binary via
4
- # postinstall that the vitest transform pipeline depends on.
2
+ # `pnpm` block. `allowBuilds` records, per dependency, whether pnpm runs
3
+ # its install script (true) or skips it (false); pnpm 11+ stops an install
4
+ # until each one has a decision. esbuild (the CLI's bundler, and vitest's
5
+ # transform) works without its script: its native binary comes from its
6
+ # `@esbuild/<platform>` package, so the script stays off.
5
7
  allowBuilds:
6
- esbuild: true
8
+ esbuild: false
@@ -7,7 +7,7 @@
7
7
  // `kind` at the top level; the runtime registers the inline check at
8
8
  // boot.
9
9
 
10
- import { defineCheck } from '@kindgi/sdk/define';
10
+ import { type DefinedCheck, defineCheck } from '@kindgi/sdk/define';
11
11
  import { z } from 'zod';
12
12
 
13
13
  const ConfigSchema = z.object({
@@ -31,15 +31,23 @@ const check = defineCheck({
31
31
  },
32
32
  });
33
33
 
34
+ // The check as the runtime registers it, typed with the SDK's
35
+ // `DefinedCheck`. Left to inference, its type would name
36
+ // `@kindgi/guardrails`, which the pack reaches only through
37
+ // `@kindgi/sdk` — `tsc` then stops with TS2742 (`declaration: true`).
38
+ type InlineCheck = Pick<DefinedCheck<typeof ConfigSchema>, 'id' | 'evaluate' | 'validateConfig'>;
39
+
40
+ const inlineCheck: InlineCheck = {
41
+ id: check.id,
42
+ evaluate: check.evaluate,
43
+ ...(check.validateConfig !== undefined && { validateConfig: check.validateConfig }),
44
+ };
45
+
34
46
  const guardrail = {
35
47
  id: '{{PACK_ID}}.response-not-empty',
36
48
  name: 'Response is non-empty',
37
49
  kind: 'zero-llm' as const,
38
- check: {
39
- id: check.id,
40
- evaluate: check.evaluate,
41
- ...(check.validateConfig !== undefined && { validateConfig: check.validateConfig }),
42
- },
50
+ check: inlineCheck,
43
51
  configSchema: check.configJsonSchema,
44
52
  action: { 'on-violation': 'halt' } as const,
45
53
  severity: 'error' as const,
@@ -6,7 +6,7 @@
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
8
8
  "engines": {
9
- "node": ">=22.0.0"
9
+ "node": ">=22.12.0"
10
10
  },
11
11
  "scripts": {
12
12
  "typecheck": "tsc --noEmit",
@@ -1,6 +1,8 @@
1
1
  # pnpm 12+ reads settings from this file, not from `package.json`'s
2
- # `pnpm` block. `allowBuilds` grants postinstall permission to
3
- # specific dependencies — esbuild ships a native binary via
4
- # postinstall that the vitest transform pipeline depends on.
2
+ # `pnpm` block. `allowBuilds` records, per dependency, whether pnpm runs
3
+ # its install script (true) or skips it (false); pnpm 11+ stops an install
4
+ # until each one has a decision. esbuild (the CLI's bundler, and vitest's
5
+ # transform) works without its script: its native binary comes from its
6
+ # `@esbuild/<platform>` package, so the script stays off.
5
7
  allowBuilds:
6
- esbuild: true
8
+ esbuild: false
@@ -0,0 +1,17 @@
1
+ /** A prompt whose answer isn't echoed. Tests hand in a fake. */
2
+ export interface TtySeam {
3
+ /** Rejects with `PromptCancelled` when the person presses Ctrl+C (or Ctrl+D) instead. */
4
+ promptHidden(prompt: string): Promise<string>;
5
+ close(): void;
6
+ }
7
+ /** The person cancelled a prompt (Ctrl+C, or Ctrl+D): no answer, not an empty one. */
8
+ export declare class PromptCancelled extends Error {
9
+ constructor();
10
+ }
11
+ /** Whether stdin is a terminal, so a hidden prompt can read from it. */
12
+ export declare function stdinIsTty(): boolean;
13
+ export declare function stripTrailingNewline(s: string): string;
14
+ export declare function readStdinToEnd(): Promise<string>;
15
+ /** The hidden prompt on the real terminal: the prompt on stderr, keystrokes from stdin. */
16
+ export declare function realTtySeam(): TtySeam;
17
+ //# sourceMappingURL=terminal-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-input.d.ts","sourceRoot":"","sources":["../src/terminal-input.ts"],"names":[],"mappings":"AAaA,gEAAgE;AAChE,MAAM,WAAW,OAAO;IACtB,yFAAyF;IACzF,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,sFAAsF;AACtF,qBAAa,eAAgB,SAAQ,KAAK;;CAKzC;AAED,wEAAwE;AACxE,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAMtD;AAED,2FAA2F;AAC3F,wBAAgB,WAAW,IAAI,OAAO,CAsDrC"}