kward 0.67.0 → 0.68.0
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/CHANGELOG.md +26 -0
- data/Gemfile.lock +2 -2
- data/README.md +5 -5
- data/doc/authentication.md +24 -1
- data/doc/configuration.md +9 -2
- data/doc/extensibility.md +1 -1
- data/doc/getting-started.md +4 -6
- data/doc/plugins.md +0 -2
- data/doc/releasing.md +7 -8
- data/doc/rpc.md +6 -6
- data/doc/usage.md +5 -2
- data/doc/web-search.md +2 -2
- data/kward.gemspec +4 -0
- data/lib/kward/agent.rb +29 -2
- data/lib/kward/ansi.rb +3 -0
- data/lib/kward/auth/anthropic_oauth.rb +291 -0
- data/lib/kward/auth/file.rb +2 -0
- data/lib/kward/auth/github_oauth.rb +3 -0
- data/lib/kward/auth/openai_oauth.rb +4 -0
- data/lib/kward/auth/openrouter_api_key.rb +2 -0
- data/lib/kward/cancellation.rb +3 -0
- data/lib/kward/cli/auth_commands.rb +82 -0
- data/lib/kward/cli/commands.rb +222 -0
- data/lib/kward/cli/compaction.rb +25 -0
- data/lib/kward/cli/doctor.rb +121 -0
- data/lib/kward/cli/interactive_turn.rb +225 -0
- data/lib/kward/cli/memory_commands.rb +133 -0
- data/lib/kward/cli/plugins.rb +112 -0
- data/lib/kward/cli/prompt_interface.rb +132 -0
- data/lib/kward/cli/rendering.rb +389 -0
- data/lib/kward/cli/runtime_helpers.rb +159 -0
- data/lib/kward/cli/sessions.rb +376 -0
- data/lib/kward/cli/settings.rb +663 -0
- data/lib/kward/cli/slash_commands.rb +112 -0
- data/lib/kward/cli/stats.rb +64 -0
- data/lib/kward/cli/tool_summaries.rb +153 -0
- data/lib/kward/cli.rb +38 -2790
- data/lib/kward/cli_transcript_formatter.rb +4 -7
- data/lib/kward/clipboard.rb +1 -0
- data/lib/kward/compaction/file_operation_tracker.rb +3 -0
- data/lib/kward/compactor.rb +29 -7
- data/lib/kward/config_files.rb +33 -24
- data/lib/kward/conversation.rb +70 -5
- data/lib/kward/events.rb +2 -0
- data/lib/kward/export_path.rb +2 -0
- data/lib/kward/image_attachments.rb +2 -0
- data/lib/kward/markdown_transcript.rb +2 -0
- data/lib/kward/memory/manager.rb +13 -0
- data/lib/kward/message_access.rb +23 -2
- data/lib/kward/message_text.rb +45 -0
- data/lib/kward/model/chat_invocation.rb +2 -0
- data/lib/kward/model/client.rb +295 -77
- data/lib/kward/model/context_overflow.rb +2 -0
- data/lib/kward/model/context_usage.rb +3 -0
- data/lib/kward/model/model_info.rb +143 -4
- data/lib/kward/model/payloads.rb +166 -13
- data/lib/kward/model/retry_message.rb +2 -0
- data/lib/kward/model/stream_parser.rb +129 -0
- data/lib/kward/pan/server.rb +3 -1
- data/lib/kward/plugin_registry.rb +12 -0
- data/lib/kward/private_file.rb +2 -0
- data/lib/kward/prompt_interface/banner.rb +3 -0
- data/lib/kward/prompt_interface/composer_controller.rb +262 -0
- data/lib/kward/prompt_interface/composer_renderer.rb +172 -0
- data/lib/kward/prompt_interface/composer_state.rb +221 -0
- data/lib/kward/prompt_interface/key_handler.rb +365 -0
- data/lib/kward/prompt_interface/layout.rb +31 -0
- data/lib/kward/prompt_interface/overlay_renderer.rb +111 -0
- data/lib/kward/prompt_interface/prompt_renderer.rb +91 -0
- data/lib/kward/prompt_interface/question_prompt.rb +328 -0
- data/lib/kward/prompt_interface/runtime_state.rb +59 -0
- data/lib/kward/prompt_interface/screen.rb +186 -0
- data/lib/kward/prompt_interface/selection_prompt.rb +242 -0
- data/lib/kward/prompt_interface/slash_overlay.rb +102 -0
- data/lib/kward/prompt_interface/stream_state.rb +65 -0
- data/lib/kward/prompt_interface/transcript_buffer.rb +85 -0
- data/lib/kward/prompt_interface/transcript_renderer.rb +142 -0
- data/lib/kward/prompt_interface.rb +69 -1832
- data/lib/kward/prompts/commands.rb +2 -0
- data/lib/kward/prompts/templates.rb +3 -0
- data/lib/kward/prompts.rb +2 -0
- data/lib/kward/question_contract.rb +66 -0
- data/lib/kward/resources/avatar_kward_logo.rb +2 -0
- data/lib/kward/resources/pixel_logo.rb +2 -0
- data/lib/kward/rpc/attachment_normalizer.rb +60 -0
- data/lib/kward/rpc/auth_manager.rb +65 -11
- data/lib/kward/rpc/config_manager.rb +11 -0
- data/lib/kward/rpc/prompt_bridge.rb +5 -26
- data/lib/kward/rpc/redactor.rb +3 -0
- data/lib/kward/rpc/runtime_payloads.rb +4 -1
- data/lib/kward/rpc/server.rb +37 -10
- data/lib/kward/rpc/session_manager.rb +123 -347
- data/lib/kward/rpc/session_metrics.rb +68 -0
- data/lib/kward/rpc/session_tree.rb +48 -0
- data/lib/kward/rpc/session_tree_rows.rb +208 -0
- data/lib/kward/rpc/tool_event_normalizer.rb +3 -0
- data/lib/kward/rpc/tool_metadata.rb +3 -0
- data/lib/kward/rpc/transcript_normalizer.rb +3 -0
- data/lib/kward/rpc/transport.rb +3 -0
- data/lib/kward/session_diff.rb +2 -0
- data/lib/kward/session_store.rb +125 -31
- data/lib/kward/session_trash.rb +1 -0
- data/lib/kward/session_tree_renderer.rb +8 -41
- data/lib/kward/session_tree_tool_display.rb +56 -0
- data/lib/kward/skills/registry.rb +3 -0
- data/lib/kward/starter_pack_installer.rb +1 -0
- data/lib/kward/steering.rb +2 -0
- data/lib/kward/telemetry/logger.rb +3 -0
- data/lib/kward/telemetry/stats.rb +3 -0
- data/lib/kward/tools/ask_user_question.rb +20 -32
- data/lib/kward/tools/base.rb +8 -0
- data/lib/kward/tools/code_search.rb +5 -0
- data/lib/kward/tools/edit_file.rb +5 -0
- data/lib/kward/tools/list_directory.rb +5 -0
- data/lib/kward/tools/read_file.rb +5 -0
- data/lib/kward/tools/read_skill.rb +5 -0
- data/lib/kward/tools/registry.rb +33 -2
- data/lib/kward/tools/run_shell_command.rb +5 -0
- data/lib/kward/tools/search/code.rb +7 -0
- data/lib/kward/tools/search/web.rb +17 -14
- data/lib/kward/tools/tool_call.rb +25 -5
- data/lib/kward/tools/web_search.rb +7 -1
- data/lib/kward/tools/write_file.rb +5 -0
- data/lib/kward/transcript_export.rb +2 -0
- data/lib/kward/version.rb +2 -1
- data/lib/kward/workspace.rb +45 -5
- metadata +43 -1
data/lib/kward/workspace.rb
CHANGED
|
@@ -3,7 +3,19 @@ require "pathname"
|
|
|
3
3
|
require "timeout"
|
|
4
4
|
require_relative "session_diff"
|
|
5
5
|
|
|
6
|
+
# Namespace for the Kward CLI agent runtime.
|
|
6
7
|
module Kward
|
|
8
|
+
# Filesystem and shell-command boundary for workspace tools.
|
|
9
|
+
#
|
|
10
|
+
# `Workspace` is deliberately low-level: it validates paths, enforces output
|
|
11
|
+
# limits, applies exact edits, writes files, and runs shell commands from one
|
|
12
|
+
# root directory. It should not know about model prompts, sessions, telemetry,
|
|
13
|
+
# or UI confirmation. Tool wrappers and frontends provide those policies.
|
|
14
|
+
#
|
|
15
|
+
# Guardrails are enabled by default and require all file paths to resolve under
|
|
16
|
+
# `root`. RPC may report when guardrails are disabled, but callers should avoid
|
|
17
|
+
# bypassing this class for local filesystem mutation so read-before-write and
|
|
18
|
+
# path safety remain consistent.
|
|
7
19
|
class Workspace
|
|
8
20
|
MAX_FILE_BYTES = 256 * 1024
|
|
9
21
|
MAX_READ_OUTPUT_BYTES = 50 * 1024
|
|
@@ -12,6 +24,7 @@ module Kward
|
|
|
12
24
|
MAX_EDIT_DIFF_BYTES = 8 * 1024
|
|
13
25
|
DEFAULT_COMMAND_TIMEOUT_SECONDS = 30
|
|
14
26
|
|
|
27
|
+
# Creates an object for workspace filesystem and shell operations.
|
|
15
28
|
def initialize(root: Dir.pwd, max_file_bytes: MAX_FILE_BYTES, max_read_output_bytes: MAX_READ_OUTPUT_BYTES, max_read_output_lines: MAX_READ_OUTPUT_LINES, max_command_output_bytes: MAX_COMMAND_OUTPUT_BYTES, guardrails: true)
|
|
16
29
|
@root = Pathname.new(root).realpath
|
|
17
30
|
@guardrails = guardrails
|
|
@@ -21,8 +34,10 @@ module Kward
|
|
|
21
34
|
@max_command_output_bytes = max_command_output_bytes
|
|
22
35
|
end
|
|
23
36
|
|
|
37
|
+
# @return [Pathname] canonical workspace root used as the base for file and shell tools
|
|
24
38
|
attr_reader :root
|
|
25
39
|
|
|
40
|
+
# Lists immediate directory children after resolving `path` through workspace guardrails.
|
|
26
41
|
def list_directory(path)
|
|
27
42
|
resolved = workspace_path(path)
|
|
28
43
|
return "Error: not a directory: #{path}" unless File.directory?(resolved)
|
|
@@ -34,6 +49,11 @@ module Kward
|
|
|
34
49
|
"Error: #{e.message}"
|
|
35
50
|
end
|
|
36
51
|
|
|
52
|
+
# Reads a bounded text slice from a workspace file.
|
|
53
|
+
#
|
|
54
|
+
# The returned string is user/model-facing and includes continuation notices
|
|
55
|
+
# when output is truncated. Errors are returned as `"Error: ..."` strings so
|
|
56
|
+
# tool calls can be persisted in the conversation without raising.
|
|
37
57
|
def read_file(path, offset: nil, limit: nil)
|
|
38
58
|
resolved = workspace_path(path)
|
|
39
59
|
return "Error: not a file: #{path}" unless File.file?(resolved)
|
|
@@ -41,11 +61,20 @@ module Kward
|
|
|
41
61
|
size = File.size(resolved)
|
|
42
62
|
return "Error: file too large: #{path} is #{size} bytes; limit is #{@max_file_bytes} bytes" if size > @max_file_bytes
|
|
43
63
|
|
|
44
|
-
|
|
64
|
+
content = File.read(resolved)
|
|
65
|
+
return "Error: not a text file: #{path}" if binary_content?(content)
|
|
66
|
+
|
|
67
|
+
read_file_slice(content, offset: offset, limit: limit)
|
|
45
68
|
rescue SecurityError, Errno::ENOENT => e
|
|
46
69
|
"Error: #{e.message}"
|
|
47
70
|
end
|
|
48
71
|
|
|
72
|
+
# Writes complete file content after enforcing read-before-write for
|
|
73
|
+
# existing files.
|
|
74
|
+
#
|
|
75
|
+
# `read_paths` must contain resolved paths previously observed by
|
|
76
|
+
# `ReadFile`; this keeps tool-driven edits explicit and prevents overwriting
|
|
77
|
+
# unseen user files.
|
|
49
78
|
def write_file(path, content, read_paths:)
|
|
50
79
|
resolved = workspace_write_path(path)
|
|
51
80
|
|
|
@@ -53,10 +82,6 @@ module Kward
|
|
|
53
82
|
return "Error: existing file must be read before writing: #{path}"
|
|
54
83
|
end
|
|
55
84
|
|
|
56
|
-
if block_given? && !yield(relative_path(resolved), content.bytesize)
|
|
57
|
-
return "Declined: write_file was not approved for #{path}"
|
|
58
|
-
end
|
|
59
|
-
|
|
60
85
|
old_content = File.exist?(resolved) ? File.read(resolved) : nil
|
|
61
86
|
File.write(resolved, content)
|
|
62
87
|
output = "Wrote #{content.bytesize} bytes to #{path}"
|
|
@@ -66,6 +91,11 @@ module Kward
|
|
|
66
91
|
"Error: #{e.message}"
|
|
67
92
|
end
|
|
68
93
|
|
|
94
|
+
# Applies exact non-overlapping replacements to a previously read file.
|
|
95
|
+
#
|
|
96
|
+
# Each `old_text` must match exactly once. This favors predictable model edits
|
|
97
|
+
# over fuzzy patching and returns readable error strings when more context is
|
|
98
|
+
# needed.
|
|
69
99
|
def edit_file(path, edits, read_paths:)
|
|
70
100
|
resolved = workspace_path(path)
|
|
71
101
|
return "Error: not a file: #{path}" unless File.file?(resolved)
|
|
@@ -84,6 +114,11 @@ module Kward
|
|
|
84
114
|
"Error: #{e.message}"
|
|
85
115
|
end
|
|
86
116
|
|
|
117
|
+
# Runs a shell command from the workspace root with timeout, cancellation,
|
|
118
|
+
# and bounded combined output.
|
|
119
|
+
#
|
|
120
|
+
# This method intentionally does not ask for confirmation; CLI/RPC policy
|
|
121
|
+
# must decide whether a command is allowed before reaching this boundary.
|
|
87
122
|
def run_shell_command(command, timeout_seconds: DEFAULT_COMMAND_TIMEOUT_SECONDS, cancellation: nil)
|
|
88
123
|
command = command.to_s.strip
|
|
89
124
|
return "Error: command is required" if command.empty?
|
|
@@ -114,6 +149,7 @@ module Kward
|
|
|
114
149
|
"Error: #{e.message}"
|
|
115
150
|
end
|
|
116
151
|
|
|
152
|
+
# Resolves a path with the same guardrails used by file tools.
|
|
117
153
|
def resolved_path(path)
|
|
118
154
|
workspace_path(path)
|
|
119
155
|
end
|
|
@@ -189,6 +225,10 @@ module Kward
|
|
|
189
225
|
output
|
|
190
226
|
end
|
|
191
227
|
|
|
228
|
+
def binary_content?(content)
|
|
229
|
+
content.include?("\x00")
|
|
230
|
+
end
|
|
231
|
+
|
|
192
232
|
def read_start_index(offset)
|
|
193
233
|
return 0 if offset.nil?
|
|
194
234
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kward
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.68.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kai Wood
|
|
@@ -140,12 +140,28 @@ files:
|
|
|
140
140
|
- lib/kward.rb
|
|
141
141
|
- lib/kward/agent.rb
|
|
142
142
|
- lib/kward/ansi.rb
|
|
143
|
+
- lib/kward/auth/anthropic_oauth.rb
|
|
143
144
|
- lib/kward/auth/file.rb
|
|
144
145
|
- lib/kward/auth/github_oauth.rb
|
|
145
146
|
- lib/kward/auth/openai_oauth.rb
|
|
146
147
|
- lib/kward/auth/openrouter_api_key.rb
|
|
147
148
|
- lib/kward/cancellation.rb
|
|
148
149
|
- lib/kward/cli.rb
|
|
150
|
+
- lib/kward/cli/auth_commands.rb
|
|
151
|
+
- lib/kward/cli/commands.rb
|
|
152
|
+
- lib/kward/cli/compaction.rb
|
|
153
|
+
- lib/kward/cli/doctor.rb
|
|
154
|
+
- lib/kward/cli/interactive_turn.rb
|
|
155
|
+
- lib/kward/cli/memory_commands.rb
|
|
156
|
+
- lib/kward/cli/plugins.rb
|
|
157
|
+
- lib/kward/cli/prompt_interface.rb
|
|
158
|
+
- lib/kward/cli/rendering.rb
|
|
159
|
+
- lib/kward/cli/runtime_helpers.rb
|
|
160
|
+
- lib/kward/cli/sessions.rb
|
|
161
|
+
- lib/kward/cli/settings.rb
|
|
162
|
+
- lib/kward/cli/slash_commands.rb
|
|
163
|
+
- lib/kward/cli/stats.rb
|
|
164
|
+
- lib/kward/cli/tool_summaries.rb
|
|
149
165
|
- lib/kward/cli_transcript_formatter.rb
|
|
150
166
|
- lib/kward/clipboard.rb
|
|
151
167
|
- lib/kward/compaction/file_operation_tracker.rb
|
|
@@ -158,6 +174,7 @@ files:
|
|
|
158
174
|
- lib/kward/markdown_transcript.rb
|
|
159
175
|
- lib/kward/memory/manager.rb
|
|
160
176
|
- lib/kward/message_access.rb
|
|
177
|
+
- lib/kward/message_text.rb
|
|
161
178
|
- lib/kward/model/chat_invocation.rb
|
|
162
179
|
- lib/kward/model/client.rb
|
|
163
180
|
- lib/kward/model/context_overflow.rb
|
|
@@ -172,11 +189,28 @@ files:
|
|
|
172
189
|
- lib/kward/private_file.rb
|
|
173
190
|
- lib/kward/prompt_interface.rb
|
|
174
191
|
- lib/kward/prompt_interface/banner.rb
|
|
192
|
+
- lib/kward/prompt_interface/composer_controller.rb
|
|
193
|
+
- lib/kward/prompt_interface/composer_renderer.rb
|
|
194
|
+
- lib/kward/prompt_interface/composer_state.rb
|
|
195
|
+
- lib/kward/prompt_interface/key_handler.rb
|
|
196
|
+
- lib/kward/prompt_interface/layout.rb
|
|
197
|
+
- lib/kward/prompt_interface/overlay_renderer.rb
|
|
198
|
+
- lib/kward/prompt_interface/prompt_renderer.rb
|
|
199
|
+
- lib/kward/prompt_interface/question_prompt.rb
|
|
200
|
+
- lib/kward/prompt_interface/runtime_state.rb
|
|
201
|
+
- lib/kward/prompt_interface/screen.rb
|
|
202
|
+
- lib/kward/prompt_interface/selection_prompt.rb
|
|
203
|
+
- lib/kward/prompt_interface/slash_overlay.rb
|
|
204
|
+
- lib/kward/prompt_interface/stream_state.rb
|
|
205
|
+
- lib/kward/prompt_interface/transcript_buffer.rb
|
|
206
|
+
- lib/kward/prompt_interface/transcript_renderer.rb
|
|
175
207
|
- lib/kward/prompts.rb
|
|
176
208
|
- lib/kward/prompts/commands.rb
|
|
177
209
|
- lib/kward/prompts/templates.rb
|
|
210
|
+
- lib/kward/question_contract.rb
|
|
178
211
|
- lib/kward/resources/avatar_kward_logo.rb
|
|
179
212
|
- lib/kward/resources/pixel_logo.rb
|
|
213
|
+
- lib/kward/rpc/attachment_normalizer.rb
|
|
180
214
|
- lib/kward/rpc/auth_manager.rb
|
|
181
215
|
- lib/kward/rpc/config_manager.rb
|
|
182
216
|
- lib/kward/rpc/prompt_bridge.rb
|
|
@@ -184,6 +218,9 @@ files:
|
|
|
184
218
|
- lib/kward/rpc/runtime_payloads.rb
|
|
185
219
|
- lib/kward/rpc/server.rb
|
|
186
220
|
- lib/kward/rpc/session_manager.rb
|
|
221
|
+
- lib/kward/rpc/session_metrics.rb
|
|
222
|
+
- lib/kward/rpc/session_tree.rb
|
|
223
|
+
- lib/kward/rpc/session_tree_rows.rb
|
|
187
224
|
- lib/kward/rpc/tool_event_normalizer.rb
|
|
188
225
|
- lib/kward/rpc/tool_metadata.rb
|
|
189
226
|
- lib/kward/rpc/transcript_normalizer.rb
|
|
@@ -192,6 +229,7 @@ files:
|
|
|
192
229
|
- lib/kward/session_store.rb
|
|
193
230
|
- lib/kward/session_trash.rb
|
|
194
231
|
- lib/kward/session_tree_renderer.rb
|
|
232
|
+
- lib/kward/session_tree_tool_display.rb
|
|
195
233
|
- lib/kward/skills/registry.rb
|
|
196
234
|
- lib/kward/starter_pack_installer.rb
|
|
197
235
|
- lib/kward/steering.rb
|
|
@@ -220,6 +258,10 @@ licenses:
|
|
|
220
258
|
- MIT
|
|
221
259
|
metadata:
|
|
222
260
|
rubygems_mfa_required: 'true'
|
|
261
|
+
source_code_uri: https://github.com/kaiwood/kward
|
|
262
|
+
changelog_uri: https://github.com/kaiwood/kward/blob/main/CHANGELOG.md
|
|
263
|
+
documentation_uri: https://github.com/kaiwood/kward#readme
|
|
264
|
+
bug_tracker_uri: https://github.com/kaiwood/kward/issues
|
|
223
265
|
rdoc_options: []
|
|
224
266
|
require_paths:
|
|
225
267
|
- lib
|