Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"plugins": [
{
"name": "kbagent",
"version": "0.94.0",
"version": "0.95.0",
"source": "./plugins/kbagent",
"description": "DEPRECATED — install from keboola/ai-kit: /plugin marketplace add keboola/ai-kit && /plugin install kbagent@keboola-claude-kit — AI-friendly interface to Keboola Connection projects — explore configs, jobs, lineage, sync configs as files, manage dev branches, and debug SQL in workspaces",
"category": "development"
Expand Down
2 changes: 1 addition & 1 deletion plugins/kbagent/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kbagent",
"version": "0.94.0",
"version": "0.95.0",
"description": "AI-friendly interface to Keboola Connection projects — explore configs, jobs, lineage, sync configs as files, manage dev branches, and debug SQL in workspaces",
"author": {
"name": "Keboola",
Expand Down
31 changes: 23 additions & 8 deletions plugins/kbagent/skills/kbagent/references/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,29 @@ Versioning convention:
counterpart** -- it did not exist when this rule was written and does not
fall under it.
- **The device-login panel's one-click link is conditional -- relay only what
is actually printed (since 0.92.0).** Alongside the verification URL and
code, the panel also prints a pre-filled `verification_uri_complete` link
("Or open this link (code pre-filled):") whenever the stack's device
response includes one; a stack that returns an empty
`verificationUriComplete` prints neither that line nor the label. Don't
promise the user a one-click link unconditionally when relaying the panel
-- check what actually came back and relay only those lines. The URL and
code lines are always present regardless.
is actually printed (since 0.92.0).** The panel prints a pre-filled
`verification_uri_complete` link only when the stack's device response
includes one; a stack that returns an empty `verificationUriComplete`
prints neither the link nor its label. Don't promise the user a one-click
link unconditionally when relaying the panel -- check what actually came
back and relay only those lines. The verification URL and the code are
always present regardless. **The panel's order changed in v0.95.0**: the
pre-filled link is now the headline ("Open this link to finish signing in
(code already filled in):") and the type-it-yourself URL is the fallback
under it ("Or enter the code by hand at this URL:"). It used to be the
other way round, with the link last under "Or open this link (code
pre-filled):" -- so a relay that keys on that old label, or that assumes
the first URL in the panel is the manual one, now picks the wrong line.
- **`press c to copy` is absent exactly when an agent is driving (since
v0.95.0).** In a real terminal the device-login panel is followed by
`Press c to copy the link`, and the keypress is read inside the wait
between device-token polls. The option disables itself -- printing
nothing, output byte-for-byte as before -- in `--json` mode, when stdin or
stdout is not a TTY, or when no native clipboard command is installed
(`pbcopy` on macOS, `clip` on Windows, `wl-copy` / `xclip` / `xsel` /
`clip.exe` on Linux and WSL). A background shell is not a TTY, so the
login you drive will not offer it: relay the link itself, never "press c",
and do not wait for a copy that cannot happen.
- **PKCE is the default; the device flow is a fallback, not a mode switch.**
The CLI tries the browser (PKCE authorization-code) flow first and falls
back to the RFC 8628 device flow ONLY on a *pre-exchange* failure: no
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "keboola-cli"
version = "0.94.0"
version = "0.95.0"
description = "AI-friendly CLI for managing Keboola projects"
readme = "README.md"
requires-python = ">=3.12"
Expand Down
1 change: 1 addition & 0 deletions scratchpad/reply-3984272224.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Confirmed and fixed in e6954b4. `_envelope_holes` now applies the guard's own criterion -- a required key that is absent **or** `None` is a hole, and so is a blank `name` -- so for an ours envelope carrying `"name": null` the candidate is `null`, the reason lands in `warnings[]` ("carries no name -- ... no resolution candidate could be prefilled; author the resolution manually"), `diff --output` refuses instead of writing the file, and `classifiable()` excludes the side rather than classifying against `None`. Pinned in `test_merge_request_service.py` for both `None` and `" "`; the existing end-to-end round-trip pin (`diff --output` -> `resolve --resolved @file` unmodified) still passes. The RFC now says the constant alone did not prevent the drift and records the shared criterion.
3 changes: 3 additions & 0 deletions scratchpad/reply-3984272227.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Confirmed -- and my earlier "both surfaces map `INVALID_ARGUMENT`" was wrong for the CLI side; thanks for checking it. Took the narrow fix in e6954b4: `create` and `update` pre-check `--external-id` against `MERGE_REQUEST_EXTERNAL_ID_MAX_LENGTH` and exit 2 before any call, the same way `request-changes` does for `--reason`. The service keeps the cap as the single rule (serve still answers 400 from it). Pinned for all three flag/command pairs, asserting no service method was called.

I did not remap `INVALID_ARGUMENT` -> 2 in `map_error_to_exit_code`: that is a repo-wide behaviour change (~20 service raise sites across job/data-app/workspace/storage/repo-validate) with no test in the repo pinning either exit code for them, so it would be a silent behaviour change and belongs in its own PR if we want it. Consequence for this PR: `_require_in_conflict_set` and the absent-`branchFromId` case stay at exit 1 on the CLI (400 over serve), consistent with how every other group treats a service-raised `INVALID_ARGUMENT` today. The RFC records the choice and the alternative.
11 changes: 11 additions & 0 deletions scratchpad/zajca-round2-replies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Zajca round 2 -- reply drafts (NOT posted; Martin approves)

## Thread 3984272224 (`_envelope_holes` vs the resolve guard)

Confirmed and fixed in e6954b4. `_envelope_holes` now applies the guard's own criterion -- a required key that is absent **or** `None` is a hole, and so is a blank `name` -- so for an ours envelope carrying `"name": null` the candidate is `null`, the reason lands in `warnings[]` ("carries no name -- ... no resolution candidate could be prefilled; author the resolution manually"), `diff --output` refuses instead of writing the file, and `classifiable()` excludes the side rather than classifying against `None`. Pinned in `test_merge_request_service.py` for both `None` and `" "`; the existing end-to-end round-trip pin (`diff --output` -> `resolve --resolved @file` unmodified) still passes. The RFC now says the constant alone did not prevent the drift and records the shared criterion.

## Thread 3984272227 (`--external-id` exit 1 vs `--reason` exit 2)

Confirmed -- and my earlier "both surfaces map `INVALID_ARGUMENT`" was wrong for the CLI side; thanks for checking it. Took the narrow fix in e6954b4: `create` and `update` pre-check `--external-id` against `MERGE_REQUEST_EXTERNAL_ID_MAX_LENGTH` and exit 2 before any call, the same way `request-changes` does for `--reason`. The service keeps the cap as the single rule (serve still answers 400 from it). Pinned for all three flag/command pairs, asserting no service method was called.

I did not remap `INVALID_ARGUMENT` -> 2 in `map_error_to_exit_code`: that is a repo-wide behaviour change (~20 service raise sites across job/data-app/workspace/storage/repo-validate) with no test in the repo pinning either exit code for them, so it would be a silent behaviour change and belongs in its own PR if we want it. Consequence for this PR: `_require_in_conflict_set` and the absent-`branchFromId` case stay at exit 1 on the CLI (400 over serve), consistent with how every other group treats a service-raised `INVALID_ARGUMENT` today. The RFC records the choice and the alternative.
23 changes: 23 additions & 0 deletions src/keboola_agent_cli/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,29 @@

# Ordered newest-first. Each value is a list of brief one-line descriptions.
CHANGELOG: dict[str, list[str]] = {
"0.95.0": [
"New (#772): `auth login`'s device-code panel now offers `press c to copy` for the "
"verification link, and leads with the pre-filled one-click link. The panel used to print "
"the manual URL + code first and the pre-filled `verification_uri_complete` link last, "
"under `Or open this link (code pre-filled):`; that link is now the headline and the "
"type-the-code URL is the fallback below it. The copy hint reads the single keypress "
"inside the wait the command already does between device-token polls -- no background "
"thread, no redraw -- and copies through a native clipboard command (`pbcopy`, `clip`, "
"`wl-copy`, `xclip`, `xsel`, or `clip.exe` on WSL). It disables itself and prints nothing "
"in `--json` mode, off a TTY, or when no clipboard command is installed, so a scripted or "
"agent-driven login is byte-for-byte unchanged.",
"Note (#768): building kbagent from source now requires uv 0.12.15 or newer "
"(`uv self update`) -- CI gates on `uv audit` instead of pip-audit (CLI-16). This is a "
"contributor-facing requirement: it comes from `[tool.uv] required-version` in this "
"repository's `pyproject.toml`, so installing or updating a published kbagent is "
"unaffected. The dependency audit also moved into its own non-blocking CI job, so an "
"advisory in a transitive dependency reports without failing an unrelated PR.",
"Note (#773): housekeeping with no user-facing change. #773 makes the `_url_copy` tests "
"type-clean (`ty` rejected reading a Rich console's `StringIO` back through "
"`Console.file`) and independent of the machine they run on -- two of them asserted that "
"no clipboard backend is detected, which is true only in a bare CI container and false on "
"macOS, Windows, WSL, or any Linux desktop.",
],
"0.94.0": [
"New (#759): a browser-login session (`auth login`) now works with nearly every command, "
"not just the Storage and Manage paths (CLI-13). It reaches the Scheduler (`flow schedule` / "
Expand Down
Loading