airlok 0.9.0 → 0.9.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  All notable changes to airlok. The format follows Keep a Changelog; versions follow SemVer.
4
4
 
5
+ ## [0.9.2] - 2026-09-13
6
+
7
+ ### Added
8
+
9
+ - Image input. Ctrl+V, or Alt+V, attaches an image from the clipboard and puts a chip like `[image 1: 1024x768 png, 210 KB]` in the line at the cursor, so the sentence can refer to it. Several images fit in one message. The backend is chosen per platform, `osascript` on macOS, `wl-paste` then `xclip` on Linux after checking a display server is running at all, and PowerShell on Windows; `-v` names the one that ran.
10
+ - A path to an image, whether typed, Tab-completed or dropped into the terminal, is offered as an attachment. Taken, it becomes a chip and the picture is what the model gets; refused, the text stays exactly as typed. A path that does not exist, or is not an image, is left alone.
11
+ - `ContentBlock::Image` in the llm crate, sent as base64 on all three wire shapes: Anthropic's `source` object, Chat Completions' `image_url` data URL, and the Responses API's `input_image`. Anything over 1568px on the long edge is downscaled and anything over 5 MB is re-encoded, with a line saying what was done; a message whose images come to more than 20 MB is refused.
12
+ - `[safety] confirm_images`, on by default, asks before an image leaves, because an image cannot be scanned for secrets. `--yes` skips it like the other confirmations, and `/permissions` shows and sets it.
13
+ - `[models."<id>"] vision = false` makes a model that takes no images refuse at attach time, naming the model, instead of failing the turn later as a provider error. A provider that rejects an image now explains itself in terms of that setting.
14
+
15
+ ### Fixed
16
+
17
+ - Session files record an image as its hash, dimensions and format, never its bytes, so `--resume` shows that an image was sent without keeping it. A resumed image becomes a line of text on the way to the provider, since there are no bytes left to send.
18
+ - An image is estimated at a flat token cost rather than the length of its base64. Counting those characters read one screenshot as hundreds of thousands of tokens, which compacted the session on the next turn and made `/context` and the token counter nonsense.
19
+
20
+ ## [0.9.1] - 2026-09-13
21
+
22
+ ### Added
23
+
24
+ - `[provider] api`, settable per model as `[models."<id>"] api`, choosing which OpenAI HTTP API to speak. `"chat"` is the default and is unchanged. On `"responses"` the conversation is sent as input items, a tool call and its result are top-level items joined by `call_id`, the system prompt is sent as `instructions`, and the reasoning effort is an object rather than a string, which is what lets a deployment keep tools and a reasoning effort at the same time.
25
+ - `airlok doctor --offline`, and `/doctor --offline` in a session, which skips the provider request, the one check that leaves the machine, and reports it as skipped rather than dropping the line.
26
+
27
+ ### Fixed
28
+
29
+ - A reasoning effort rejected by the provider now says when the value came from `/effort` and how to put it back, instead of suggesting an edit to a config that already says the right thing. `/effort` also warns when raising the effort on a model whose config pins it to `none`, which is where a deployment starts refusing tools.
30
+ - The argument hint no longer offers the first candidate before anything is typed, so `/goal` no longer reads as an offer to complete to `/goal clear`.
31
+
5
32
  ## [0.9.0] - 2026-09-13
6
33
 
7
34
  ### Added
package/README.md CHANGED
@@ -55,6 +55,8 @@ While a turn runs, a status line below the output shows a spinner, what airlok i
55
55
  | Tab | take the first `/` command, `@` path, or command argument on offer; Tab again cycles through the rest |
56
56
  | Right arrow | take the rest of the `/` command shown after the cursor |
57
57
  | Esc or Ctrl-C | during a turn, cancel it |
58
+ | Ctrl+V | attach an image from the clipboard. A chip like `[image 1: 1024x768 png, 210 KB]` goes in at the cursor, so the sentence can refer to it; several fit in one message. Alt+V does the same, for terminals that keep Ctrl+V for themselves. Every failure says why on its own line |
59
+ | a path to an image | typed, Tab-completed or dropped into the terminal, a path ending `.png`, `.jpg`, `.jpeg`, `.gif` or `.webp` is offered as an attachment. Approved, it becomes a chip, so the model gets the picture rather than the path; refused, it stays as typed |
58
60
  | Ctrl-C | at the prompt, clear the line; on an empty line it does nothing |
59
61
  | Ctrl-D | save and quit |
60
62
  | Ctrl-R | search this run's history; Up and Down step through it |
@@ -94,7 +96,7 @@ A cancelled turn keeps the text streamed so far in the history, marked as interr
94
96
  | `/init` | propose an AIRLOK.md for this repository, as a diff to approve |
95
97
  | `/copy [<n>\|code]` | copy the last reply to the clipboard; a number takes the Nth from the end, `code` the last fenced block |
96
98
  | `/diff [<path>]` | what airlok changed on disk this session, diffed from before its first write |
97
- | `/doctor` | check the config, key, provider, MCP servers, git, terminal and storage; `airlok doctor` does the same and exits non-zero on failure |
99
+ | `/doctor` | check the config, key, provider, MCP servers, git, terminal and storage; `airlok doctor` does the same and exits non-zero on failure. `--offline` skips the provider request, the one check that leaves the machine |
98
100
  | `/goal [<statement>\|clear]` | what the session is working toward, kept in the system prompt every turn and shown in the footer |
99
101
  | `/clear` | start a new session; the current one stays saved |
100
102
  | `/exit` | save and quit; `/quit` works too |
@@ -254,6 +256,7 @@ model = "claude-sonnet-4-6" # per provider: anthropic "claude-sonnet-4-6", ope
254
256
  # base_url = "https://api.openai.com/v1" # openai only; Azure: "https://<resource>.openai.azure.com/openai/v1"
255
257
  # api_key_env = "ANTHROPIC_API_KEY" # env var holding the key
256
258
  # api_key_cmd = "..." # shell command whose stdout is the key
259
+ # api = "chat" # openai only: "chat" (the default) or "responses"
257
260
  context_window = 200000 # input tokens the model accepts; used to decide when to compact
258
261
 
259
262
  [agent]
@@ -266,6 +269,7 @@ keep_recent_turns = 4 # turns kept verbatim after the summary
266
269
  [safety]
267
270
  confirm_writes = true # show a diff and ask before write_file / edit_file
268
271
  confirm_bash = true # ask before running a command that is not allow-listed
272
+ confirm_images = true # ask before sending an image, which cannot be scanned for secrets
269
273
  bash_allowlist = ["git status", "git diff", "ls", "cat", "pwd", "find", "grep", "rg", "cargo check", "cargo test", "cargo build"]
270
274
  bash_denylist = ["rm -rf", "git push --force", "sudo"]
271
275
 
@@ -277,6 +281,8 @@ show_secrets_in_output = false # show secrets from files in full in the termin
277
281
 
278
282
  [models."gpt-6-astra"] # settings for one model id (the deployment name on Azure); none by default
279
283
  reasoning_effort = "none" # openai only, sent as reasoning_effort; not validated
284
+ api = "responses" # openai only, overrides [provider] api for this model
285
+ vision = false # the model takes no images, so airlok refuses at attach time
280
286
  ```
281
287
 
282
288
  For openai, `base_url` falls back to the `OPENAI_BASE_URL` environment variable when the config does not set it.
@@ -299,7 +305,7 @@ base_url = "https://<resource>.openai.azure.com/openai/v1"
299
305
  api_key_cmd = "az cognitiveservices account keys list -n <resource> -g <resource-group> --query key1 -o tsv"
300
306
  ```
301
307
 
302
- Azure's `gpt-6-astra` accepts tools on Chat Completions only with reasoning off, so it needs `[models."gpt-6-astra"]` with `reasoning_effort = "none"`. Without it, airlok shows the provider's error and names that setting. The entry applies however the model is chosen, `/model gpt-6-astra` included.
308
+ Azure's `gpt-6-astra` accepts tools on Chat Completions only with reasoning off, so on that API it needs `[models."gpt-6-astra"]` with `reasoning_effort = "none"`. Giving the model `api = "responses"` instead keeps both the tools and the reasoning effort, which is what makes `/effort` worth using there. With neither, airlok shows the provider's error and names the setting behind it. The entry applies however the model is chosen, `/model gpt-6-astra` included.
303
309
 
304
310
  With this in the user config, plain `airlok "..."` works. The key is sent in Azure's `api-key` header, chosen from the host. No shell wrapper or exported variable is needed.
305
311
 
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT OR Apache-2.0",
21
21
  "name": "airlok",
22
- "version": "0.9.0"
22
+ "version": "0.9.2"
23
23
  },
24
24
  "node_modules/detect-libc": {
25
25
  "engines": {
@@ -48,5 +48,5 @@
48
48
  }
49
49
  },
50
50
  "requires": true,
51
- "version": "0.9.0"
51
+ "version": "0.9.2"
52
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "artifactDownloadUrls": [
3
- "https://github.com/airlok-dev/airlok/releases/download/v0.9.0"
3
+ "https://github.com/airlok-dev/airlok/releases/download/v0.9.2"
4
4
  ],
5
5
  "bin": {
6
6
  "airlok": "run-airlok.js"
@@ -60,7 +60,7 @@
60
60
  "zipExt": ".tar.xz"
61
61
  }
62
62
  },
63
- "version": "0.9.0",
63
+ "version": "0.9.2",
64
64
  "volta": {
65
65
  "node": "18.14.1",
66
66
  "npm": "9.5.0"