agent-harness 0.28.1 → 0.28.3
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.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +14 -0
- data/lib/agent_harness/providers/kilocode.rb +85 -2
- data/lib/agent_harness/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d913e0f2d865b5da590d18bd9b1a62dfc6c2620996c374b844eaff5401b040b2
|
|
4
|
+
data.tar.gz: ef5f41a73da2695a54ca6a8a4c30b169c6c17ec284c5ea718b2cb0eb60edaf9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0838d91fa198bed8eac755a4e8204afbf788c583f4beb6b9e5535337f4b332fe23f9cfb6fc897464002808032c66846f775abafcd6accd967609b89117a25d01'
|
|
7
|
+
data.tar.gz: 8d8e3670c0ae6936ed508851de2693a13a4fb17207ec6105e6f4128857b226beb6de6a75638c177c15a933b3fb8d654988a48d3e7c61c8cffa3a765246deb5b8
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@
|
|
|
6
6
|
* **auth:** add provider-owned PKCE code-exchange API for Claude OAuth (`AgentHarness::Authentication.exchange_code`). Takes an authorization code plus PKCE verifier (and `redirect_uri`/`client_id`), posts an `authorization_code` grant to the Claude token endpoint, and persists the resulting access/refresh tokens in the native `claudeAiOauth` shape. Adds `exchange_code_supported?` and a `code_exchange` key to `auth_capabilities` ([#266](https://github.com/viamin/agent-harness/issues/266)).
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
## [0.28.3](https://github.com/viamin/agent-harness/compare/agent-harness/v0.28.2...agent-harness/v0.28.3) (2026-07-10)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* Kilocode: default external_directory permission blocks /tmp scratch files, silently killing non-interactive runs ([#285](https://github.com/viamin/agent-harness/issues/285)) ([d703c0a](https://github.com/viamin/agent-harness/commit/d703c0abb7b91fb7a5ba8081e612486edff5e8f5))
|
|
15
|
+
|
|
16
|
+
## [0.28.2](https://github.com/viamin/agent-harness/compare/agent-harness/v0.28.1...agent-harness/v0.28.2) (2026-07-10)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* Kilocode: default external_directory permission blocks /tmp scratch files, silently killing non-interactive runs ([#283](https://github.com/viamin/agent-harness/issues/283)) ([1ad518f](https://github.com/viamin/agent-harness/commit/1ad518f5c135c5c95d161b9d41a799692f470f76))
|
|
22
|
+
|
|
9
23
|
## [0.28.1](https://github.com/viamin/agent-harness/compare/agent-harness/v0.28.0...agent-harness/v0.28.1) (2026-07-08)
|
|
10
24
|
|
|
11
25
|
|
|
@@ -13,6 +13,18 @@ module AgentHarness
|
|
|
13
13
|
DEFAULT_VERSION = "7.1.3"
|
|
14
14
|
SUPPORTED_VERSION_REQUIREMENT = "= #{DEFAULT_VERSION}"
|
|
15
15
|
STRUCTURED_EVENT_TYPES = %w[text error step_finish result usage].freeze
|
|
16
|
+
# Kilo CLI (an OpenCode fork) ships the same external_directory
|
|
17
|
+
# permission category as OpenCode, defaulting to "ask" for anything
|
|
18
|
+
# outside the project dir. In non-interactive execution there is no
|
|
19
|
+
# human to answer the prompt, so reads of scratch files under /tmp are
|
|
20
|
+
# auto-rejected and the agent silently loses access to its own scratch
|
|
21
|
+
# output, killing the run without a recoverable error. This default rule
|
|
22
|
+
# broadens the allowlist to all of /tmp so the agent can read back files
|
|
23
|
+
# it (or its sub-agents) wrote there. See #282 (precedent: #277/#280).
|
|
24
|
+
DEFAULT_PERMISSION_EXTERNAL_DIRECTORY_PATTERN = "/tmp/**"
|
|
25
|
+
DEFAULT_PERMISSION_CONFIG = {
|
|
26
|
+
"external_directory" => {DEFAULT_PERMISSION_EXTERNAL_DIRECTORY_PATTERN => "allow"}
|
|
27
|
+
}.freeze
|
|
16
28
|
USAGE_EVENT_TYPES = %w[result usage].freeze
|
|
17
29
|
TOKEN_USAGE_KEYS = %w[
|
|
18
30
|
input_tokens
|
|
@@ -170,8 +182,9 @@ module AgentHarness
|
|
|
170
182
|
provider_name = options[:provider_name] || "openai"
|
|
171
183
|
model_id = options[:model_id]
|
|
172
184
|
|
|
173
|
-
config = {provider
|
|
174
|
-
config[
|
|
185
|
+
config = {"provider" => {provider_name => {}}}
|
|
186
|
+
config["model"] = "#{provider_name}/#{model_id}" if model_id
|
|
187
|
+
apply_default_external_directory_permission(config, options)
|
|
175
188
|
|
|
176
189
|
config.to_json
|
|
177
190
|
end
|
|
@@ -202,6 +215,31 @@ module AgentHarness
|
|
|
202
215
|
cmd
|
|
203
216
|
end
|
|
204
217
|
|
|
218
|
+
# Materialize the permissive external_directory permission (and any other
|
|
219
|
+
# runtime config extras) to +~/.config/kilocode/kilo.json+ before the CLI
|
|
220
|
+
# boots. This is the runtime path that actually fixes #282: without it the
|
|
221
|
+
# permission lives only in {config_file_content}'s return value, which no
|
|
222
|
+
# execution caller invokes, so Kilo would boot with stock "ask" defaults
|
|
223
|
+
# and auto-reject /tmp reads in non-interactive runs. Mirrors the OpenCode
|
|
224
|
+
# precedent in #280.
|
|
225
|
+
def build_execution_preparation(options)
|
|
226
|
+
runtime = options[:provider_runtime]
|
|
227
|
+
return nil unless runtime
|
|
228
|
+
|
|
229
|
+
config_payload = kilocode_config_payload(runtime)
|
|
230
|
+
return nil unless config_payload
|
|
231
|
+
|
|
232
|
+
ExecutionPreparation.new(
|
|
233
|
+
file_writes: [
|
|
234
|
+
{
|
|
235
|
+
path: kilocode_config_path,
|
|
236
|
+
content: serialize_kilocode_config(config_payload),
|
|
237
|
+
mode: 0o600
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
)
|
|
241
|
+
end
|
|
242
|
+
|
|
205
243
|
def parse_response(result, duration:)
|
|
206
244
|
output = result.stdout
|
|
207
245
|
tokens = nil
|
|
@@ -332,6 +370,51 @@ module AgentHarness
|
|
|
332
370
|
|
|
333
371
|
private
|
|
334
372
|
|
|
373
|
+
# Default-merge a permissive external_directory permission into the
|
|
374
|
+
# generated Kilo config unless the caller takes responsibility for
|
|
375
|
+
# permission config. A caller-supplied permission (passed via the
|
|
376
|
+
# +:permission+ option or already present on the config under the
|
|
377
|
+
# +"permission"+ key, e.g. from runtime metadata config extras) is
|
|
378
|
+
# honored verbatim and never overridden, and an invalid or empty
|
|
379
|
+
# caller permission is ignored in favor of the default rule.
|
|
380
|
+
def apply_default_external_directory_permission(config, options = {})
|
|
381
|
+
caller_permission = options[:permission] || options["permission"] || config["permission"]
|
|
382
|
+
if caller_permission.is_a?(Hash) && !caller_permission.empty?
|
|
383
|
+
config["permission"] = deep_dup(caller_permission)
|
|
384
|
+
return
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
config["permission"] = deep_dup(DEFAULT_PERMISSION_CONFIG)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def kilocode_config_path
|
|
391
|
+
"~/.config/kilocode/kilo.json"
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def kilocode_config_payload(runtime)
|
|
395
|
+
metadata = runtime.metadata
|
|
396
|
+
config_extras = metadata[:config] || metadata["config"] || {}
|
|
397
|
+
unless config_extras.is_a?(Hash)
|
|
398
|
+
raise ArgumentError,
|
|
399
|
+
"Kilocode runtime metadata config must be a Hash of provider-specific extras (got #{config_extras.class})"
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
payload = stringify_keys(config_extras)
|
|
403
|
+
payload["model"] = runtime.model if runtime.model
|
|
404
|
+
apply_default_external_directory_permission(payload)
|
|
405
|
+
payload.empty? ? nil : payload
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def serialize_kilocode_config(payload)
|
|
409
|
+
JSON.pretty_generate(payload)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def stringify_keys(hash)
|
|
413
|
+
hash.each_with_object({}) do |(key, value), result|
|
|
414
|
+
result[key.to_s] = value
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
335
418
|
def heartbeat_hook_script(heartbeat_file_path)
|
|
336
419
|
"touch #{Shellwords.escape(heartbeat_file_path)}"
|
|
337
420
|
end
|