kward 0.73.1 → 0.75.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +4 -2
  5. data/Rakefile +18 -0
  6. data/doc/configuration.md +70 -4
  7. data/doc/extensibility.md +6 -19
  8. data/doc/getting-started.md +1 -1
  9. data/doc/lifecycle-hooks.md +424 -0
  10. data/doc/mcp.md +72 -0
  11. data/doc/memory.md +1 -1
  12. data/doc/personas.md +2 -2
  13. data/doc/plugins.md +1 -1
  14. data/doc/releasing.md +7 -15
  15. data/doc/rpc.md +108 -15
  16. data/doc/session-management.md +9 -9
  17. data/doc/skills.md +199 -0
  18. data/doc/usage.md +14 -7
  19. data/lib/kward/agent.rb +72 -22
  20. data/lib/kward/auth/anthropic_oauth.rb +5 -87
  21. data/lib/kward/auth/oauth_helpers.rb +105 -0
  22. data/lib/kward/auth/openai_oauth.rb +4 -86
  23. data/lib/kward/cli/commands.rb +12 -2
  24. data/lib/kward/cli/compaction.rb +7 -0
  25. data/lib/kward/cli/doctor.rb +18 -10
  26. data/lib/kward/cli/git.rb +30 -3
  27. data/lib/kward/cli/hook_commands.rb +258 -0
  28. data/lib/kward/cli/interactive_turn.rb +9 -3
  29. data/lib/kward/cli/memory_commands.rb +1 -5
  30. data/lib/kward/cli/plugins.rb +41 -1
  31. data/lib/kward/cli/prompt_interface.rb +32 -3
  32. data/lib/kward/cli/rendering.rb +1 -1
  33. data/lib/kward/cli/runtime_helpers.rb +44 -5
  34. data/lib/kward/cli/sessions.rb +13 -0
  35. data/lib/kward/cli/settings.rb +226 -152
  36. data/lib/kward/cli/slash_commands.rb +81 -42
  37. data/lib/kward/cli/tabs.rb +32 -15
  38. data/lib/kward/cli.rb +64 -4
  39. data/lib/kward/cli_transcript_formatter.rb +0 -7
  40. data/lib/kward/compaction/token_estimator.rb +112 -0
  41. data/lib/kward/compactor.rb +42 -116
  42. data/lib/kward/config_files.rb +152 -27
  43. data/lib/kward/deep_copy.rb +42 -0
  44. data/lib/kward/diff_view_mode.rb +36 -0
  45. data/lib/kward/events.rb +1 -0
  46. data/lib/kward/export_path.rb +2 -6
  47. data/lib/kward/frontmatter.rb +43 -0
  48. data/lib/kward/hooks/audit_log.rb +121 -0
  49. data/lib/kward/hooks/catalog.rb +110 -0
  50. data/lib/kward/hooks/command_handler.rb +66 -0
  51. data/lib/kward/hooks/config_loader.rb +104 -0
  52. data/lib/kward/hooks/decision.rb +102 -0
  53. data/lib/kward/hooks/event.rb +60 -0
  54. data/lib/kward/hooks/http_handler.rb +72 -0
  55. data/lib/kward/hooks/manager.rb +158 -0
  56. data/lib/kward/hooks/matcher.rb +75 -0
  57. data/lib/kward/hooks.rb +16 -0
  58. data/lib/kward/markdown_transcript.rb +4 -3
  59. data/lib/kward/mcp/client.rb +56 -0
  60. data/lib/kward/mcp/server_config.rb +59 -0
  61. data/lib/kward/mcp/stdio_transport.rb +112 -0
  62. data/lib/kward/memory/turn_context.rb +19 -0
  63. data/lib/kward/message_access.rb +2 -2
  64. data/lib/kward/message_text.rb +19 -0
  65. data/lib/kward/model/client.rb +13 -45
  66. data/lib/kward/model/context_usage.rb +10 -4
  67. data/lib/kward/model/copilot_models.rb +44 -0
  68. data/lib/kward/model/model_info.rb +24 -0
  69. data/lib/kward/model/payloads.rb +15 -17
  70. data/lib/kward/model/stream_parser.rb +178 -13
  71. data/lib/kward/pan/server.rb +51 -2
  72. data/lib/kward/path_guard.rb +13 -0
  73. data/lib/kward/plugin_registry.rb +86 -25
  74. data/lib/kward/prompt_interface/editor/controller.rb +124 -4
  75. data/lib/kward/prompt_interface/editor/modes/emacs.rb +4 -0
  76. data/lib/kward/prompt_interface/editor/modes/modern.rb +10 -4
  77. data/lib/kward/prompt_interface/editor/modes/vibe.rb +448 -20
  78. data/lib/kward/prompt_interface/editor/renderer.rb +27 -0
  79. data/lib/kward/prompt_interface/editor/search.rb +70 -13
  80. data/lib/kward/prompt_interface/editor/state.rb +72 -13
  81. data/lib/kward/prompt_interface/editor/vibe_state.rb +12 -1
  82. data/lib/kward/prompt_interface/selection_prompt.rb +26 -6
  83. data/lib/kward/prompt_interface.rb +4 -1
  84. data/lib/kward/prompts/commands.rb +3 -3
  85. data/lib/kward/prompts.rb +7 -7
  86. data/lib/kward/rpc/mcp_status.rb +50 -0
  87. data/lib/kward/rpc/prompt_bridge.rb +38 -4
  88. data/lib/kward/rpc/runtime_payloads.rb +1 -1
  89. data/lib/kward/rpc/server.rb +94 -13
  90. data/lib/kward/rpc/session_manager.rb +258 -33
  91. data/lib/kward/rpc/session_metrics.rb +1 -1
  92. data/lib/kward/rpc/session_tree_rows.rb +13 -64
  93. data/lib/kward/rpc/tool_event_normalizer.rb +16 -2
  94. data/lib/kward/rpc/transcript_normalizer.rb +9 -10
  95. data/lib/kward/rpc/turn_context.rb +109 -0
  96. data/lib/kward/session_store.rb +6 -20
  97. data/lib/kward/session_tree_nodes.rb +98 -18
  98. data/lib/kward/session_tree_renderer.rb +6 -61
  99. data/lib/kward/skills/registry.rb +109 -17
  100. data/lib/kward/tools/mcp_tool.rb +122 -0
  101. data/lib/kward/tools/read_skill.rb +9 -4
  102. data/lib/kward/tools/registry.rb +297 -9
  103. data/lib/kward/tools/search/code.rb +4 -22
  104. data/lib/kward/tools/search/web.rb +28 -2
  105. data/lib/kward/update_check.rb +117 -0
  106. data/lib/kward/version.rb +1 -1
  107. data/lib/kward/workers/manager.rb +43 -3
  108. data/lib/kward/workspace.rb +3 -1
  109. data/templates/default/fulldoc/html/css/kward.css +22 -0
  110. data/templates/default/fulldoc/html/js/kward.js +2 -0
  111. data/templates/default/kward_navigation.rb +4 -2
  112. data/templates/default/layout/html/setup.rb +2 -0
  113. metadata +30 -1
@@ -0,0 +1,117 @@
1
+ require "fileutils"
2
+ require "json"
3
+ require "net/http"
4
+ require "time"
5
+ require "uri"
6
+
7
+ # Namespace for the Kward CLI agent runtime.
8
+ module Kward
9
+ # Cached RubyGems update check for the interactive startup screen.
10
+ class UpdateCheck
11
+ CHECK_INTERVAL_SECONDS = 24 * 60 * 60
12
+ LATEST_VERSION_URL = URI("https://rubygems.org/api/v1/versions/kward/latest.json")
13
+
14
+ Notice = Struct.new(:latest_version, keyword_init: true)
15
+
16
+ def initialize(current_version:, config: ConfigFiles.read_config, path: ConfigFiles.update_check_cache_path, now: Time.now)
17
+ @current_version = current_version.to_s
18
+ @config = config
19
+ @path = path
20
+ @now = now
21
+ end
22
+
23
+ def enabled?
24
+ return false if disabled_by_environment?
25
+
26
+ updates = @config["updates"]
27
+ return false if updates.is_a?(Hash) && updates["check"] == false
28
+
29
+ true
30
+ end
31
+
32
+ def notice
33
+ return nil unless enabled?
34
+
35
+ latest_version = cache["latest_version"].to_s
36
+ return nil if latest_version.empty?
37
+ return nil if dismissed_version == latest_version
38
+ return nil unless newer_than_current?(latest_version)
39
+
40
+ Notice.new(latest_version: latest_version)
41
+ end
42
+
43
+ def refresh_if_stale
44
+ return false unless enabled?
45
+ return false unless stale?
46
+
47
+ refresh
48
+ end
49
+
50
+ def refresh
51
+ latest_version = fetch_latest_version
52
+ write_cache(cache.merge(
53
+ "checked_at" => @now.utc.iso8601,
54
+ "latest_version" => latest_version
55
+ ))
56
+ true
57
+ rescue StandardError
58
+ false
59
+ end
60
+
61
+ private
62
+
63
+ def disabled_by_environment?
64
+ value = ENV["KWARD_DISABLE_UPDATE_CHECK"].to_s.strip.downcase
65
+ ["1", "true", "yes", "on"].include?(value)
66
+ end
67
+
68
+ def dismissed_version
69
+ cache["dismissed_version"].to_s
70
+ end
71
+
72
+ def stale?
73
+ checked_at = Time.iso8601(cache["checked_at"].to_s)
74
+ (@now - checked_at) >= CHECK_INTERVAL_SECONDS
75
+ rescue ArgumentError, TypeError
76
+ true
77
+ end
78
+
79
+ def cache
80
+ @cache ||= read_cache
81
+ end
82
+
83
+ def read_cache
84
+ return {} unless File.file?(@path)
85
+
86
+ data = JSON.parse(File.read(@path))
87
+ data.is_a?(Hash) ? data : {}
88
+ rescue JSON::ParserError, SystemCallError
89
+ {}
90
+ end
91
+
92
+ def write_cache(data)
93
+ FileUtils.mkdir_p(File.dirname(@path))
94
+ File.write(@path, JSON.pretty_generate(data) + "\n")
95
+ @cache = data
96
+ end
97
+
98
+ def fetch_latest_version
99
+ request = Net::HTTP::Get.new(LATEST_VERSION_URL)
100
+ request["User-Agent"] = "kward/#{Kward::VERSION}"
101
+ response = Net::HTTP.start(LATEST_VERSION_URL.hostname, LATEST_VERSION_URL.port, use_ssl: true, open_timeout: 2, read_timeout: 2) do |http|
102
+ http.request(request)
103
+ end
104
+ return "" unless response.is_a?(Net::HTTPSuccess)
105
+
106
+ JSON.parse(response.body)["version"].to_s
107
+ rescue JSON::ParserError
108
+ ""
109
+ end
110
+
111
+ def newer_than_current?(version)
112
+ Gem::Version.new(version) > Gem::Version.new(@current_version)
113
+ rescue ArgumentError
114
+ false
115
+ end
116
+ end
117
+ end
data/lib/kward/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Namespace for the Kward CLI agent runtime.
2
2
  module Kward
3
3
  # Current gem version.
4
- VERSION = "0.73.1"
4
+ VERSION = "0.75.0"
5
5
  end
@@ -2,6 +2,7 @@ require "timeout"
2
2
  require_relative "../agent"
3
3
  require_relative "../cancellation"
4
4
  require_relative "../conversation"
5
+ require_relative "../hooks"
5
6
  require_relative "../model/client"
6
7
  require_relative "../session_store"
7
8
  require_relative "../tools/registry"
@@ -16,7 +17,7 @@ module Kward
16
17
  class Manager
17
18
  DEFAULT_TIMEOUT_SECONDS = 180
18
19
 
19
- def initialize(client_factory: -> { Client.new }, prompt: nil, workspace_root: Dir.pwd, timeout_seconds: DEFAULT_TIMEOUT_SECONDS, on_status_change: nil, session_store: nil, provider: nil, model: nil, reasoning_effort: nil, write_lock: nil, worker_store: nil, git_guard: nil, write_lane_available: -> { true })
20
+ def initialize(client_factory: -> { Client.new }, prompt: nil, workspace_root: Dir.pwd, timeout_seconds: DEFAULT_TIMEOUT_SECONDS, on_status_change: nil, session_store: nil, provider: nil, model: nil, reasoning_effort: nil, write_lock: nil, worker_store: nil, git_guard: nil, write_lane_available: -> { true }, hook_manager: nil, hook_context: nil)
20
21
  @client_factory = client_factory
21
22
  @prompt = prompt
22
23
  @workspace_root = ConfigFiles.canonical_workspace_root(workspace_root)
@@ -30,12 +31,15 @@ module Kward
30
31
  @worker_store = worker_store
31
32
  @git_guard = git_guard || GitGuard.new(root: @workspace_root)
32
33
  @write_lane_available = write_lane_available
34
+ @hook_manager = hook_manager
35
+ @hook_context = hook_context
33
36
  @workers = {}
34
37
  @mutex = Mutex.new
35
38
  end
36
39
 
37
40
  def start(role:, prompt:, title: nil, id: nil)
38
41
  worker = build_worker(role: role, prompt: prompt, title: title, id: id)
42
+ run_blocking_hook("worker_job_create", worker)
39
43
  enqueue(worker)
40
44
  end
41
45
 
@@ -105,15 +109,19 @@ module Kward
105
109
  worker.conversation = conversation
106
110
  attach_session(worker, conversation)
107
111
  writer_id = wait_for_worker_writer(worker)
112
+ run_blocking_hook("worker_job_start_before", worker)
108
113
  update_status(worker, "running")
114
+ run_hook("worker_job_start_after", worker)
109
115
  registry = ToolRegistry.new(
110
116
  workspace: Workspace.new(root: worker.workspace_root),
111
117
  prompt: @prompt,
112
118
  allowed_tool_names: ToolPolicy.allowed_tool_names(worker.role),
113
119
  write_lock: @write_lock,
114
- writer_id: writer_id
120
+ writer_id: writer_id,
121
+ hook_manager: @hook_manager,
122
+ hook_context: @hook_context
115
123
  )
116
- agent = Agent.new(client: @client_factory.call, tool_registry: registry, conversation: conversation)
124
+ agent = Agent.new(client: @client_factory.call, tool_registry: registry, conversation: conversation, hook_manager: @hook_manager, hook_context: @hook_context)
117
125
  report = Timeout.timeout(@timeout_seconds, WorkerTimeoutError) do
118
126
  agent.ask(worker_prompt(worker), cancellation: worker.cancellation) do |event|
119
127
  worker.record_event(event)
@@ -121,16 +129,48 @@ module Kward
121
129
  end
122
130
  report = finalize_write_worker(worker, report)
123
131
  update_status(worker, "ready", report: report, error: "")
132
+ run_hook("worker_job_ready_for_review", worker)
124
133
  rescue WorkerTimeoutError
125
134
  update_status(worker, "failed", error: "Worker timed out after #{@timeout_seconds} seconds")
135
+ run_hook("worker_job_failed", worker, error: "Worker timed out after #{@timeout_seconds} seconds")
126
136
  rescue Cancellation::CancelledError
127
137
  update_status(worker, "cancelled")
128
138
  rescue StandardError => e
129
139
  update_status(worker, "failed", error: e.message)
140
+ run_hook("worker_job_failed", worker, error: e.message)
130
141
  ensure
131
142
  release_worker_writer(worker)
132
143
  end
133
144
 
145
+ def run_blocking_hook(name, worker, payload = {})
146
+ result = run_hook(name, worker, payload)
147
+ return result unless result && !result.allowed?
148
+
149
+ raise HookDenied, result.decision.message || "Worker lifecycle hook #{name} blocked the job"
150
+ end
151
+
152
+ def run_hook(name, worker, payload = {})
153
+ return unless @hook_manager
154
+
155
+ @hook_manager.run(Hooks::Event.new(
156
+ name: name,
157
+ workspace: { root: worker.workspace_root },
158
+ payload: worker_payload(worker).merge(payload)
159
+ ), context: @hook_context)
160
+ end
161
+
162
+ HookDenied = Class.new(StandardError)
163
+
164
+ def worker_payload(worker)
165
+ {
166
+ worker_id: worker.id,
167
+ role: worker.role,
168
+ title: worker.title,
169
+ status: worker.status,
170
+ session_path: worker.session&.path
171
+ }.compact
172
+ end
173
+
134
174
  def update_status(worker, status, **values)
135
175
  return worker if worker.status == "archived" && status.to_s != "archived"
136
176
 
@@ -2,6 +2,8 @@ require "pathname"
2
2
  require_relative "local_command_runner"
3
3
  require_relative "session_diff"
4
4
 
5
+ require_relative "path_guard"
6
+
5
7
  # Namespace for the Kward CLI agent runtime.
6
8
  module Kward
7
9
  # Filesystem and shell-command boundary for workspace tools.
@@ -212,7 +214,7 @@ module Kward
212
214
  end
213
215
 
214
216
  def inside_workspace?(path)
215
- path.to_s == @root.to_s || path.to_s.start_with?("#{@root}/")
217
+ PathGuard.inside?(path, @root)
216
218
  end
217
219
 
218
220
  def relative_path(path)
@@ -1030,6 +1030,21 @@ body.kward-docs .kward-home #footer p {
1030
1030
  }
1031
1031
 
1032
1032
  @media (max-width: 620px) {
1033
+ .kward-hero > *,
1034
+ .kward-install-card > *,
1035
+ .kward-feature-strip > *,
1036
+ .kward-capabilities li {
1037
+ min-width: 0;
1038
+ }
1039
+
1040
+ .kward-hero h1 {
1041
+ font-size: clamp(32px, 10vw, 38px);
1042
+ }
1043
+
1044
+ .kward-swosh {
1045
+ max-width: 100%;
1046
+ }
1047
+
1033
1048
  .kward-feature-strip,
1034
1049
  .kward-capabilities ul {
1035
1050
  grid-template-columns: 1fr;
@@ -1370,6 +1385,7 @@ body.kward-docs .kward-home #footer {
1370
1385
  flex-direction: column;
1371
1386
  gap: 2px;
1372
1387
  height: auto !important;
1388
+ justify-content: flex-start;
1373
1389
  left: 12px;
1374
1390
  max-height: calc(100vh - 100px);
1375
1391
  overflow-y: auto;
@@ -1810,6 +1826,12 @@ body.kward-docs #toc li > ol {
1810
1826
  margin-top: 6px;
1811
1827
  }
1812
1828
 
1829
+ body.kward-docs #content code,
1830
+ body.kward-docs #filecontents code,
1831
+ body.kward-docs #toc code {
1832
+ overflow-wrap: anywhere;
1833
+ }
1834
+
1813
1835
 
1814
1836
  /* Keep TOC hover states readable on the dark theme. */
1815
1837
  body.kward-docs #toc a:hover,
@@ -8,8 +8,10 @@ const guideLinks = {
8
8
  'doc/session-management.md': 'file.session-management.html',
9
9
  'doc/memory.md': 'file.memory.html',
10
10
  'doc/personas.md': 'file.personas.html',
11
+ 'doc/skills.md': 'file.skills.html',
11
12
  'doc/extensibility.md': 'file.extensibility.html',
12
13
  'doc/plugins.md': 'file.plugins.html',
14
+ 'doc/lifecycle-hooks.md': 'file.lifecycle-hooks.html',
13
15
  'doc/agent-tools.md': 'file.agent-tools.html',
14
16
  'doc/workspace-tools.md': 'file.workspace-tools.html',
15
17
  'doc/web-search.md': 'file.web-search.html',
@@ -18,7 +18,8 @@ module KwardDocsNavigationData
18
18
  ["Sessions", "file.session-management.html"],
19
19
  ["Tabs", "file.tabs.html"],
20
20
  ["Memory", "file.memory.html"],
21
- ["Personas", "file.personas.html"]
21
+ ["Personas", "file.personas.html"],
22
+ ["Skills", "file.skills.html"]
22
23
  ]
23
24
  ],
24
25
  [
@@ -37,7 +38,8 @@ module KwardDocsNavigationData
37
38
  "Customize",
38
39
  [
39
40
  ["Extensibility", "file.extensibility.html"],
40
- ["Plugins", "file.plugins.html"]
41
+ ["Plugins", "file.plugins.html"],
42
+ ["Lifecycle hooks", "file.lifecycle-hooks.html"]
41
43
  ]
42
44
  ],
43
45
  [
@@ -38,8 +38,10 @@ module KwardDocsNavigation
38
38
  "doc/shell.md" => "file.shell.html",
39
39
  "doc/memory.md" => "file.memory.html",
40
40
  "doc/personas.md" => "file.personas.html",
41
+ "doc/skills.md" => "file.skills.html",
41
42
  "doc/extensibility.md" => "file.extensibility.html",
42
43
  "doc/plugins.md" => "file.plugins.html",
44
+ "doc/lifecycle-hooks.md" => "file.lifecycle-hooks.html",
43
45
  "doc/agent-tools.md" => "file.agent-tools.html",
44
46
  "doc/workspace-tools.md" => "file.workspace-tools.html",
45
47
  "doc/context-budgeting.md" => "file.context-budgeting.html",
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.73.1
4
+ version: 0.75.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kai Wood
@@ -137,6 +137,8 @@ files:
137
137
  - doc/files.md
138
138
  - doc/getting-started.md
139
139
  - doc/git.md
140
+ - doc/lifecycle-hooks.md
141
+ - doc/mcp.md
140
142
  - doc/memory.md
141
143
  - doc/personas.md
142
144
  - doc/plugins.md
@@ -144,6 +146,7 @@ files:
144
146
  - doc/rpc.md
145
147
  - doc/session-management.md
146
148
  - doc/shell.md
149
+ - doc/skills.md
147
150
  - doc/tabs.md
148
151
  - doc/troubleshooting.md
149
152
  - doc/usage.md
@@ -158,6 +161,7 @@ files:
158
161
  - lib/kward/auth/anthropic_oauth.rb
159
162
  - lib/kward/auth/file.rb
160
163
  - lib/kward/auth/github_oauth.rb
164
+ - lib/kward/auth/oauth_helpers.rb
161
165
  - lib/kward/auth/openai_oauth.rb
162
166
  - lib/kward/auth/openrouter_api_key.rb
163
167
  - lib/kward/cancellation.rb
@@ -167,6 +171,7 @@ files:
167
171
  - lib/kward/cli/compaction.rb
168
172
  - lib/kward/cli/doctor.rb
169
173
  - lib/kward/cli/git.rb
174
+ - lib/kward/cli/hook_commands.rb
170
175
  - lib/kward/cli/interactive_turn.rb
171
176
  - lib/kward/cli/memory_commands.rb
172
177
  - lib/kward/cli/openrouter_commands.rb
@@ -184,26 +189,45 @@ files:
184
189
  - lib/kward/cli_transcript_formatter.rb
185
190
  - lib/kward/clipboard.rb
186
191
  - lib/kward/compaction/file_operation_tracker.rb
192
+ - lib/kward/compaction/token_estimator.rb
187
193
  - lib/kward/compactor.rb
188
194
  - lib/kward/config_files.rb
189
195
  - lib/kward/context_budget_meter.rb
190
196
  - lib/kward/conversation.rb
197
+ - lib/kward/deep_copy.rb
198
+ - lib/kward/diff_view_mode.rb
191
199
  - lib/kward/editor_mode.rb
192
200
  - lib/kward/ekwsh.rb
193
201
  - lib/kward/events.rb
194
202
  - lib/kward/export_path.rb
203
+ - lib/kward/frontmatter.rb
204
+ - lib/kward/hooks.rb
205
+ - lib/kward/hooks/audit_log.rb
206
+ - lib/kward/hooks/catalog.rb
207
+ - lib/kward/hooks/command_handler.rb
208
+ - lib/kward/hooks/config_loader.rb
209
+ - lib/kward/hooks/decision.rb
210
+ - lib/kward/hooks/event.rb
211
+ - lib/kward/hooks/http_handler.rb
212
+ - lib/kward/hooks/manager.rb
213
+ - lib/kward/hooks/matcher.rb
195
214
  - lib/kward/image_attachments.rb
196
215
  - lib/kward/interactive_pty_runner.rb
197
216
  - lib/kward/local_command_runner.rb
198
217
  - lib/kward/local_pty_command_runner.rb
199
218
  - lib/kward/markdown_transcript.rb
219
+ - lib/kward/mcp/client.rb
220
+ - lib/kward/mcp/server_config.rb
221
+ - lib/kward/mcp/stdio_transport.rb
200
222
  - lib/kward/memory/manager.rb
223
+ - lib/kward/memory/turn_context.rb
201
224
  - lib/kward/message_access.rb
202
225
  - lib/kward/message_text.rb
203
226
  - lib/kward/model/chat_invocation.rb
204
227
  - lib/kward/model/client.rb
205
228
  - lib/kward/model/context_overflow.rb
206
229
  - lib/kward/model/context_usage.rb
230
+ - lib/kward/model/copilot_models.rb
207
231
  - lib/kward/model/model_info.rb
208
232
  - lib/kward/model/payloads.rb
209
233
  - lib/kward/model/retry_message.rb
@@ -211,6 +235,7 @@ files:
211
235
  - lib/kward/openrouter_model_cache.rb
212
236
  - lib/kward/pan/index.html.erb
213
237
  - lib/kward/pan/server.rb
238
+ - lib/kward/path_guard.rb
214
239
  - lib/kward/plugin_registry.rb
215
240
  - lib/kward/private_file.rb
216
241
  - lib/kward/project_files.rb
@@ -265,6 +290,7 @@ files:
265
290
  - lib/kward/rpc/attachment_normalizer.rb
266
291
  - lib/kward/rpc/auth_manager.rb
267
292
  - lib/kward/rpc/config_manager.rb
293
+ - lib/kward/rpc/mcp_status.rb
268
294
  - lib/kward/rpc/memory_methods.rb
269
295
  - lib/kward/rpc/prompt_bridge.rb
270
296
  - lib/kward/rpc/redactor.rb
@@ -278,6 +304,7 @@ files:
278
304
  - lib/kward/rpc/tool_metadata.rb
279
305
  - lib/kward/rpc/transcript_normalizer.rb
280
306
  - lib/kward/rpc/transport.rb
307
+ - lib/kward/rpc/turn_context.rb
281
308
  - lib/kward/scratchpad_runner.rb
282
309
  - lib/kward/session_diff.rb
283
310
  - lib/kward/session_naming.rb
@@ -305,6 +332,7 @@ files:
305
332
  - lib/kward/tools/fetch_content.rb
306
333
  - lib/kward/tools/fetch_raw.rb
307
334
  - lib/kward/tools/list_directory.rb
335
+ - lib/kward/tools/mcp_tool.rb
308
336
  - lib/kward/tools/read_file.rb
309
337
  - lib/kward/tools/read_skill.rb
310
338
  - lib/kward/tools/registry.rb
@@ -318,6 +346,7 @@ files:
318
346
  - lib/kward/tools/web_search.rb
319
347
  - lib/kward/tools/write_file.rb
320
348
  - lib/kward/transcript_export.rb
349
+ - lib/kward/update_check.rb
321
350
  - lib/kward/version.rb
322
351
  - lib/kward/workers.rb
323
352
  - lib/kward/workers/git_guard.rb