@kindgi/cli 0.1.11-rc.0 → 0.2.0-rc.1
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.
- package/README.md +77 -33
- package/dist/build/containerfile.d.ts +2 -0
- package/dist/build/containerfile.d.ts.map +1 -1
- package/dist/build/containerfile.js +14 -3
- package/dist/build/containerfile.js.map +1 -1
- package/dist/build/defaults.d.ts +2 -0
- package/dist/build/defaults.d.ts.map +1 -1
- package/dist/build/defaults.js +8 -0
- package/dist/build/defaults.js.map +1 -1
- package/dist/build/hosted.d.ts +2 -9
- package/dist/build/hosted.d.ts.map +1 -1
- package/dist/build/hosted.js +4 -2
- package/dist/build/hosted.js.map +1 -1
- package/dist/build/pack-blocks.d.ts +51 -0
- package/dist/build/pack-blocks.d.ts.map +1 -0
- package/dist/build/pack-blocks.js +98 -0
- package/dist/build/pack-blocks.js.map +1 -0
- package/dist/build/runners.d.ts +5 -1
- package/dist/build/runners.d.ts.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adapters.d.ts.map +1 -1
- package/dist/commands/adapters.js +12 -6
- package/dist/commands/adapters.js.map +1 -1
- package/dist/commands/agents.js +8 -8
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +155 -39
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/blocks.d.ts.map +1 -1
- package/dist/commands/blocks.js +1 -1
- package/dist/commands/blocks.js.map +1 -1
- package/dist/commands/build.d.ts +17 -6
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +136 -89
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/connection-apps.d.ts +3 -0
- package/dist/commands/connection-apps.d.ts.map +1 -0
- package/dist/commands/connection-apps.js +239 -0
- package/dist/commands/connection-apps.js.map +1 -0
- package/dist/commands/connections.d.ts +44 -0
- package/dist/commands/connections.d.ts.map +1 -0
- package/dist/commands/connections.js +385 -0
- package/dist/commands/connections.js.map +1 -0
- package/dist/commands/conversations.js +1 -1
- package/dist/commands/conversations.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +178 -97
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +10 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +177 -87
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.js +7 -7
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env-scoped.d.ts.map +1 -1
- package/dist/commands/env-scoped.js +37 -22
- package/dist/commands/env-scoped.js.map +1 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +35 -22
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/eval-runs.js +6 -6
- package/dist/commands/eval-runs.js.map +1 -1
- package/dist/commands/eval-suites.js +9 -9
- package/dist/commands/eval-suites.js.map +1 -1
- package/dist/commands/exports.d.ts.map +1 -1
- package/dist/commands/exports.js +35 -9
- package/dist/commands/exports.js.map +1 -1
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +4 -3
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/gate-policies.d.ts.map +1 -1
- package/dist/commands/gate-policies.js +7 -7
- package/dist/commands/gate-policies.js.map +1 -1
- package/dist/commands/helpers.d.ts +33 -0
- package/dist/commands/helpers.d.ts.map +1 -1
- package/dist/commands/helpers.js +49 -0
- package/dist/commands/helpers.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +10 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +57 -45
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/judge-classes.js +4 -4
- package/dist/commands/judge-classes.js.map +1 -1
- package/dist/commands/judging-queue.d.ts +3 -0
- package/dist/commands/judging-queue.d.ts.map +1 -0
- package/dist/commands/judging-queue.js +105 -0
- package/dist/commands/judging-queue.js.map +1 -0
- package/dist/commands/judging-rules.d.ts +3 -0
- package/dist/commands/judging-rules.d.ts.map +1 -0
- package/dist/commands/judging-rules.js +351 -0
- package/dist/commands/judging-rules.js.map +1 -0
- package/dist/commands/judgments.d.ts.map +1 -1
- package/dist/commands/judgments.js +78 -36
- package/dist/commands/judgments.js.map +1 -1
- package/dist/commands/key.d.ts.map +1 -1
- package/dist/commands/key.js +107 -9
- package/dist/commands/key.js.map +1 -1
- package/dist/commands/license.d.ts.map +1 -1
- package/dist/commands/license.js +67 -15
- package/dist/commands/license.js.map +1 -1
- package/dist/commands/mail-triggers.d.ts +3 -0
- package/dist/commands/mail-triggers.d.ts.map +1 -0
- package/dist/commands/mail-triggers.js +290 -0
- package/dist/commands/mail-triggers.js.map +1 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +4 -4
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/people.js +8 -14
- package/dist/commands/people.js.map +1 -1
- package/dist/commands/promote.js +1 -1
- package/dist/commands/promote.js.map +1 -1
- package/dist/commands/proposals.d.ts.map +1 -1
- package/dist/commands/proposals.js +83 -30
- package/dist/commands/proposals.js.map +1 -1
- package/dist/commands/run-waits.d.ts +68 -19
- package/dist/commands/run-waits.d.ts.map +1 -1
- package/dist/commands/run-waits.js +82 -8
- package/dist/commands/run-waits.js.map +1 -1
- package/dist/commands/runs.d.ts.map +1 -1
- package/dist/commands/runs.js +70 -30
- package/dist/commands/runs.js.map +1 -1
- package/dist/commands/schedules.d.ts.map +1 -1
- package/dist/commands/schedules.js +44 -20
- package/dist/commands/schedules.js.map +1 -1
- package/dist/commands/secrets-copy.d.ts.map +1 -1
- package/dist/commands/secrets-copy.js +20 -12
- package/dist/commands/secrets-copy.js.map +1 -1
- package/dist/commands/secrets.d.ts.map +1 -1
- package/dist/commands/secrets.js +13 -8
- package/dist/commands/secrets.js.map +1 -1
- package/dist/commands/service-accounts.d.ts.map +1 -1
- package/dist/commands/service-accounts.js +4 -2
- package/dist/commands/service-accounts.js.map +1 -1
- package/dist/commands/sign-in.js +2 -2
- package/dist/commands/sign-in.js.map +1 -1
- package/dist/commands/sites.d.ts.map +1 -1
- package/dist/commands/sites.js +13 -6
- package/dist/commands/sites.js.map +1 -1
- package/dist/commands/skills.d.ts +54 -3
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +169 -38
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/tokens.d.ts.map +1 -1
- package/dist/commands/tokens.js +9 -1
- package/dist/commands/tokens.js.map +1 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +9 -8
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/webhooks.d.ts.map +1 -1
- package/dist/commands/webhooks.js +72 -33
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -3
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +12 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -1
- package/dist/deploy/pack-blocks-gate.d.ts +12 -0
- package/dist/deploy/pack-blocks-gate.d.ts.map +1 -0
- package/dist/deploy/pack-blocks-gate.js +34 -0
- package/dist/deploy/pack-blocks-gate.js.map +1 -0
- package/dist/deploy/post.d.ts +9 -0
- package/dist/deploy/post.d.ts.map +1 -1
- package/dist/deploy/post.js +20 -3
- package/dist/deploy/post.js.map +1 -1
- package/dist/dev/defaults.d.ts.map +1 -1
- package/dist/dev/defaults.js +8 -1
- package/dist/dev/defaults.js.map +1 -1
- package/dist/dev/dev-only-imports.d.ts +7 -4
- package/dist/dev/dev-only-imports.d.ts.map +1 -1
- package/dist/dev/dev-only-imports.js +5 -5
- package/dist/dev/dev-only-imports.js.map +1 -1
- package/dist/dev/log-view.d.ts +4 -4
- package/dist/dev/log-view.d.ts.map +1 -1
- package/dist/dev/log-view.js +4 -4
- package/dist/dev/log-view.js.map +1 -1
- package/dist/dev/pack-service.d.ts +7 -1
- package/dist/dev/pack-service.d.ts.map +1 -1
- package/dist/dev/pack-service.js +36 -3
- package/dist/dev/pack-service.js.map +1 -1
- package/dist/dev/preview-expiry.d.ts +6 -7
- package/dist/dev/preview-expiry.d.ts.map +1 -1
- package/dist/dev/preview-expiry.js +7 -8
- package/dist/dev/preview-expiry.js.map +1 -1
- package/dist/dev/providers.d.ts +2 -1
- package/dist/dev/providers.d.ts.map +1 -1
- package/dist/dev/providers.js +28 -12
- package/dist/dev/providers.js.map +1 -1
- package/dist/dev/runners.d.ts +19 -0
- package/dist/dev/runners.d.ts.map +1 -1
- package/dist/dev/runtime-container.d.ts.map +1 -1
- package/dist/dev/runtime-container.js +2 -2
- package/dist/dev/runtime-container.js.map +1 -1
- package/dist/dev/runtime-env.d.ts +2 -1
- package/dist/dev/runtime-env.d.ts.map +1 -1
- package/dist/dev/runtime-env.js +5 -5
- package/dist/dev/runtime-env.js.map +1 -1
- package/dist/dev/runtime-image.d.ts +2 -2
- package/dist/dev/runtime-image.d.ts.map +1 -1
- package/dist/dev/runtime-image.js +2 -2
- package/dist/dev/runtime-image.js.map +1 -1
- package/dist/dev/runtime-registry.d.ts +8 -10
- package/dist/dev/runtime-registry.d.ts.map +1 -1
- package/dist/dev/runtime-registry.js +27 -27
- package/dist/dev/runtime-registry.js.map +1 -1
- package/dist/dev/sandbox/index.js +1 -1
- package/dist/dev/sandbox/notices.d.ts +2 -0
- package/dist/dev/sandbox/notices.d.ts.map +1 -1
- package/dist/dev/sandbox/notices.js +5 -2
- package/dist/dev/sandbox/notices.js.map +1 -1
- package/dist/env/defaults.d.ts.map +1 -1
- package/dist/env/defaults.js +3 -1
- package/dist/env/defaults.js.map +1 -1
- package/dist/env/pack-env-plan.d.ts +4 -0
- package/dist/env/pack-env-plan.d.ts.map +1 -1
- package/dist/env/pack-env-plan.js +8 -2
- package/dist/env/pack-env-plan.js.map +1 -1
- package/dist/exports/create.d.ts +2 -0
- package/dist/exports/create.d.ts.map +1 -1
- package/dist/exports/create.js +10 -2
- package/dist/exports/create.js.map +1 -1
- package/dist/exports/plan.d.ts.map +1 -1
- package/dist/exports/plan.js +32 -0
- package/dist/exports/plan.js.map +1 -1
- package/dist/feedback/store.d.ts.map +1 -1
- package/dist/feedback/store.js +8 -19
- package/dist/feedback/store.js.map +1 -1
- package/dist/help.d.ts +6 -0
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +35 -1
- package/dist/help.js.map +1 -1
- package/dist/init/agent-access.d.ts +3 -2
- package/dist/init/agent-access.d.ts.map +1 -1
- package/dist/init/agent-access.js +5 -1
- package/dist/init/agent-access.js.map +1 -1
- package/dist/init/augment-scaffolder.d.ts +7 -0
- package/dist/init/augment-scaffolder.d.ts.map +1 -1
- package/dist/init/augment-scaffolder.js +15 -14
- package/dist/init/augment-scaffolder.js.map +1 -1
- package/dist/init/dependency-specs.d.ts +1 -0
- package/dist/init/dependency-specs.d.ts.map +1 -1
- package/dist/init/dependency-specs.js +27 -7
- package/dist/init/dependency-specs.js.map +1 -1
- package/dist/init/java-augment.d.ts +3 -0
- package/dist/init/java-augment.d.ts.map +1 -1
- package/dist/init/java-augment.js +16 -15
- package/dist/init/java-augment.js.map +1 -1
- package/dist/init/python-augment.d.ts +3 -0
- package/dist/init/python-augment.d.ts.map +1 -1
- package/dist/init/python-augment.js +15 -14
- package/dist/init/python-augment.js.map +1 -1
- package/dist/init/scala-augment.d.ts +8 -1
- package/dist/init/scala-augment.d.ts.map +1 -1
- package/dist/init/scala-augment.js +32 -17
- package/dist/init/scala-augment.js.map +1 -1
- package/dist/key/defaults.d.ts.map +1 -1
- package/dist/key/defaults.js +6 -1
- package/dist/key/defaults.js.map +1 -1
- package/dist/key/runners.d.ts +4 -1
- package/dist/key/runners.d.ts.map +1 -1
- package/dist/license/renew.d.ts +6 -0
- package/dist/license/renew.d.ts.map +1 -1
- package/dist/license/renew.js +8 -5
- package/dist/license/renew.js.map +1 -1
- package/dist/main.d.ts +10 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +19 -5
- package/dist/main.js.map +1 -1
- package/dist/output.d.ts +6 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +8 -0
- package/dist/output.js.map +1 -1
- package/dist/parse.d.ts +1 -1
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +1 -1
- package/dist/parse.js.map +1 -1
- package/dist/private-file.d.ts +23 -0
- package/dist/private-file.d.ts.map +1 -0
- package/dist/private-file.js +65 -0
- package/dist/private-file.js.map +1 -0
- package/dist/progress-head.d.ts +13 -0
- package/dist/progress-head.d.ts.map +1 -0
- package/dist/progress-head.js +30 -0
- package/dist/progress-head.js.map +1 -0
- package/dist/progress-lines.d.ts +29 -0
- package/dist/progress-lines.d.ts.map +1 -0
- package/dist/progress-lines.js +35 -0
- package/dist/progress-lines.js.map +1 -0
- package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +6 -6
- package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +2 -2
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +13 -3
- package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +47 -9
- package/dist/sdk-skills/kindgi-fix-corrections/SKILL.md +262 -0
- package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-getting-started/SKILL.md +46 -9
- package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +5 -5
- package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +101 -11
- package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +41 -9
- package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +4 -4
- package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +53 -10
- package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +42 -11
- package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +5 -5
- package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +92 -9
- package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +41 -9
- package/dist/sdk-skills/kindgi-using/SKILL.md +63 -21
- package/dist/templates/drupal/AGENTS.md +2 -1
- package/dist/templates/follow-up/.nvmrc +1 -0
- package/dist/templates/follow-up/AGENTS.md +83 -0
- package/dist/templates/follow-up/README.md.tmpl +111 -0
- package/dist/templates/follow-up/agents/follow-up/index.test.ts.tmpl +26 -0
- package/dist/templates/follow-up/agents/follow-up/index.ts.tmpl +53 -0
- package/dist/templates/follow-up/gitignore +8 -0
- package/dist/templates/follow-up/kindgi.config.ts.tmpl +45 -0
- package/dist/templates/follow-up/package.json.tmpl +30 -0
- package/dist/templates/follow-up/pnpm-workspace.yaml +9 -0
- package/dist/templates/follow-up/tools/gmail-send/index.test.ts.tmpl +60 -0
- package/dist/templates/follow-up/tools/gmail-send/index.ts.tmpl +14 -0
- package/dist/templates/follow-up/tsconfig.json.tmpl +27 -0
- package/dist/templates/follow-up/vitest.config.ts.tmpl +14 -0
- package/dist/templates/java/AGENTS.md +2 -1
- package/dist/templates/minimal/AGENTS.md +2 -1
- package/dist/templates/python/AGENTS.md +2 -1
- package/dist/templates/sample/AGENTS.md +2 -1
- package/dist/templates/scala/AGENTS.md +2 -1
- package/dist/templates/woocommerce/AGENTS.md +12 -3
- package/dist/templates/woocommerce/README.md.tmpl +29 -5
- package/dist/templates/woocommerce/agents/store-agent/index.test.ts.tmpl +38 -7
- package/dist/templates/woocommerce/agents/store-agent/index.ts.tmpl +7 -12
- package/dist/templates/woocommerce/blocks/store-agent-prompt.json.tmpl +10 -0
- package/dist/templates/woocommerce/blocks/store-agent-prompt.liquid.tmpl +7 -0
- package/dist/templates/woocommerce/kindgi.config.ts.tmpl +1 -0
- package/dist/value-target.d.ts +4 -2
- package/dist/value-target.d.ts.map +1 -1
- package/dist/value-target.js +8 -5
- package/dist/value-target.js.map +1 -1
- package/package.json +13 -13
|
@@ -10,14 +10,15 @@ description: >
|
|
|
10
10
|
`kindgi.config.json` yet and the user asks to "add Kindgi", "make an
|
|
11
11
|
agent", "set up a pack", or when you are orienting in a Java pack
|
|
12
12
|
(`kindgi.config.json` with `"language": "java"`) for the first time.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
kindgi-authoring-
|
|
13
|
+
Load it too when upgrading a self-hosted deployment, or when asked for
|
|
14
|
+
a migration script (there is none). Authoring tools, guardrails, agents
|
|
15
|
+
and flows is covered by kindgi-java-authoring-tools,
|
|
16
|
+
kindgi-java-authoring-guardrails, kindgi-java-authoring-agents and
|
|
17
|
+
kindgi-java-authoring-flows; models by kindgi-authoring-providers.
|
|
17
18
|
type: core
|
|
18
19
|
library: "kindgi-pack (Java)"
|
|
19
|
-
version: "0.1.
|
|
20
|
-
sdk_version: "0.
|
|
20
|
+
version: "0.1.4"
|
|
21
|
+
sdk_version: "0.2.0-rc.1"
|
|
21
22
|
pack_languages: [java]
|
|
22
23
|
sources:
|
|
23
24
|
- sdks/java/kindgi-pack/README.md
|
|
@@ -64,7 +65,7 @@ You need a JDK 17 or later (`JAVA_HOME`). Maven comes with the pack
|
|
|
64
65
|
(`./mvnw`).
|
|
65
66
|
|
|
66
67
|
```sh
|
|
67
|
-
npx --yes @kindgi/cli@0.
|
|
68
|
+
npx --yes @kindgi/cli@0.2 init my-pack --template=java # or: uvx --from "kindgi-cli>=0.2,<0.3" kindgi init …
|
|
68
69
|
cd my-pack
|
|
69
70
|
./mvnw test # the template's tests: the tools, called directly
|
|
70
71
|
./kindgiw dev # boots Kindgi locally and runs this pack, recompiling on save
|
|
@@ -88,7 +89,7 @@ reported as `file:line:col`, and the last good code keeps serving.
|
|
|
88
89
|
In the app's directory (where its `pom.xml` is):
|
|
89
90
|
|
|
90
91
|
```sh
|
|
91
|
-
npx --yes @kindgi/cli@0.
|
|
92
|
+
npx --yes @kindgi/cli@0.2 init # --pack-id=<id> if the app's artifactId doesn't make one
|
|
92
93
|
./kindgiw dev
|
|
93
94
|
```
|
|
94
95
|
|
|
@@ -235,7 +236,7 @@ Show it in the app's own UI. **Never:**
|
|
|
235
236
|
gives no database access.
|
|
236
237
|
- **link users to Kindgi's console**, or any Kindgi UI, for this data.
|
|
237
238
|
|
|
238
|
-
Docs: https://docs.kindgi.com/v0.
|
|
239
|
+
Docs: https://docs.kindgi.com/v0.2/guides/runs/show-runs-in-your-app/
|
|
239
240
|
|
|
240
241
|
## Build an image
|
|
241
242
|
|
|
@@ -254,6 +255,37 @@ deployed pack service missing a required one isn't ready, and its `/readyz`
|
|
|
254
255
|
names it; one the pack doesn't declare is dropped before the code loads
|
|
255
256
|
(`kindgi dev` keeps it).
|
|
256
257
|
|
|
258
|
+
## Upgrading a deployment
|
|
259
|
+
|
|
260
|
+
There's no migration script, and none to write: a self-hosted runtime brings
|
|
261
|
+
its database up to date when it starts, applying the migrations the database
|
|
262
|
+
doesn't have yet, then serving. Migrations only go forward: an upgrade
|
|
263
|
+
starts with a backup of the database, and going back means restoring it and
|
|
264
|
+
running the older version on it.
|
|
265
|
+
|
|
266
|
+
- **On Cloud Run, a small dev deployment** (`network_mode = "none"`, on
|
|
267
|
+
runtime 0.1.8 or later): the Cloud Run module's `./upgrade.sh`, as of the
|
|
268
|
+
`@kindgi/sdk@<version>` tag of the release you're upgrading to, since it
|
|
269
|
+
knows the steps up to its own release. Run `./upgrade.sh --dry-run` first:
|
|
270
|
+
it changes nothing, and lists what a real run would change. Its plan also
|
|
271
|
+
reads every `*.auto.tfvars.json` in the module's folder (the pack's env),
|
|
272
|
+
and `yes` applies exactly the saved plan it showed. The module README's
|
|
273
|
+
Upgrading section has the rest:
|
|
274
|
+
https://github.com/kindgi/kindgi-sdk/tree/main/deploy/gcp-cloud-run#upgrading
|
|
275
|
+
- **Any other Cloud Run deployment:** by hand, staging first, as the Cloud
|
|
276
|
+
Run page's "Upgrade by hand" section says:
|
|
277
|
+
https://docs.kindgi.com/v0.2/deploy/self-hosted/cloud-run/#upgrade-by-hand
|
|
278
|
+
- **On Azure Container Apps:** the "Operate it" section of its page,
|
|
279
|
+
https://docs.kindgi.com/v0.2/deploy/self-hosted/azure-container-apps/#operate-it.
|
|
280
|
+
- **Otherwise:** the operate page's upgrade steps,
|
|
281
|
+
https://docs.kindgi.com/v0.2/deploy/self-hosted/operate/#upgrade-the-runtime.
|
|
282
|
+
|
|
283
|
+
An upgrade changes a running deployment: give the person the commands to run
|
|
284
|
+
in their own terminal (`./upgrade.sh` waits for them to type `yes`).
|
|
285
|
+
|
|
286
|
+
Not `./kindgiw upgrade`: that moves the pack's own pins (the CLI's and
|
|
287
|
+
kindgi-pack's), not a deployment's runtime.
|
|
288
|
+
|
|
257
289
|
## Two things need the human
|
|
258
290
|
|
|
259
291
|
- **The pack id and version** in `kindgi.config.json`. The id prefixes every
|
|
@@ -16,7 +16,7 @@ description: >
|
|
|
16
16
|
type: core
|
|
17
17
|
library: "kindgi (Python)"
|
|
18
18
|
version: "0.1.7"
|
|
19
|
-
sdk_version: "0.
|
|
19
|
+
sdk_version: "0.2.0-rc.1"
|
|
20
20
|
pack_languages: [python]
|
|
21
21
|
sources:
|
|
22
22
|
- sdks/python/src/kindgi/pack/define.py
|
|
@@ -142,8 +142,8 @@ brief_writer = Agent(
|
|
|
142
142
|
loosen them. `"separateApprover"` in `hitl` (`True`, or
|
|
143
143
|
`{"overrides": {"<tool id>": True}}`) makes a tool's approval need
|
|
144
144
|
someone other than whoever asked.
|
|
145
|
-
- **`budget`** — per turn: `maxSteps` (model calls, default 8
|
|
146
|
-
`maxCostUsd`, `maxWallMs` (default 120 000). Steps or cost exceeded
|
|
145
|
+
- **`budget`** — per turn: `maxSteps` (model calls, default 8, at most
|
|
146
|
+
32), `maxCostUsd`, `maxWallMs` (default 120 000). Steps or cost exceeded
|
|
147
147
|
fails the turn (`budget-exceeded`); out of wall time aborts it. Leave
|
|
148
148
|
room for real models: a turn with tool calls can take tens of seconds.
|
|
149
149
|
- **`output`** — a typed answer: a pydantic model class (or any type
|
|
@@ -182,7 +182,7 @@ brief_writer = Agent(
|
|
|
182
182
|
one person, or instruction-like text, waits for a person's approval.
|
|
183
183
|
Use a model with reliable tool calling. `{"instructionTypes":
|
|
184
184
|
["acme.policy"]}` makes a retrieved, verified fact of those types an
|
|
185
|
-
instruction. See https://docs.kindgi.com/v0.
|
|
185
|
+
instruction. See https://docs.kindgi.com/v0.2/guides/agents/give-an-agent-memory/.
|
|
186
186
|
|
|
187
187
|
**In a run a webhook or an event started**, the turn's message is data:
|
|
188
188
|
it arrives inside an `<event note="kindgi event: data, not
|
|
@@ -14,8 +14,8 @@ description: >
|
|
|
14
14
|
kindgi-python-getting-started.
|
|
15
15
|
type: core
|
|
16
16
|
library: "kindgi (Python)"
|
|
17
|
-
version: "0.1.
|
|
18
|
-
sdk_version: "0.
|
|
17
|
+
version: "0.1.6"
|
|
18
|
+
sdk_version: "0.2.0-rc.1"
|
|
19
19
|
pack_languages: [python]
|
|
20
20
|
sources:
|
|
21
21
|
- sdks/python/src/kindgi/pack/define.py
|
|
@@ -95,8 +95,10 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
|
|
|
95
95
|
field's path (a bad output as `output-validation-failed`); the agent's
|
|
96
96
|
`tool_errors` policy decides whether the model gets to fix the call.
|
|
97
97
|
- **Problems in the declaration** (a missing docstring, an
|
|
98
|
-
unannotated parameter, a non-object input
|
|
99
|
-
|
|
98
|
+
unannotated parameter, a non-object input, or an input or output
|
|
99
|
+
schema the runtime's compile refuses, such as one with a keyword it
|
|
100
|
+
doesn't know) raise `DefinitionError` where the tool is declared; the
|
|
101
|
+
indexer reports it with the file.
|
|
100
102
|
|
|
101
103
|
## `ToolContext`
|
|
102
104
|
|
|
@@ -112,7 +114,7 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
|
|
|
112
114
|
system it writes to (an `Idempotency-Key` header, a client reference, a
|
|
113
115
|
unique column) or looks for it there first: a refund never goes out
|
|
114
116
|
twice. A UUID; `None` outside a run and from a runtime before 0.1.6.
|
|
115
|
-
Docs: https://docs.kindgi.com/v0.
|
|
117
|
+
Docs: https://docs.kindgi.com/v0.2/guides/tools/write-a-tool/#make-a-side-effect-happen-once
|
|
116
118
|
- `ctx.project_id`, `ctx.org_id` — the run's project, and that project's
|
|
117
119
|
org (`None` when it has none). The runtime sets them from the run, never
|
|
118
120
|
from the input: to check an org or project id the input names, compare
|
|
@@ -136,7 +138,7 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
|
|
|
136
138
|
amounts and outcomes, never what a person typed (a refund's reason, a
|
|
137
139
|
message, an address): the log is read by whoever operates the runtime.
|
|
138
140
|
`ToolContext.for_test(…)` logs nothing unless you pass it `log=`. Docs:
|
|
139
|
-
https://docs.kindgi.com/v0.
|
|
141
|
+
https://docs.kindgi.com/v0.2/guides/tools/write-a-tool/#log-from-a-tool
|
|
140
142
|
|
|
141
143
|
## Configuration and secrets
|
|
142
144
|
|
|
@@ -189,7 +191,7 @@ def find_order(lookup: Lookup, ctx: ToolContext) -> Found:
|
|
|
189
191
|
precondition-failed: Tool "acme-orders.needs-account" was not run: env-value-missing: tool "acme-orders.needs-account" needs env value "ACME_ACCOUNT_ID" in env "local", and none is set for project e889c1f5-eae7-45dc-8669-5bd029a5d85c, its org, or the tenant. Set it: kindgi env set ACME_ACCOUNT_ID <value> --scope=project:e889c1f5-eae7-45dc-8669-5bd029a5d85c --env=local (or --scope=tenant, for every project)
|
|
190
192
|
```
|
|
191
193
|
- **Not secret:** env values are recorded with each run that uses them and shown in its journal. A credential is a secret, never an env value.
|
|
192
|
-
- **In a test:** `ToolContext.for_test(env={"ORDERS_BASE_URL": "…"})`.
|
|
194
|
+
- **In a test:** `ToolContext.for_test(tool=find_order, env={"ORDERS_BASE_URL": "…"})` decides them as a run does: a schema `default` fills a name the test doesn't set, each value is checked, and a missing or invalid one raises `ValueError`.
|
|
193
195
|
|
|
194
196
|
Everything else comes from the process environment: `os.environ["CITATOR_URL"]`.
|
|
195
197
|
The pack service runs with the pack's environment — in `kindgi dev`
|
|
@@ -207,6 +209,38 @@ the pack service drops every other variable before your code loads
|
|
|
207
209
|
unset once deployed. `KINDGI_*` names are Kindgi's own settings: a pack
|
|
208
210
|
can't declare one.
|
|
209
211
|
|
|
212
|
+
### Connections to other apps
|
|
213
|
+
|
|
214
|
+
A tool that acts in another app as a person or as the company (sending mail, opening an issue) declares a **connection**, never a secret holding someone's token, and reads the call's short-lived token from `ctx.connections` (runtime 0.2.0 or later):
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
import httpx
|
|
218
|
+
|
|
219
|
+
from kindgi import ConnectionRejected, ToolContext, tool
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@tool(
|
|
223
|
+
id="my-pack.send-mail",
|
|
224
|
+
needs_spec={"connections": {"mail": {"app": "google", "permissions": ["gmail.send"], "as": "person"}}},
|
|
225
|
+
)
|
|
226
|
+
def send_mail(message: Message, ctx: ToolContext) -> Sent:
|
|
227
|
+
"""Sends a message from the person's mailbox."""
|
|
228
|
+
mail = ctx.connections["mail"]
|
|
229
|
+
res = httpx.get(url, headers={"authorization": f"Bearer {mail.access_token}"})
|
|
230
|
+
if res.status_code == 401:
|
|
231
|
+
raise ConnectionRejected("mail")
|
|
232
|
+
# …
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
- **Whose connection:** `"as": "person"` is the connection of the person the run acts as (whoever started it, or the owner of the schedule or webhook that did); `"as": "company"` is the company's. The runtime picks it from the run, never from the input or the model. A run that acts as nobody (a service account's, an event's) fails a `"person"` call with `connection-needs-a-person`.
|
|
236
|
+
- **The token:** `access_token` is current for this call only. Never keep, print, log or return it; it never reaches the journal. `account.label` says whose account it is (`ana@acme.com`).
|
|
237
|
+
- **A 401 from the app:** `raise ConnectionRejected("mail")`, with the connection's name (a second argument can say what the app answered, never the token), or raise your own error `from` it. The runtime renews the token once and runs the call again; refused again, the call fails with `connection-rejected`.
|
|
238
|
+
- **An HTTP tool** sends the token with no code: `authorization={"kind": "connection", "connection": "mail"}`.
|
|
239
|
+
- **Unattended runs:** in a run no person started, a tool that uses a `"person"` connection waits for that person's yes, reads included: `mutating=False` doesn't lift it. The agent's own approval settings can't lift it; only a trigger's `toolsAllowedUnattended` can, which a project admin sets, as for `needs_approval_when_unattended` (below). In a run a new mail started, the mail is a stranger's text, so two more calls wait: a call of a tool that isn't `mutating=False`, and, when the trigger reads the company's mailbox, a read with the company's connection to that app. The mail trigger's `toolsAllowedUnattended` lifts these too.
|
|
240
|
+
- **In a unit test:** `ToolContext.for_test(connections={"mail": ToolConnection(connection_id="c-1", app="google", app_name="Google", access_token="test", account=ConnectionAccount(id="1", label="ana@acme.com"))})`, all from `kindgi`. `ctx.connections` is empty when the tool declares none.
|
|
241
|
+
|
|
242
|
+
Docs: https://docs.kindgi.com/v0.2/guides/connections/use-a-connection/
|
|
243
|
+
|
|
210
244
|
## Errors and output
|
|
211
245
|
|
|
212
246
|
- Raise an exception for a failure: the call fails with
|
|
@@ -229,6 +263,10 @@ approval gates on (`conversation_policy={"hitl": {"tools": {...}}}`)
|
|
|
229
263
|
and has neither an override for the tool nor a `default` doesn't ask
|
|
230
264
|
before a read-only tool, and asks before any other on first use.
|
|
231
265
|
|
|
266
|
+
In a run a new mail started, a call of a tool that isn't read-only waits
|
|
267
|
+
for a person's yes, unless the mail trigger's `toolsAllowedUnattended`
|
|
268
|
+
lists it.
|
|
269
|
+
|
|
232
270
|
```python
|
|
233
271
|
@tool(id="acme.find-citations", mutating=False)
|
|
234
272
|
def find_citations(query: CitationQuery) -> Citations:
|
|
@@ -244,10 +282,11 @@ policy and review; declare what the tool really does.
|
|
|
244
282
|
|
|
245
283
|
## A person's yes when no one is watching: `needs_approval_when_unattended`
|
|
246
284
|
|
|
247
|
-
`needs_approval_when_unattended=True` declares that a person must say yes to every call of the tool in a run no person started: one a schedule, a webhook, an event or a service account's key started. In such a run:
|
|
285
|
+
`needs_approval_when_unattended=True` declares that a person must say yes to every call of the tool in a run no person started: one a schedule, a webhook, a new mail, an event or a service account's key started. In such a run:
|
|
248
286
|
|
|
249
287
|
- **An agent's call waits** for a person's yes, whatever the agent's `conversation_policy` says in `hitl["tools"]`. The agent's rules can't lift it: agents are reused, and the tool's author knows what it does.
|
|
250
288
|
- **A flow's tool step that calls it is refused.** Put the tool behind an agent step instead, whose call waits.
|
|
289
|
+
- **A trigger can lift both, for its own runs only.** A project admin names the tool in a webhook trigger's, a schedule's or a mail trigger's `toolsAllowedUnattended` (`--allow-unattended=<tool-id>` on `kindgi webhooks`, `kindgi schedules` and `kindgi mail-triggers`). In that trigger's runs, the tool is then as in a run a person started. The tenant's approval rules still apply.
|
|
251
290
|
|
|
252
291
|
In a run a person started (signed in, or with their own API key), the agent's rules decide, as for any tool. Left out, it counts as `False`. Declare it on a tool that moves money or changes something people rely on:
|
|
253
292
|
|
|
@@ -262,7 +301,11 @@ def refund(request: RefundRequest) -> Refunded:
|
|
|
262
301
|
"""Refunds an order."""
|
|
263
302
|
```
|
|
264
303
|
|
|
265
|
-
Docs: https://docs.kindgi.com/v0.
|
|
304
|
+
Docs: https://docs.kindgi.com/v0.2/guides/approvals/ask-before-a-tool-runs/#when-no-person-started-the-run
|
|
305
|
+
|
|
306
|
+
## Results that are text from outside: `result_is_outside_data`
|
|
307
|
+
|
|
308
|
+
`result_is_outside_data=True` says the tool's results are text from outside that nobody checked, such as a mail someone sent or a page a search found. An agent reads each result of the tool as data, not instructions, in that turn and in every later turn's history. It changes what the model is told, not what the tool may do: pair it with approvals for anything an agent could do with what it read. Absent means `false`.
|
|
266
309
|
|
|
267
310
|
## HTTP tools — one request, no code
|
|
268
311
|
|
|
@@ -394,7 +437,7 @@ removed field, a narrower type — not on every save.
|
|
|
394
437
|
folder, `~/.aws`) or any `.env*` file, and gets `EPERM` there. A tool that
|
|
395
438
|
needs a path names it in `pyproject.toml`: `[tool.kindgi.dev.sandbox]` `allowRead = ["~/.aws"]`.
|
|
396
439
|
Never set `KINDGI_DEV_SANDBOX=off` or `dev.sandbox: false` to get past it
|
|
397
|
-
(https://docs.kindgi.com/v0.
|
|
440
|
+
(https://docs.kindgi.com/v0.2/guides/secrets/dev-sandbox/).
|
|
398
441
|
|
|
399
442
|
## When the framework itself is the problem
|
|
400
443
|
|
|
@@ -9,13 +9,15 @@ description: >
|
|
|
9
9
|
project has no `[tool.kindgi]` table yet and the user asks to "add
|
|
10
10
|
Kindgi", "make an agent", "set up a pack", or when you are orienting
|
|
11
11
|
in a Python pack (pyproject.toml with `[tool.kindgi]`) for the first
|
|
12
|
-
time.
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
time. Load it too when upgrading a self-hosted deployment, or when
|
|
13
|
+
asked for a migration script (there is none). Authoring tools, guardrails
|
|
14
|
+
and agents is covered by kindgi-python-authoring-tools,
|
|
15
|
+
kindgi-python-authoring-guardrails and kindgi-python-authoring-agents;
|
|
16
|
+
models by kindgi-authoring-providers.
|
|
15
17
|
type: core
|
|
16
18
|
library: "kindgi (Python)"
|
|
17
|
-
version: "0.1.
|
|
18
|
-
sdk_version: "0.
|
|
19
|
+
version: "0.1.10"
|
|
20
|
+
sdk_version: "0.2.0-rc.1"
|
|
19
21
|
pack_languages: [python]
|
|
20
22
|
sources:
|
|
21
23
|
- sdks/python/README.md
|
|
@@ -54,7 +56,7 @@ primitive; `test_*.py`, `*_test.py` and `conftest.py` are skipped.
|
|
|
54
56
|
## Scaffold a new pack
|
|
55
57
|
|
|
56
58
|
```sh
|
|
57
|
-
uvx --from "kindgi-cli>=0.
|
|
59
|
+
uvx --from "kindgi-cli>=0.2,<0.3" kindgi init my-pack --template=python
|
|
58
60
|
cd my-pack
|
|
59
61
|
uv sync # .venv with the kindgi package and the kindgi CLI
|
|
60
62
|
uv run pytest
|
|
@@ -77,7 +79,7 @@ and don't stop theirs.
|
|
|
77
79
|
In the app's directory (where its `pyproject.toml` is):
|
|
78
80
|
|
|
79
81
|
```sh
|
|
80
|
-
uv add --dev "kindgi-cli>=0.
|
|
82
|
+
uv add --dev "kindgi-cli>=0.2,<0.3" # the CLI (Poetry: poetry add --group dev …)
|
|
81
83
|
uv run kindgi init # --pack-id=<id> if the app's name doesn't make one
|
|
82
84
|
uv sync # or what it prints for Poetry / pip
|
|
83
85
|
uv run kindgi dev
|
|
@@ -205,8 +207,9 @@ for event in client.runs.follow(run.id): # to the run's end, reconnecting
|
|
|
205
207
|
print(event.kind)
|
|
206
208
|
```
|
|
207
209
|
|
|
208
|
-
`AsyncKindgi` is the asyncio twin. `kindgi dev
|
|
209
|
-
token
|
|
210
|
+
`AsyncKindgi` is the asyncio twin. With `kindgi dev`, the URL and the
|
|
211
|
+
token are `apiUrl` and `token` in the pack's `.kindgirc.json`, which the
|
|
212
|
+
CLI reads too; the banner shows only the token's last four characters.
|
|
210
213
|
|
|
211
214
|
## Your app and Kindgi's data
|
|
212
215
|
|
|
@@ -255,7 +258,7 @@ month = client.cost.aggregate(
|
|
|
255
258
|
# month.total_usd; month.groups[i].key ({"month": "2026-10"}), .total_usd, .tokens
|
|
256
259
|
```
|
|
257
260
|
|
|
258
|
-
Docs: https://docs.kindgi.com/v0.
|
|
261
|
+
Docs: https://docs.kindgi.com/v0.2/guides/observability/cost-per-run/
|
|
259
262
|
|
|
260
263
|
Show it in the app's own UI. **Never:**
|
|
261
264
|
|
|
@@ -267,7 +270,7 @@ Show it in the app's own UI. **Never:**
|
|
|
267
270
|
- **link users to Kindgi's console** or any Kindgi UI for this data.
|
|
268
271
|
|
|
269
272
|
To keep a copy (reporting, search), pull it through the API into the app's
|
|
270
|
-
own tables. Docs: https://docs.kindgi.com/v0.
|
|
273
|
+
own tables. Docs: https://docs.kindgi.com/v0.2/guides/runs/show-runs-in-your-app/
|
|
271
274
|
|
|
272
275
|
## Build an image
|
|
273
276
|
|
|
@@ -301,6 +304,34 @@ optional = ["SENTRY_DSN"]
|
|
|
301
304
|
A `[tool.uv] required-version` that excludes the image's uv stops the
|
|
302
305
|
build before anything uploads, with the range to use.
|
|
303
306
|
|
|
307
|
+
## Upgrading a deployment
|
|
308
|
+
|
|
309
|
+
There's no migration script, and none to write: a self-hosted runtime brings
|
|
310
|
+
its database up to date when it starts, applying the migrations the database
|
|
311
|
+
doesn't have yet, then serving. Migrations only go forward: an upgrade
|
|
312
|
+
starts with a backup of the database, and going back means restoring it and
|
|
313
|
+
running the older version on it.
|
|
314
|
+
|
|
315
|
+
- **On Cloud Run, a small dev deployment** (`network_mode = "none"`, on
|
|
316
|
+
runtime 0.1.8 or later): the Cloud Run module's `./upgrade.sh`, as of the
|
|
317
|
+
`@kindgi/sdk@<version>` tag of the release you're upgrading to, since it
|
|
318
|
+
knows the steps up to its own release. Run `./upgrade.sh --dry-run` first:
|
|
319
|
+
it changes nothing, and lists what a real run would change. Its plan also
|
|
320
|
+
reads every `*.auto.tfvars.json` in the module's folder (the pack's env),
|
|
321
|
+
and `yes` applies exactly the saved plan it showed. The module README's
|
|
322
|
+
Upgrading section has the rest:
|
|
323
|
+
https://github.com/kindgi/kindgi-sdk/tree/main/deploy/gcp-cloud-run#upgrading
|
|
324
|
+
- **Any other Cloud Run deployment:** by hand, staging first, as the Cloud
|
|
325
|
+
Run page's "Upgrade by hand" section says:
|
|
326
|
+
https://docs.kindgi.com/v0.2/deploy/self-hosted/cloud-run/#upgrade-by-hand
|
|
327
|
+
- **On Azure Container Apps:** the "Operate it" section of its page,
|
|
328
|
+
https://docs.kindgi.com/v0.2/deploy/self-hosted/azure-container-apps/#operate-it.
|
|
329
|
+
- **Otherwise:** the operate page's upgrade steps,
|
|
330
|
+
https://docs.kindgi.com/v0.2/deploy/self-hosted/operate/#upgrade-the-runtime.
|
|
331
|
+
|
|
332
|
+
An upgrade changes a running deployment: give the person the commands to run
|
|
333
|
+
in their own terminal (`./upgrade.sh` waits for them to type `yes`).
|
|
334
|
+
|
|
304
335
|
## Two things need the human
|
|
305
336
|
|
|
306
337
|
- **The pack id and version** in `[tool.kindgi.pack]`. The id prefixes
|
|
@@ -17,7 +17,7 @@ description: >
|
|
|
17
17
|
type: core
|
|
18
18
|
library: "kindgi-pack-scala"
|
|
19
19
|
version: "0.1.4"
|
|
20
|
-
sdk_version: "0.
|
|
20
|
+
sdk_version: "0.2.0-rc.1"
|
|
21
21
|
pack_languages: [scala]
|
|
22
22
|
sources:
|
|
23
23
|
- sdks/scala/README.md
|
|
@@ -150,10 +150,10 @@ object BriefWriter {
|
|
|
150
150
|
`Map("overrides" -> Map("<tool id>" -> true))`) makes a tool's approval
|
|
151
151
|
need someone other than whoever asked.
|
|
152
152
|
- **`set("budget", …)`:** per turn. `maxSteps` counts model calls (default
|
|
153
|
-
8); `maxCostUsd`; `maxWallMs` (default 120 000). Exceeding
|
|
154
|
-
cost fails the turn (`budget-exceeded`); running out of
|
|
155
|
-
it. Leave room for real models: a turn with tool calls
|
|
156
|
-
seconds.
|
|
153
|
+
8, at most 32); `maxCostUsd`; `maxWallMs` (default 120 000). Exceeding
|
|
154
|
+
the steps or the cost fails the turn (`budget-exceeded`); running out of
|
|
155
|
+
wall time aborts it. Leave room for real models: a turn with tool calls
|
|
156
|
+
can take tens of seconds.
|
|
157
157
|
- **`output[T]`:** a typed answer, with its schema derived from the case
|
|
158
158
|
class. The final answer must be JSON matching it. A wrong one goes back to
|
|
159
159
|
the model with the problems (`maxRepairs`, default 1), and then the turn
|
|
@@ -15,8 +15,8 @@ description: >
|
|
|
15
15
|
kindgi-scala-getting-started.
|
|
16
16
|
type: core
|
|
17
17
|
library: "kindgi-pack-scala"
|
|
18
|
-
version: "0.1.
|
|
19
|
-
sdk_version: "0.
|
|
18
|
+
version: "0.1.4"
|
|
19
|
+
sdk_version: "0.2.0-rc.1"
|
|
20
20
|
pack_languages: [scala]
|
|
21
21
|
sources:
|
|
22
22
|
- sdks/scala/README.md
|
|
@@ -156,7 +156,7 @@ object Citator {
|
|
|
156
156
|
it writes to (`Option(ctx.idempotencyKey).foreach(k => request.header("Idempotency-Key", k))`)
|
|
157
157
|
or looks for it there first: a refund never goes out twice. A UUID; `null`
|
|
158
158
|
outside a run and from a runtime before 0.1.6. Docs:
|
|
159
|
-
https://docs.kindgi.com/v0.
|
|
159
|
+
https://docs.kindgi.com/v0.2/guides/tools/write-a-tool/#make-a-side-effect-happen-once
|
|
160
160
|
- `ctx.projectId`, `ctx.orgId`: the run's project, and its org (`null` when
|
|
161
161
|
it has none). The runtime sets them from the run, never from the input.
|
|
162
162
|
To check an id the input names, compare it with these.
|
|
@@ -203,6 +203,34 @@ dropped before your code loads (`kindgi dev` keeps them), so an undeclared
|
|
|
203
203
|
one works locally and is unset once deployed. `KINDGI_*` names are Kindgi's
|
|
204
204
|
own: a pack can't declare one.
|
|
205
205
|
|
|
206
|
+
### Connections to other apps
|
|
207
|
+
|
|
208
|
+
A tool that acts in another app as a person or as the company (sending mail, opening an issue) declares a **connection**, never a secret holding someone's token, and reads the call's short-lived token from `ctx.connections` (runtime 0.2.0 or later):
|
|
209
|
+
|
|
210
|
+
```scala
|
|
211
|
+
val tool: Tool[Input, Output] = Tool[Input, Output]("my-pack.send-mail")
|
|
212
|
+
// …description, version, effects…
|
|
213
|
+
.set("needsSpec", Map("connections" -> Map(
|
|
214
|
+
"mail" -> Map("app" -> "google", "permissions" -> List("gmail.send"), "as" -> "person"))))
|
|
215
|
+
.handler { (in, ctx) =>
|
|
216
|
+
val mail = ctx.connections.get("mail")
|
|
217
|
+
val res = http.send(
|
|
218
|
+
HttpRequest.newBuilder(uri).header("authorization", s"Bearer ${mail.accessToken}").build(),
|
|
219
|
+
HttpResponse.BodyHandlers.ofString())
|
|
220
|
+
if (res.statusCode == 401) throw new ConnectionRejectedException("mail")
|
|
221
|
+
// …
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- **Whose connection:** `"as" -> "person"` is the connection of the person the run acts as (whoever started it, or the owner of the schedule or webhook that did); `"as" -> "company"` is the company's. The runtime picks it from the run, never from the input or the model. A run that acts as nobody (a service account's, an event's) fails a `"person"` call with `connection-needs-a-person`.
|
|
226
|
+
- **The token:** `accessToken` is current for this call only. Never keep, print, log or return it; it never reaches the journal. `account.label` says whose account it is (`ana@acme.com`). `ToolConnection`, `ConnectionAccount` and `ConnectionRejectedException` come with `com.kindgi.pack.scaladsl._`.
|
|
227
|
+
- **A 401 from the app:** `throw new ConnectionRejectedException("mail")`, with the connection's name (a second argument can say what the app answered, never the token), or your own exception with it as the cause. The runtime renews the token once and runs the call again; refused again, the call fails with `connection-rejected`.
|
|
228
|
+
- **An HTTP tool** sends the token with no code: `.authorization(new HttpAuthSpec.Connection("mail"))`.
|
|
229
|
+
- **Unattended runs:** in a run no person started, a tool that uses a `"person"` connection waits for that person's yes, reads included: `.readOnly` doesn't lift it. The agent's own approval settings can't lift it; only a trigger's `toolsAllowedUnattended` can, which a project admin sets, as for `needsApprovalWhenUnattended` (below). In a run a new mail started, the mail is a stranger's text, so two more calls wait: a call of a tool that isn't `.readOnly`, and, when the trigger reads the company's mailbox, a read with the company's connection to that app. The mail trigger's `toolsAllowedUnattended` lifts these too.
|
|
230
|
+
- **In a unit test:** `com.kindgi.pack.ToolContext.forTest(java.util.Map.of("mail", new ToolConnection("c-1", "google", "Google", "test", new ConnectionAccount("1", "ana@acme.com"), null)))`; the last argument, when the token expires, can be `null`. `ctx.connections` is empty when the tool declares none.
|
|
231
|
+
|
|
232
|
+
Docs: https://docs.kindgi.com/v0.2/guides/connections/use-a-connection/
|
|
233
|
+
|
|
206
234
|
## Errors and output
|
|
207
235
|
|
|
208
236
|
- Throw for a failure, or fail the `Future`: the call fails with
|
|
@@ -222,6 +250,10 @@ the tool's approval default: an agent that turns approval gates on
|
|
|
222
250
|
(`conversationPolicy.hitl`) asks before any tool that isn't read-only on its
|
|
223
251
|
first use.
|
|
224
252
|
|
|
253
|
+
In a run a new mail started, a call of a tool that isn't read-only waits
|
|
254
|
+
for a person's yes, unless the mail trigger's `toolsAllowedUnattended`
|
|
255
|
+
lists it.
|
|
256
|
+
|
|
225
257
|
`effect(kind, resource)` declares a side effect, such as
|
|
226
258
|
`.effect("writes", "db:ledger")`. A dry run also stops at a tool with a
|
|
227
259
|
`writes`, `deletes`, `spawns-run`, `emits-event` or `external-side-effect`
|
|
@@ -229,15 +261,58 @@ effect. `set(field, value)` sets the index entry's other fields (`needs`,
|
|
|
229
261
|
`needsSpec`, `sandbox`, `limits`, `network`), with Scala maps and lists. They
|
|
230
262
|
are recorded for policy and review, so declare what the tool really does.
|
|
231
263
|
|
|
232
|
-
|
|
233
|
-
|
|
264
|
+
A tool that calls an HTTP API can be a handler with `java.net.http.HttpClient`,
|
|
265
|
+
as above, or the request declared as data with no handler — see **HTTP tool (as
|
|
266
|
+
data)** below.
|
|
267
|
+
|
|
268
|
+
## HTTP tool (as data)
|
|
269
|
+
|
|
270
|
+
A tool that calls an HTTP API can be the request itself, declared as data,
|
|
271
|
+
instead of a handler: `.http(spec)` in place of `.handler(...)`. The Kindgi
|
|
272
|
+
runtime makes the request from the spec — the SDK only builds and validates it,
|
|
273
|
+
so calling such a tool in this JVM throws. The spec types are Java's, from
|
|
274
|
+
`com.kindgi.pack.http`:
|
|
275
|
+
|
|
276
|
+
```scala
|
|
277
|
+
import com.kindgi.pack.scaladsl._
|
|
278
|
+
import com.kindgi.pack.http._
|
|
279
|
+
|
|
280
|
+
object FetchOrder {
|
|
281
|
+
final case class Input(orderId: String)
|
|
282
|
+
final case class Output(id: String, status: String, total: Double)
|
|
283
|
+
|
|
284
|
+
val tool: Tool[Input, Output] = Tool[Input, Output]("shop.fetch-order")
|
|
285
|
+
.description("Fetch an order by id from the storefront API.")
|
|
286
|
+
.version("0.1.0")
|
|
287
|
+
.readOnly
|
|
288
|
+
.http(
|
|
289
|
+
HttpToolSpec.builder()
|
|
290
|
+
.method(HttpMethod.GET)
|
|
291
|
+
.urlTemplate("https://api.shop.example/orders/{orderId}")
|
|
292
|
+
.authorization(new HttpAuthSpec.Bearer(new ToolSecretRef("production", "shop-api-token")))
|
|
293
|
+
.successStatus(200, 299)
|
|
294
|
+
.build())
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Every `{placeholder}` in the URL — in the path and query only, never in the
|
|
299
|
+
host or port — is a field of the input, and so is one in a
|
|
300
|
+
`HttpRequestBodySpec.Text` body; `.http(...)` throws if it isn't. Authorization
|
|
301
|
+
is a `secretRef` (`HttpAuthSpec.Bearer` or `HttpAuthSpec.Header`), named for the
|
|
302
|
+
runtime to resolve, never a literal credential. A request body is
|
|
303
|
+
`HttpRequestBodySpec.JsonInput` (the input as JSON), `InputPassthrough` or
|
|
304
|
+
`Text`. `timeoutMs` (default 30 seconds) covers the whole call, the response
|
|
305
|
+
read included, and a run's cancel does too; a response body over 10 MiB,
|
|
306
|
+
measured decompressed, fails the call — so point a tool at an endpoint that
|
|
307
|
+
pages or filters, not one that returns everything.
|
|
234
308
|
|
|
235
309
|
## A person's yes when no one is watching: `needsApprovalWhenUnattended`
|
|
236
310
|
|
|
237
|
-
`needsApprovalWhenUnattended(true)` declares that a person must say yes to every call of the tool in a run no person started: one a schedule, a webhook, an event or a service account's key started. In such a run:
|
|
311
|
+
`needsApprovalWhenUnattended(true)` declares that a person must say yes to every call of the tool in a run no person started: one a schedule, a webhook, a new mail, an event or a service account's key started. In such a run:
|
|
238
312
|
|
|
239
313
|
- **An agent's call waits** for a person's yes, whatever the agent's `conversationPolicy.hitl.tools` says. The agent's rules can't lift it: agents are reused, and the tool's author knows what it does.
|
|
240
314
|
- **A flow's tool step that calls it is refused.** Put the tool behind an agent step instead, whose call waits.
|
|
315
|
+
- **A trigger can lift both, for its own runs only.** A project admin names the tool in a webhook trigger's, a schedule's or a mail trigger's `toolsAllowedUnattended` (`--allow-unattended=<tool-id>` on `kindgi webhooks`, `kindgi schedules` and `kindgi mail-triggers`). In that trigger's runs, the tool is then as in a run a person started. The tenant's approval rules still apply.
|
|
241
316
|
|
|
242
317
|
In a run a person started (signed in, or with their own API key), the agent's rules decide, as for any tool. Left unset, it counts as `false`. Declare it on a tool that moves money or changes something people rely on:
|
|
243
318
|
|
|
@@ -247,13 +322,21 @@ In a run a person started (signed in, or with their own API key), the agent's ru
|
|
|
247
322
|
.needsApprovalWhenUnattended(true)
|
|
248
323
|
```
|
|
249
324
|
|
|
250
|
-
Docs: https://docs.kindgi.com/v0.
|
|
325
|
+
Docs: https://docs.kindgi.com/v0.2/guides/approvals/ask-before-a-tool-runs/#when-no-person-started-the-run
|
|
326
|
+
|
|
327
|
+
## Results that are text from outside: `resultIsOutsideData`
|
|
328
|
+
|
|
329
|
+
`resultIsOutsideData(true)` says the tool's results are text from outside that nobody checked, such as a mail someone sent or a page a search found. An agent reads each result of the tool as data, not instructions, in that turn and in every later turn's history. It changes what the model is told, not what the tool may do: pair it with approvals for anything an agent could do with what it read. Absent means `false`.
|
|
251
330
|
|
|
252
331
|
## Testing
|
|
253
332
|
|
|
254
333
|
`tool.call(input, ctx)` runs the handler with the input as given (no schema
|
|
255
334
|
check). `ToolContext.forTest()` is a context with a test tenant and run and
|
|
256
|
-
nothing else.
|
|
335
|
+
nothing else. `ToolContext.forTest(tool, env, secrets)` adds the env values
|
|
336
|
+
the tool declares in `needsSpec`, decided as a run decides them (a schema
|
|
337
|
+
`default` fills a name the test doesn't set, each value is checked, and a
|
|
338
|
+
missing or invalid one throws `IllegalArgumentException`), and the secrets as
|
|
339
|
+
given. A handler that reads the environment and calls a service is
|
|
257
340
|
tested through the method it calls, with a stub server:
|
|
258
341
|
|
|
259
342
|
```scala
|
|
@@ -337,7 +420,7 @@ changes (a removed field, a narrower type), not on every save.
|
|
|
337
420
|
folder, `~/.aws`) or any `.env*` file, and gets `EPERM` there. A tool that
|
|
338
421
|
needs a path names it in `kindgi.config.json`: `"dev": {"sandbox": {"allowRead": ["~/.aws"]}}`.
|
|
339
422
|
Never set `KINDGI_DEV_SANDBOX=off` or `dev.sandbox: false` to get past it
|
|
340
|
-
(https://docs.kindgi.com/v0.
|
|
423
|
+
(https://docs.kindgi.com/v0.2/guides/secrets/dev-sandbox/).
|
|
341
424
|
|
|
342
425
|
## When the framework itself is the problem
|
|
343
426
|
|