Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,12 @@ kbagent kai ask --message "question" [--project NAME]
kbagent kai chat --message "msg" [--chat-id ID] [--project NAME]
kbagent kai chat-detail --chat-id ID [--project NAME]
kbagent kai history [--project NAME] [--limit N]
# Default-project resolution (since vNEXT, #684): the `kai` group, `docs query`, `component detail`,
# `component list --query`, `config examples`, and `config new` (scaffold mode) resolve an omitted
# --project through the shared cascade (--project > KBAGENT_PROJECT env > `project use` pin > sole
# project). Before vNEXT these paths used the FIRST REGISTERED project and ignored the pin.
# Several projects with no pin now exit 5 (CONFIG_ERROR) instead of silently picking the first.
# Same fix over `kbagent serve`: /kai/*, POST /documentation/query, GET /components?query=...

kbagent transformation create --project NAME --name NAME (--sql 'SELECT ...' | --sql-file PATH) [--created-table NAME ...] [--component-id ID] [--description D] [--branch ID] [--dry-run]
kbagent transformation show --project NAME --config-id ID [--component-id ID] [--branch ID]
Expand Down
9 changes: 9 additions & 0 deletions plugins/kbagent/agents/keboola-expert.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,15 @@ its absence is NOT a promise the entry is version-independent (see §1 Rule 6).
because the component ships none. Reach for `config examples` or an existing
config in the project instead.

**A command without `--project` refused with CONFIG_ERROR (or picked a project)**
- On **vNEXT+** the `kai` group, `docs query`, `component detail`, `component
list --query`, `config examples`, and `config new` (scaffold mode) resolve an
omitted `--project` through the pin cascade: `--project` > `KBAGENT_PROJECT`
env > `project use` pin > sole project. Several projects and no pin -> exit 5
(`CONFIG_ERROR`). That exit is the fix working, not a bug -- pass `--project`
or run `project use`. On <= 0.90.1 the same commands silently used the FIRST
registered project and ignored the pin (issue #684). gotchas.md.

**Reading job logs / table usage / narrow config search (0.88.0+)**
- `job detail --log-tail-lines N` -- the ONLY route to an already-finished job's
logs (`job run` tails only the run it started). `job list --offset/--sort-by/
Expand Down
12 changes: 6 additions & 6 deletions plugins/kbagent/skills/kbagent/references/commands-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ Requires a **super-admin** Manage API token (same kind as `org setup`). Same def

## Component Discovery
- `component sync-action ACTION_NAME --component-id ID --project ALIAS (--config-id ID [--row-id ID] | --config-data JSON|@file|-) [--branch ID] [--timeout N]` -- run a synchronous component action (`testConnection`, `getTables`, ...) on the `sync-actions.{stack}` service. `ACTION_NAME` is freeform (component-defined; discover via `component detail` `synchronous_actions`). `--row-id` shallow-merges the row over the root config at TOP level only (row `parameters`/`storage` replace root wholesale -- NOT deep merge; MCP `run_sync_action` parity). `--config-data` sends explicit `configData` verbatim. Response is action-specific pass-through. Ports the `run_sync_action` MCP tool. **Since 0.89.0 (#620)** the ROOT configuration's `authorization` and `runtime` blocks are forwarded into `configData` too -- root only (a `--row-id` never overrides them), and only when non-empty. `authorization.oauth_api.id` is the OAuth broker reference the sync-actions service resolves and decrypts, so on 0.88.0 and earlier every sync action on an OAuth / Service-Account component (`keboola.ex-linkedin-ads`, ...) failed with an opaque empty-body 400.
- `config examples --component-id ID [--project NAME] [--row]` -- sample root/row configurations from the AI-service component detail. `--json` emits `{component_id, root_examples, row_examples}`; `--row` limits to row examples. Ports the `get_config_examples` MCP tool.
- `component list [--project NAME] [--type TYPE] [--query "text"]` -- list/search components (AI-powered with `--query`)
- `component detail --component-id ID [--project NAME]` -- show component schema, docs URL, examples. **Since 0.90.0** a component the AI Service does not index (private/deprecated: `keboola.mcp-server-tool`, `keboola.data-apps`) no longer errors -- it falls back to the project's Storage component catalog. `documentation_source` (`"ai_service"` vs `"storage_catalog"`) is on BOTH paths and tells them apart; the fallback has NO configuration examples (`examples_count`/`row_examples_count` always 0), so read `documentation_source` before treating 0 as "this component ships none". `NOT_FOUND` is still raised when both sources miss. **Since 0.90.0** omitting `--project` really does use the first configured project -- on <= 0.89.x it failed with `CONFIG_ERROR: Project 'None' not found` despite the help text, so pass `--project` explicitly there. See `gotchas.md`.
- `config examples --component-id ID [--project NAME] [--row]` -- sample root/row configurations from the AI-service component detail. `--json` emits `{component_id, root_examples, row_examples}`; `--row` limits to row examples. Ports the `get_config_examples` MCP tool. **Since vNEXT (#684)** an omitted `--project` resolves the `project use` pin, not the first registered project. See `gotchas.md`.
- `component list [--project NAME] [--type TYPE] [--query "text"]` -- list/search components (AI-powered with `--query`). **Since vNEXT (#684)** the `--query` path resolves an omitted `--project` through the `project use` pin, not the first registered project. The no-`--query` path still fans out to all projects. See `gotchas.md`.
- `component detail --component-id ID [--project NAME]` -- show component schema, docs URL, examples. **Since 0.90.0** a component the AI Service does not index (private/deprecated: `keboola.mcp-server-tool`, `keboola.data-apps`) no longer errors -- it falls back to the project's Storage component catalog. `documentation_source` (`"ai_service"` vs `"storage_catalog"`) is on BOTH paths and tells them apart; the fallback has NO configuration examples (`examples_count`/`row_examples_count` always 0), so read `documentation_source` before treating 0 as "this component ships none". `NOT_FOUND` is still raised when both sources miss. **Since 0.90.0** omitting `--project` really does fall back to a default project -- on <= 0.89.x it failed with `CONFIG_ERROR: Project 'None' not found` despite the help text, so pass `--project` explicitly there. **Since vNEXT (#684)** that fallback is the `project use` pin (explicit > `KBAGENT_PROJECT` env > pin > sole project), not the first registered project. Several projects with no pin now fail with `CONFIG_ERROR` (exit 5). On 0.90.0-0.90.1 the fallback was the first registered project. See `gotchas.md`.

## Configuration Browsing
- `config list [--project NAME] [--component-type TYPE] [--component-id ID] [--branch ID] [--include-rows]` -- list configs across projects (branch-aware). With `--include-rows` each row extends to include the full `configuration` and `rows` body (noticeably larger payload -- use only when the bodies are needed; the summary default covers name/description/component/last_modified/folder)
Expand All @@ -131,7 +131,7 @@ Requires a **super-admin** Manage API token (same kind as `org setup`). Same def
- `config delete --project NAME --component-id ID --config-id ID [--branch ID] [--dry-run]` -- SOFT-delete a configuration into the Storage trash (restorable). Since 0.89.0 it locates the config first and a config already in the trash is NOT deleted again -- the raw API purges permanently on a second DELETE (the retry-after-timeout trap); kbagent reports `already_in_trash` and exits 0 instead. `--dry-run` reports the located state without writing. Undo with `config restore`. Permission class `destructive`
- `config restore --project NAME --component-id ID --config-id ID [--branch ID]` *(since v0.89.0)* -- restore a trashed configuration (versions, rows and metadata come back). Only works on a config currently in the trash. Permission class `write`
- `config trash-list --project NAME [--component-id ID] [--branch ID]` *(since v0.89.0)* -- list configurations in the trash; each row carries `component_id`, `config_id`, `name`, `version` and `deleted_at`, which is exactly what `config restore` needs. Permission class `read`
- `config new --component-id ID [--project NAME] [--name NAME] [--output-dir DIR] [--push --no-files --description D --configuration JSON|@file|- --configuration-file PATH --no-validate --branch ID --dry-run --allow-plaintext-on-encrypt-failure]` -- **two modes**. **Default (no `--push`)**: scaffold new config from component schema; writes files to `--output-dir` or prints to stdout. **No Storage write calls** -- one AI Service read fetches the component schema/examples (that is what `--project` authenticates even without `--push`). **With `--push`** (0.33.0+, requires `--project` + non-empty `--name`): also POSTs to `/v2/storage/components/{cid}/configs` for a one-shot remote create. `#`-prefixed secrets in the pushed body auto-encrypt via the Encryption API first (fail-closed; since 0.54.0, #378; `--allow-plaintext-on-encrypt-failure` overrides). `--no-files` skips the filesystem step entirely (FIIA-style empty-shell pattern). `--configuration` / `--configuration-file` override the POSTed body (default is `{}`, with validation auto-skipped for the default empty shell). `--dry-run` previews the planned POST + validation result without creating. Since 0.89.0, `--push` + `--output-dir` writes the scaffold WITH `_keboola.config_id` into the subtree of the branch the config was created in (registering the branch in the manifest when missing), so the next `sync push` adopts it instead of duplicating (issue #644); with an explicit body the local file mirrors the pushed encrypted configuration. Schema validation runs by default when an explicit body is given (fail-closed: `ConfigError` exit 5 on mismatch) but skips silently if the AI Service has no schema for the component or returns an error; `--no-validate` opts out. Works for ALL component types including `keboola.snowflake-transformation`. **Since 0.90.0** the scaffold mode's optional `--project` really does fall back to the first configured project when omitted -- on <= 0.89.x it failed with `CONFIG_ERROR: Project 'None' not found` (see `gotchas.md`).
- `config new --component-id ID [--project NAME] [--name NAME] [--output-dir DIR] [--push --no-files --description D --configuration JSON|@file|- --configuration-file PATH --no-validate --branch ID --dry-run --allow-plaintext-on-encrypt-failure]` -- **two modes**. **Default (no `--push`)**: scaffold new config from component schema; writes files to `--output-dir` or prints to stdout. **No Storage write calls** -- one AI Service read fetches the component schema/examples (that is what `--project` authenticates even without `--push`). **With `--push`** (0.33.0+, requires `--project` + non-empty `--name`): also POSTs to `/v2/storage/components/{cid}/configs` for a one-shot remote create. `#`-prefixed secrets in the pushed body auto-encrypt via the Encryption API first (fail-closed; since 0.54.0, #378; `--allow-plaintext-on-encrypt-failure` overrides). `--no-files` skips the filesystem step entirely (FIIA-style empty-shell pattern). `--configuration` / `--configuration-file` override the POSTed body (default is `{}`, with validation auto-skipped for the default empty shell). `--dry-run` previews the planned POST + validation result without creating. Since 0.89.0, `--push` + `--output-dir` writes the scaffold WITH `_keboola.config_id` into the subtree of the branch the config was created in (registering the branch in the manifest when missing), so the next `sync push` adopts it instead of duplicating (issue #644); with an explicit body the local file mirrors the pushed encrypted configuration. Schema validation runs by default when an explicit body is given (fail-closed: `ConfigError` exit 5 on mismatch) but skips silently if the AI Service has no schema for the component or returns an error; `--no-validate` opts out. Works for ALL component types including `keboola.snowflake-transformation`. **Since 0.90.0** the scaffold mode's optional `--project` really does fall back to a default project when omitted -- on <= 0.89.x it failed with `CONFIG_ERROR: Project 'None' not found` (see `gotchas.md`). **Since vNEXT (#684)** that fallback is the `project use` pin, not the first registered project.
- `config clone --project P --component-id ID --config-id ID --name NAME [--target-project P2] [--description D] [--set PATH=VALUE ...] [--secret PATH=VALUE ...] [--branch ID] [--target-branch ID] [--dry-run] [--allow-plaintext-on-encrypt-failure]` (0.84.2+, #587) -- duplicate a configuration **whole**. Reach for this instead of reading `config detail` and rebuilding a body: copying only `configuration["parameters"]` silently drops its siblings (`runtime`, `storage`, `authorization`), and a lost `runtime.parallelism` makes Keboola fall back to `parallelism: 1` -- the reporter's 65-row writer went sequential, 140 min instead of ~60-90, with nothing in any output pointing at it. **Same project** (default): server-side copy via `POST .../configs/{id}/versions/{v}/create`; rows and `KBC::` encrypted values travel with it (verified live). `--set PATH=VALUE` is applied as a follow-up update on the copy, so an override can never be the reason a key went missing. **Cross project** (`--target-project`): reassembled client-side and rows recreated one by one, because encrypted values **cannot** travel -- a Keboola ciphertext is scoped to the project it was encrypted in. Any `KBC::` value makes the clone **fail with exit 5**, listing every path, until re-supplied via `--secret PATH=VALUE` (encrypted in the TARGET project on write). `--dry-run` reports those paths instead of refusing -- run it first to learn what to gather. Storage bucket/table IDs are copied **verbatim, never remapped**; `sync clone` is the command that remaps.
- `config variables-set --project NAME --component-id ID --config-id ID --var KEY=VALUE [--var ...] [--replace] [--variables-id ID] [--values-id ID] [--branch ID] [--dry-run] [--allow-plaintext-on-encrypt-failure] [--yes]` -- attach variable values to a config. Auto-creates a sibling `keboola.variables` config + default row on first use and links it via the parent's `runtime.variables_id` / `variables_values_id`. Defaults to merge; `--replace` drops keys not in `--var`. `#`-prefixed values encrypt via the Encryption API (fail-closed; exit non-zero on `ENCRYPTION_FAILED`). See `variables-workflow.md`
- `config variables-get --project NAME --component-id ID --config-id ID [--branch ID]` -- resolve `variables_id` + `values_id` from the parent config and fetch the current KEY=VALUE map. Returns `{linked: bool, variables_id, values_id, values}`; `linked=false` means the parent has no variables attached
Expand Down Expand Up @@ -279,10 +279,10 @@ Ports the `create_sql_transformation` / `update_sql_transformation` tools (#396)
- `transformation edit --project NAME --config-id ID --change-description TEXT (--op JSON ... | --op-file ops.json) [--storage JSON|@file|-] [--component-id ID] [--branch ID] [--dry-run]` -- 9 ops (`add_block`, `remove_block`, `rename_block`, `add_code`, `remove_code`, `rename_code`, `set_code`, `add_script`, `str_replace`) applied sequentially against batch-start ids. `--storage` REPLACES `configuration.storage` wholesale (include ALL mappings you want to keep). Unknown ids error with the list of valid ids.

## Documentation Q&A
- `docs query "QUESTION" [--project NAME]` -- natural-language answer from the Keboola documentation via the AI Service (server-side RAG, no local corpus). Returns answer text + source URLs; `--json` emits `{query, text, source_urls}`. Unlike `kai ask` it does NOT see project data, works with any token (no master-token / feature-flag requirement), and is the right tool for "how do I ..." questions. Ports the `docs_query` MCP tool.
- `docs query "QUESTION" [--project NAME]` -- natural-language answer from the Keboola documentation via the AI Service (server-side RAG, no local corpus). Returns answer text + source URLs; `--json` emits `{query, text, source_urls}`. Unlike `kai ask` it does NOT see project data, works with any token (no master-token / feature-flag requirement), and is the right tool for "how do I ..." questions. Ports the `docs_query` MCP tool. **Since vNEXT (#684)** an omitted `--project` resolves the `project use` pin, not the first registered project. See `gotchas.md`.

## Kai (Keboola AI Assistant)
Requires the project to be added with its **master ('owner') Storage API token** -- the auto-generated owner token, not a custom one. Custom tokens cannot access Kai. Also requires the `agent-chat` feature flag on the project. Use `kai preflight` to verify both conditions without raising.
Requires the project to be added with its **master ('owner') Storage API token** -- the auto-generated owner token, not a custom one. Custom tokens cannot access Kai. Also requires the `agent-chat` feature flag on the project. Use `kai preflight` to verify both conditions without raising. **Since vNEXT (#684)** every `kai` subcommand resolves an omitted `--project` through the `project use` pin (explicit > `KBAGENT_PROJECT` env > pin > sole project). On 0.90.1 and older the fallback was the first registered project and the pin was ignored -- pass `--project` explicitly there. See `gotchas.md`.
- `kai ping [--project NAME]` -- check Kai server health and MCP connection status. Fails with KAI_NOT_ENABLED if the agent-chat feature is missing or the token is not a master token
- `kai preflight [--project NAME]` -- inspect token readiness WITHOUT raising. Returns `{ok, is_master_token, has_agent_chat_feature, token_description, error}`. Use this in UIs and automation pre-flight checks instead of `ping`
- `kai ask --message "question" [--project NAME]` -- one-shot question to Kai, collects full response
Expand Down
27 changes: 27 additions & 0 deletions plugins/kbagent/skills/kbagent/references/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -4559,6 +4559,8 @@ fallback (`config examples` already resolved it correctly).
`component detail`'s `project_alias` reports the alias actually used (never
`None`). With NO projects configured at all, the failure is an actionable
`CONFIG_ERROR: No projects configured. Use 'kbagent project add' ...`.
Since vNEXT the fallback is the `project use` pin, not the first project --
see the vNEXT gotcha on the `project use` pin (issue #684).
- **<= 0.89.x**: pass `--project` explicitly to these two commands -- the help
text's "first available" promise does not work there.
- `component sync-action` is unaffected: its `--project` is genuinely required
Expand Down Expand Up @@ -4811,3 +4813,28 @@ volatile components without waiting for an upstream kbagent release.
and pushing DELETED the config in production. If you are stuck on an older
version, do not delete-dir-then-push a `keboola.mcp-server-tool` (or any
MCP-workspace) directory -- upgrade instead.

## `kai` / `docs query` / `component` / `config new` now honor the `project use` pin

*(since vNEXT, closes #684)* These commands take an optional `--project`: the whole `kai` group,
`docs query`, `component detail`, `component list --query`, `config examples`,
and `config new` (scaffold mode). Before vNEXT, they resolved an omitted
`--project` to the **first registered project**. They ignored the pin from
`kbagent project use`. With two or more projects registered, the command acted
on the wrong project and reported no warning.

An omitted `--project` now resolves through the same cascade as every other
single-project command:

1. explicit `--project`
2. `KBAGENT_PROJECT` env var
3. the `project use` pin
4. the sole registered project

- **New failure mode**: several projects and no pin now fail with
`CONFIG_ERROR` (exit 5). The message names the three fixes. Before, the
command silently used the first registered project.
- **On 0.90.1 and older**: pass `--project` explicitly whenever the pinned
project is not the first row of `project list`.
- The fix also covers `kbagent serve`: the `/kai/*` routes, `POST /documentation/query`,
and `GET /components?query=...` resolved the project the same wrong way.
Loading