kward 0.70.0 → 0.71.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/pages.yml +1 -1
  3. data/CHANGELOG.md +48 -2
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +90 -2
  6. data/README.md +30 -6
  7. data/Rakefile +96 -0
  8. data/doc/agent-tools.md +43 -0
  9. data/doc/api.md +92 -0
  10. data/doc/authentication.md +39 -25
  11. data/doc/configuration.md +1 -15
  12. data/doc/context-tools.md +70 -0
  13. data/doc/plugins.md +2 -2
  14. data/doc/releasing.md +14 -5
  15. data/doc/rpc.md +3 -11
  16. data/doc/session-management.md +220 -0
  17. data/doc/usage.md +7 -8
  18. data/doc/workspace-tools.md +105 -0
  19. data/lib/kward/cli/commands.rb +8 -0
  20. data/lib/kward/cli/openrouter_commands.rb +55 -0
  21. data/lib/kward/cli/prompt_interface.rb +80 -6
  22. data/lib/kward/cli/rendering.rb +11 -6
  23. data/lib/kward/cli/sessions.rb +260 -11
  24. data/lib/kward/cli/settings.rb +0 -30
  25. data/lib/kward/cli/slash_commands.rb +24 -6
  26. data/lib/kward/cli.rb +13 -0
  27. data/lib/kward/compactor.rb +4 -1
  28. data/lib/kward/config_files.rb +4 -6
  29. data/lib/kward/conversation.rb +49 -20
  30. data/lib/kward/model/client.rb +37 -50
  31. data/lib/kward/model/context_usage.rb +13 -6
  32. data/lib/kward/model/model_info.rb +92 -16
  33. data/lib/kward/model/payloads.rb +2 -0
  34. data/lib/kward/openrouter_model_cache.rb +120 -0
  35. data/lib/kward/plugin_registry.rb +47 -1
  36. data/lib/kward/prompt_interface/banner.rb +16 -51
  37. data/lib/kward/prompt_interface/composer_controller.rb +60 -87
  38. data/lib/kward/prompt_interface/composer_renderer.rb +7 -1
  39. data/lib/kward/prompt_interface/key_handler.rb +31 -10
  40. data/lib/kward/prompt_interface/layout.rb +2 -2
  41. data/lib/kward/prompt_interface/prompt_renderer.rb +32 -13
  42. data/lib/kward/prompt_interface/question_prompt.rb +34 -42
  43. data/lib/kward/prompt_interface/runtime_state.rb +6 -1
  44. data/lib/kward/prompt_interface/screen.rb +1 -0
  45. data/lib/kward/prompt_interface/selection_prompt.rb +513 -54
  46. data/lib/kward/prompt_interface/transcript_buffer.rb +7 -16
  47. data/lib/kward/prompt_interface/transcript_renderer.rb +3 -3
  48. data/lib/kward/prompt_interface.rb +22 -28
  49. data/lib/kward/prompts/commands.rb +2 -1
  50. data/lib/kward/prompts.rb +2 -2
  51. data/lib/kward/rpc/server.rb +3 -8
  52. data/lib/kward/rpc/session_manager.rb +17 -6
  53. data/lib/kward/session_store.rb +23 -4
  54. data/lib/kward/telemetry/logger.rb +5 -3
  55. data/lib/kward/tool_output_compactor.rb +127 -0
  56. data/lib/kward/tools/base.rb +8 -2
  57. data/lib/kward/tools/registry.rb +37 -6
  58. data/lib/kward/tools/retrieve_tool_output.rb +71 -0
  59. data/lib/kward/tools/search/web.rb +2 -2
  60. data/lib/kward/tools/summarize_file_structure.rb +29 -0
  61. data/lib/kward/tools/tool_call.rb +2 -0
  62. data/lib/kward/version.rb +1 -1
  63. data/lib/kward/workspace.rb +58 -2
  64. data/templates/default/fulldoc/html/css/kward.css +256 -7
  65. data/templates/default/fulldoc/html/full_list.erb +107 -0
  66. data/templates/default/fulldoc/html/js/kward.js +161 -2
  67. data/templates/default/fulldoc/html/setup.rb +8 -0
  68. data/templates/default/kward_navigation.rb +91 -0
  69. data/templates/default/layout/html/layout.erb +39 -8
  70. data/templates/default/layout/html/setup.rb +33 -38
  71. metadata +13 -3
  72. data/lib/kward/resources/avatar_kward_logo.rb +0 -50
  73. data/lib/kward/resources/pixel_logo.rb +0 -232
@@ -5,17 +5,90 @@ const guideLinks = {
5
5
  'doc/configuration.md': 'file.configuration.html',
6
6
  'doc/authentication.md': 'file.authentication.html',
7
7
  'doc/troubleshooting.md': 'file.troubleshooting.html',
8
+ 'doc/session-management.md': 'file.session-management.html',
8
9
  'doc/memory.md': 'file.memory.html',
9
10
  'doc/personas.md': 'file.personas.html',
10
11
  'doc/extensibility.md': 'file.extensibility.html',
11
12
  'doc/plugins.md': 'file.plugins.html',
13
+ 'doc/agent-tools.md': 'file.agent-tools.html',
14
+ 'doc/workspace-tools.md': 'file.workspace-tools.html',
12
15
  'doc/web-search.md': 'file.web-search.html',
13
16
  'doc/code-search.md': 'file.code-search.html',
17
+ 'doc/context-tools.md': 'file.context-tools.html',
14
18
  'doc/rpc.md': 'file.rpc.html',
15
19
  'doc/releasing.md': 'file.releasing.html'
16
20
  }
17
21
 
18
22
  let pageController = null
23
+ let navigating = false
24
+
25
+ const scrollToCurrentHash = () => {
26
+ if (!window.location.hash) {
27
+ window.scrollTo({ top: 0 })
28
+ return
29
+ }
30
+
31
+ const id = decodeURIComponent(window.location.hash.slice(1))
32
+ const target = document.getElementById(id) || document.getElementsByName(id)[0]
33
+ if (target) target.scrollIntoView()
34
+ }
35
+
36
+ const replacePage = async (url, pushState = true) => {
37
+ if (navigating) return
38
+ navigating = true
39
+ document.documentElement.classList.add('kward-navigating')
40
+
41
+ try {
42
+ const response = await fetch(url, { headers: { 'X-Requested-With': 'Kward-Docs' } })
43
+ if (!response.ok) throw new Error(`Navigation failed with ${response.status}`)
44
+
45
+ const html = await response.text()
46
+ const nextDocument = new DOMParser().parseFromString(html, 'text/html')
47
+ if (!nextDocument.body) throw new Error('Navigation response did not include a body')
48
+
49
+ document.title = nextDocument.title
50
+ document.body.className = nextDocument.body.className
51
+ document.body.innerHTML = nextDocument.body.innerHTML
52
+
53
+ if (pushState) window.history.pushState({ kwardDocs: true }, '', url)
54
+ initializePage()
55
+ scrollToCurrentHash()
56
+ } catch (_error) {
57
+ window.location.href = url
58
+ } finally {
59
+ navigating = false
60
+ document.documentElement.classList.remove('kward-navigating')
61
+ }
62
+ }
63
+
64
+ const isNavigableLink = (event, link) => {
65
+ if (event.defaultPrevented || event.button !== 0) return false
66
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return false
67
+ if (link.target && link.target !== '_self') return false
68
+ if (link.download || link.dataset.noTurbo) return false
69
+
70
+ const url = new URL(link.href, window.location.href)
71
+ if (url.origin !== window.location.origin) return false
72
+ if (url.pathname === window.location.pathname && url.search === window.location.search) return false
73
+
74
+ return url.pathname === '/' || url.pathname.endsWith('/') || url.pathname.endsWith('.html')
75
+ }
76
+
77
+ const visitLink = (link) => replacePage(link.href)
78
+
79
+ const setupTurbolinks = (signal) => {
80
+ document.addEventListener('click', (event) => {
81
+ const link = event.target.closest('a[href]')
82
+ if (!link || !isNavigableLink(event, link)) return
83
+
84
+ event.preventDefault()
85
+ visitLink(link)
86
+ }, { signal })
87
+
88
+ window.addEventListener('popstate', () => {
89
+ replacePage(window.location.href, false)
90
+ }, { signal })
91
+ }
19
92
 
20
93
  const setupGuideSearch = (signal) => {
21
94
  const form = document.querySelector('.kward-guide-search')
@@ -151,7 +224,7 @@ const setupGuideSearch = (signal) => {
151
224
  } else if (event.key === 'Enter') {
152
225
  if (selectedIndex >= 0 && items[selectedIndex]) {
153
226
  event.preventDefault()
154
- window.location.href = items[selectedIndex].href
227
+ visitLink(items[selectedIndex])
155
228
  }
156
229
  }
157
230
  }, { signal })
@@ -159,7 +232,7 @@ const setupGuideSearch = (signal) => {
159
232
  form.addEventListener('submit', (event) => {
160
233
  event.preventDefault()
161
234
  const firstResult = results.querySelector('a')
162
- if (firstResult) window.location.href = firstResult.href
235
+ if (firstResult) visitLink(firstResult)
163
236
  }, { signal })
164
237
 
165
238
  document.addEventListener('click', (event) => {
@@ -252,6 +325,90 @@ const rewriteGuideLinks = () => {
252
325
  })
253
326
  }
254
327
 
328
+ const setupTableOfContents = () => {
329
+ const existingToc = document.getElementById('toc')
330
+ if (document.querySelector('.kward-no-toc')) {
331
+ if (existingToc) existingToc.remove()
332
+ return
333
+ }
334
+
335
+ const fileContents = document.getElementById('filecontents')
336
+ const content = document.getElementById('content')
337
+ if (!fileContents || !content || content.querySelector('#toc')) return
338
+
339
+ const headingTags = ['h2', 'h3', 'h4', 'h5', 'h6']
340
+ if (fileContents.querySelectorAll('h1').length > 1) headingTags.unshift('h1')
341
+
342
+ const headings = Array.from(fileContents.querySelectorAll(headingTags.join(', ')))
343
+ .filter((heading) => !heading.closest('.method_details .docstring') && heading.id !== 'filecontents')
344
+ if (headings.length === 0) return
345
+
346
+ const topLevel = document.createElement('ol')
347
+ topLevel.className = 'top'
348
+
349
+ let currentList = topLevel
350
+ let currentItem = null
351
+ let counter = 0
352
+ let lastLevel = parseInt(headingTags[0].slice(1), 10)
353
+
354
+ headings.forEach((heading) => {
355
+ const level = parseInt(heading.tagName.slice(1), 10)
356
+
357
+ if (!heading.id) {
358
+ let proposedId = heading.getAttribute('toc-id')
359
+ if (!proposedId) {
360
+ proposedId = heading.textContent.replace(/[^a-z0-9-]/gi, '_')
361
+ if (document.getElementById(proposedId)) {
362
+ proposedId += counter
363
+ counter += 1
364
+ }
365
+ }
366
+ heading.id = proposedId
367
+ }
368
+
369
+ if (level > lastLevel) {
370
+ while (level > lastLevel) {
371
+ if (!currentItem) {
372
+ currentItem = document.createElement('li')
373
+ currentList.appendChild(currentItem)
374
+ }
375
+ const nestedList = document.createElement('ol')
376
+ currentItem.appendChild(nestedList)
377
+ currentList = nestedList
378
+ currentItem = null
379
+ lastLevel += 1
380
+ }
381
+ } else if (level < lastLevel) {
382
+ while (level < lastLevel && currentList.parentElement) {
383
+ currentList = currentList.parentElement.parentElement
384
+ lastLevel -= 1
385
+ }
386
+ }
387
+
388
+ const title = heading.getAttribute('toc-title') || heading.textContent
389
+ const item = document.createElement('li')
390
+ const link = document.createElement('a')
391
+ link.href = `#${heading.id}`
392
+ link.textContent = title
393
+ item.appendChild(link)
394
+ currentList.appendChild(item)
395
+ currentItem = item
396
+ })
397
+
398
+ const toc = document.createElement('div')
399
+ toc.id = 'toc'
400
+ toc.innerHTML = '<p class="title hide_toc"><a href="#"><strong>Table of Contents</strong></a></p>'
401
+ toc.appendChild(topLevel)
402
+ content.insertBefore(toc, content.firstChild)
403
+
404
+ const hideLink = toc.querySelector('.hide_toc')
405
+ hideLink.addEventListener('click', (event) => {
406
+ event.preventDefault()
407
+ const hidden = toc.classList.toggle('hidden')
408
+ topLevel.style.display = hidden ? 'none' : ''
409
+ })
410
+ }
411
+
255
412
  const setupCodeCopy = () => {
256
413
  document.querySelectorAll('pre').forEach((block) => {
257
414
  if (block.closest('.code-copy-wrapper')) return
@@ -285,9 +442,11 @@ const initializePage = () => {
285
442
  if (pageController) pageController.abort()
286
443
  pageController = new AbortController()
287
444
 
445
+ setupTurbolinks(pageController.signal)
288
446
  setupGuideSearch(pageController.signal)
289
447
  setupNavigation(pageController.signal)
290
448
  rewriteGuideLinks()
449
+ setupTableOfContents()
291
450
  setupCodeCopy()
292
451
  }
293
452
 
@@ -1,8 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../kward_navigation"
4
+
5
+ include KwardDocsNavigationData
6
+
3
7
  def generate_assets
4
8
  super
5
9
  asset('css/kward.css', file('css/kward.css', true))
6
10
  asset('js/kward.js', file('js/kward.js', true))
7
11
  asset('images/kward_logo.png', file('images/kward_logo.png', true))
8
12
  end
13
+
14
+ def stylesheets_full_list
15
+ super + %w(css/kward.css)
16
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KwardDocsNavigationData
4
+ GUIDE_GROUPS = [
5
+ [
6
+ "Start here",
7
+ [
8
+ ["Getting started", "file.getting-started.html"],
9
+ ["Usage", "file.usage.html"],
10
+ ["Configuration", "file.configuration.html"],
11
+ ["Authentication", "file.authentication.html"],
12
+ ["Troubleshooting", "file.troubleshooting.html"]
13
+ ]
14
+ ],
15
+ [
16
+ "Feature guides",
17
+ [
18
+ ["Sessions", "file.session-management.html"],
19
+ ["Memory", "file.memory.html"],
20
+ ["Personas", "file.personas.html"]
21
+ ]
22
+ ]
23
+ ].freeze
24
+
25
+ EXTENSION_GROUPS = [
26
+ [
27
+ "Customize",
28
+ [
29
+ ["Extensibility", "file.extensibility.html"],
30
+ ["Plugins", "file.plugins.html"]
31
+ ]
32
+ ],
33
+ [
34
+ "Integrate",
35
+ [
36
+ ["RPC protocol", "file.rpc.html"],
37
+ ["Releasing", "file.releasing.html"]
38
+ ]
39
+ ],
40
+ [
41
+ "Agent tools",
42
+ [
43
+ ["Overview", "file.agent-tools.html"],
44
+ ["Workspace tools", "file.workspace-tools.html"],
45
+ ["Web search", "file.web-search.html"],
46
+ ["Code search", "file.code-search.html"],
47
+ ["Context tools", "file.context-tools.html"]
48
+ ]
49
+ ]
50
+ ].freeze
51
+
52
+ API_OVERVIEW = "file.api.html"
53
+ API_GROUPS = [
54
+ [
55
+ "Reference",
56
+ [
57
+ ["Overview", API_OVERVIEW],
58
+ ["Classes & Modules", "class_list.html"],
59
+ ["Methods", "method_list.html"],
60
+ ["Files", "file_list.html"]
61
+ ]
62
+ ],
63
+ [
64
+ "Key namespaces",
65
+ [
66
+ ["Kward", "Kward.html"],
67
+ ["Tools", "Kward/Tools.html"],
68
+ ["RPC", "Kward/RPC.html"],
69
+ ["CLI", "Kward/CLI.html"],
70
+ ["Prompts", "Kward/Prompts.html"],
71
+ ["Skills", "Kward/Skills.html"]
72
+ ]
73
+ ]
74
+ ].freeze
75
+
76
+ def guide_groups
77
+ GUIDE_GROUPS
78
+ end
79
+
80
+ def extension_groups
81
+ EXTENSION_GROUPS
82
+ end
83
+
84
+ def api_groups
85
+ API_GROUPS
86
+ end
87
+
88
+ def api_overview
89
+ API_OVERVIEW
90
+ end
91
+ end
@@ -22,8 +22,8 @@
22
22
  <nav id="kward-primary-nav" class="kward-topnav" aria-label="Primary navigation">
23
23
  <a href="<%= url_for('index.html') %>" class="<%= 'active' if home_page? %>">Home</a>
24
24
  <div class="kward-nav-menu <%= 'active' if guide_page? %>">
25
- <a class="kward-nav-menu-link" href="<%= url_for('file.README.html') %>">User Guides</a>
26
- <button class="kward-nav-menu-button" type="button" aria-label="Expand user guides" aria-expanded="false">⌄</button>
25
+ <a class="kward-nav-menu-link" href="<%= url_for(guide_overview) %>">Guides</a>
26
+ <button class="kward-nav-menu-button" type="button" aria-label="Expand guides" aria-expanded="false">⌄</button>
27
27
  <div class="kward-nav-dropdown">
28
28
  <% guide_groups.each do |title, items| %>
29
29
  <section>
@@ -35,13 +35,44 @@
35
35
  <% end %>
36
36
  </div>
37
37
  </div>
38
- <a href="<%= url_for('Kward.html') %>" class="<%= 'active' if api_page? %>">API Docs</a>
38
+ <div class="kward-nav-menu <%= 'active' if extension_page? %>">
39
+ <a class="kward-nav-menu-link" href="<%= url_for(extension_overview) %>">Advanced</a>
40
+ <button class="kward-nav-menu-button" type="button" aria-label="Expand advanced guides" aria-expanded="false">⌄</button>
41
+ <div class="kward-nav-dropdown kward-advanced-nav-dropdown">
42
+ <% extension_groups.each do |title, items| %>
43
+ <section>
44
+ <h2><%= h title %></h2>
45
+ <% items.each do |label, link| %>
46
+ <a href="<%= url_for(link) %>"><%= h label %></a>
47
+ <% end %>
48
+ </section>
49
+ <% end %>
50
+ </div>
51
+ </div>
52
+ <div class="kward-nav-menu <%= 'active' if api_page? %>">
53
+ <a class="kward-nav-menu-link" href="<%= url_for(api_overview) %>">API Docs</a>
54
+ <button class="kward-nav-menu-button" type="button" aria-label="Expand API docs" aria-expanded="false">⌄</button>
55
+ <div class="kward-nav-dropdown kward-api-nav-dropdown">
56
+ <% api_groups.each do |title, items| %>
57
+ <section>
58
+ <h2><%= h title %></h2>
59
+ <% items.each do |label, link| %>
60
+ <a href="<%= url_for(link) %>"><%= h label %></a>
61
+ <% end %>
62
+ </section>
63
+ <% end %>
64
+ </div>
65
+ </div>
39
66
  </nav>
40
- <form class="kward-guide-search" role="search">
41
- <label class="kward-sr-only" for="kward-guide-search-input">Search user guides</label>
42
- <input id="kward-guide-search-input" type="search" placeholder="Search guides" autocomplete="off" aria-label="Search user guides" aria-controls="kward-guide-search-results">
43
- <div id="kward-guide-search-results" class="kward-guide-search-results" role="listbox" aria-label="Search results"></div>
44
- </form>
67
+ <% if api_page? %>
68
+ <a class="kward-api-index-link" href="<%= url_for('class_list.html') %>">Search API index</a>
69
+ <% else %>
70
+ <form class="kward-guide-search" role="search">
71
+ <label class="kward-sr-only" for="kward-guide-search-input">Search user guides</label>
72
+ <input id="kward-guide-search-input" type="search" placeholder="Search guides" autocomplete="off" aria-label="Search user guides" aria-controls="kward-guide-search-results">
73
+ <div id="kward-guide-search-results" class="kward-guide-search-results" role="listbox" aria-label="Search results"></div>
74
+ </form>
75
+ <% end %>
45
76
  <script type="application/json" id="kward-guide-search-index"><%= guide_search_index_json %></script>
46
77
  </header>
47
78
 
@@ -1,44 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
+ require_relative "../../kward_navigation"
4
5
 
5
6
  module KwardDocsNavigation
6
- GUIDE_GROUPS = [
7
- [
8
- "Start here",
9
- [
10
- ["Getting started", "file.getting-started.html"],
11
- ["Usage", "file.usage.html"],
12
- ["Configuration", "file.configuration.html"],
13
- ["Authentication", "file.authentication.html"],
14
- ["Troubleshooting", "file.troubleshooting.html"]
15
- ]
16
- ],
17
- [
18
- "Feature guides",
19
- [
20
- ["Memory", "file.memory.html"],
21
- ["Personas", "file.personas.html"],
22
- ["Extensibility", "file.extensibility.html"],
23
- ["Plugins", "file.plugins.html"],
24
- ["Web search", "file.web-search.html"],
25
- ["Code search", "file.code-search.html"]
26
- ]
27
- ],
28
- [
29
- "Advanced/reference",
30
- [
31
- ["RPC protocol", "file.rpc.html"],
32
- ["Releasing", "file.releasing.html"]
33
- ]
34
- ]
35
- ].freeze
7
+ include KwardDocsNavigationData
8
+ API_FILE_LINKS = {
9
+ "doc/api.md" => API_OVERVIEW
10
+ }.freeze
11
+ API_LINKS = ([API_OVERVIEW] + API_GROUPS.flat_map { |_title, items| items.map(&:last) }).freeze
12
+
13
+ EXTENSION_OVERVIEW = "file.extensibility.html"
14
+ EXTENSION_LINKS = ([EXTENSION_OVERVIEW] + EXTENSION_GROUPS.flat_map { |_title, items| items.map(&:last) }).uniq.freeze
36
15
 
37
16
  GUIDE_OVERVIEW = "file.README.html"
38
17
  GUIDE_LINKS = ([GUIDE_OVERVIEW] + GUIDE_GROUPS.flat_map { |_title, items| items.map(&:last) }).freeze
39
18
  GUIDE_SEARCH_FILES = [
40
19
  ["Overview", "README.md", GUIDE_OVERVIEW],
41
- *GUIDE_GROUPS.flat_map do |_title, items|
20
+ *(GUIDE_GROUPS + EXTENSION_GROUPS).flat_map do |_title, items|
42
21
  items.map do |label, link|
43
22
  source = "doc/#{link.delete_prefix("file.").delete_suffix(".html")}.md"
44
23
  [label, source, link]
@@ -51,24 +30,28 @@ module KwardDocsNavigation
51
30
  "doc/configuration.md" => "file.configuration.html",
52
31
  "doc/authentication.md" => "file.authentication.html",
53
32
  "doc/troubleshooting.md" => "file.troubleshooting.html",
33
+ "doc/session-management.md" => "file.session-management.html",
54
34
  "doc/memory.md" => "file.memory.html",
55
35
  "doc/personas.md" => "file.personas.html",
56
36
  "doc/extensibility.md" => "file.extensibility.html",
57
37
  "doc/plugins.md" => "file.plugins.html",
38
+ "doc/agent-tools.md" => "file.agent-tools.html",
39
+ "doc/workspace-tools.md" => "file.workspace-tools.html",
58
40
  "doc/web-search.md" => "file.web-search.html",
59
41
  "doc/code-search.md" => "file.code-search.html",
42
+ "doc/context-tools.md" => "file.context-tools.html",
60
43
  "doc/rpc.md" => "file.rpc.html",
61
44
  "doc/releasing.md" => "file.releasing.html"
62
45
  }.freeze
63
46
 
64
- def guide_groups
65
- GUIDE_GROUPS
66
- end
67
-
68
47
  def guide_overview
69
48
  GUIDE_OVERVIEW
70
49
  end
71
50
 
51
+ def extension_overview
52
+ EXTENSION_OVERVIEW
53
+ end
54
+
72
55
  def guide_search_index_json
73
56
  JSON.generate(guide_search_index).gsub("</", "<\\/")
74
57
  end
@@ -99,7 +82,15 @@ module KwardDocsNavigation
99
82
  end
100
83
 
101
84
  def guide_file?
102
- defined?(@file) && GUIDE_FILE_LINKS.key?(@file&.filename.to_s)
85
+ defined?(@file) && GUIDE_LINKS.include?(GUIDE_FILE_LINKS[@file&.filename.to_s])
86
+ end
87
+
88
+ def extension_file?
89
+ defined?(@file) && EXTENSION_LINKS.include?(GUIDE_FILE_LINKS[@file&.filename.to_s])
90
+ end
91
+
92
+ def api_file?
93
+ defined?(@file) && API_FILE_LINKS.key?(@file&.filename.to_s)
103
94
  end
104
95
 
105
96
  def home_page?
@@ -110,8 +101,12 @@ module KwardDocsNavigation
110
101
  (readme_file? && !options.index) || guide_file? || GUIDE_LINKS.include?(current_docs_path)
111
102
  end
112
103
 
104
+ def extension_page?
105
+ extension_file? || EXTENSION_LINKS.include?(current_docs_path)
106
+ end
107
+
113
108
  def api_page?
114
- !home_page? && !guide_page?
109
+ api_file? || API_LINKS.include?(current_docs_path) || (!home_page? && !guide_page? && !extension_page?)
115
110
  end
116
111
 
117
112
  def diskfile
@@ -121,7 +116,7 @@ module KwardDocsNavigation
121
116
  end
122
117
 
123
118
  def rewrite_guide_links(html)
124
- GUIDE_FILE_LINKS.each do |source, target|
119
+ GUIDE_FILE_LINKS.merge(API_FILE_LINKS).each do |source, target|
125
120
  html = html.gsub(%(href="#{source}"), %(href="#{target}"))
126
121
  end
127
122
  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.70.0
4
+ version: 0.71.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kai Wood
@@ -124,9 +124,12 @@ files:
124
124
  - LICENSE
125
125
  - README.md
126
126
  - Rakefile
127
+ - doc/agent-tools.md
128
+ - doc/api.md
127
129
  - doc/authentication.md
128
130
  - doc/code-search.md
129
131
  - doc/configuration.md
132
+ - doc/context-tools.md
130
133
  - doc/extensibility.md
131
134
  - doc/getting-started.md
132
135
  - doc/memory.md
@@ -134,9 +137,11 @@ files:
134
137
  - doc/plugins.md
135
138
  - doc/releasing.md
136
139
  - doc/rpc.md
140
+ - doc/session-management.md
137
141
  - doc/troubleshooting.md
138
142
  - doc/usage.md
139
143
  - doc/web-search.md
144
+ - doc/workspace-tools.md
140
145
  - exe/kward
141
146
  - kward.gemspec
142
147
  - lib/kward.rb
@@ -155,6 +160,7 @@ files:
155
160
  - lib/kward/cli/doctor.rb
156
161
  - lib/kward/cli/interactive_turn.rb
157
162
  - lib/kward/cli/memory_commands.rb
163
+ - lib/kward/cli/openrouter_commands.rb
158
164
  - lib/kward/cli/plugins.rb
159
165
  - lib/kward/cli/prompt_interface.rb
160
166
  - lib/kward/cli/rendering.rb
@@ -186,6 +192,7 @@ files:
186
192
  - lib/kward/model/payloads.rb
187
193
  - lib/kward/model/retry_message.rb
188
194
  - lib/kward/model/stream_parser.rb
195
+ - lib/kward/openrouter_model_cache.rb
189
196
  - lib/kward/pan/index.html.erb
190
197
  - lib/kward/pan/server.rb
191
198
  - lib/kward/plugin_registry.rb
@@ -211,8 +218,6 @@ files:
211
218
  - lib/kward/prompts/commands.rb
212
219
  - lib/kward/prompts/templates.rb
213
220
  - lib/kward/question_contract.rb
214
- - lib/kward/resources/avatar_kward_logo.rb
215
- - lib/kward/resources/pixel_logo.rb
216
221
  - lib/kward/rpc/attachment_normalizer.rb
217
222
  - lib/kward/rpc/auth_manager.rb
218
223
  - lib/kward/rpc/config_manager.rb
@@ -238,6 +243,7 @@ files:
238
243
  - lib/kward/steering.rb
239
244
  - lib/kward/telemetry/logger.rb
240
245
  - lib/kward/telemetry/stats.rb
246
+ - lib/kward/tool_output_compactor.rb
241
247
  - lib/kward/tools/ask_user_question.rb
242
248
  - lib/kward/tools/base.rb
243
249
  - lib/kward/tools/code_search.rb
@@ -248,10 +254,12 @@ files:
248
254
  - lib/kward/tools/read_file.rb
249
255
  - lib/kward/tools/read_skill.rb
250
256
  - lib/kward/tools/registry.rb
257
+ - lib/kward/tools/retrieve_tool_output.rb
251
258
  - lib/kward/tools/run_shell_command.rb
252
259
  - lib/kward/tools/search/code.rb
253
260
  - lib/kward/tools/search/web.rb
254
261
  - lib/kward/tools/search/web_fetch.rb
262
+ - lib/kward/tools/summarize_file_structure.rb
255
263
  - lib/kward/tools/tool_call.rb
256
264
  - lib/kward/tools/web_search.rb
257
265
  - lib/kward/tools/write_file.rb
@@ -260,9 +268,11 @@ files:
260
268
  - lib/kward/workspace.rb
261
269
  - lib/main.rb
262
270
  - templates/default/fulldoc/html/css/kward.css
271
+ - templates/default/fulldoc/html/full_list.erb
263
272
  - templates/default/fulldoc/html/images/kward_logo.png
264
273
  - templates/default/fulldoc/html/js/kward.js
265
274
  - templates/default/fulldoc/html/setup.rb
275
+ - templates/default/kward_navigation.rb
266
276
  - templates/default/layout/html/breadcrumb.erb
267
277
  - templates/default/layout/html/layout.erb
268
278
  - templates/default/layout/html/setup.rb
@@ -1,50 +0,0 @@
1
- # Generated from avatar_kward_32x32.png as RGB terminal cells.
2
- # The interactive banner uses this data instead of decoding a PNG at runtime.
3
- module Kward
4
- # Static avatar logo data used by generated resources.
5
- module Resources
6
- # Static avatar logo data used by generated resources.
7
- module AvatarKwardLogo
8
- PIXELS = [
9
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
10
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, [36, 40, 24], [39, 42, 25], [39, 42, 25], [33, 36, 21], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
11
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, [33, 36, 23], [78, 86, 52], [85, 93, 56], [84, 93, 55], [65, 72, 43], [31, 33, 19], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
12
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, [49, 54, 33], [78, 86, 52], [85, 93, 56], [85, 93, 56], [85, 93, 56], [84, 93, 55], [75, 83, 49], [35, 38, 23], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
13
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, [61, 68, 40], [80, 88, 53], [85, 93, 56], [75, 83, 49], [72, 80, 48], [70, 78, 46], [78, 86, 52], [84, 93, 55], [76, 85, 51], [50, 55, 34], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
14
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, [42, 46, 27], [80, 88, 53], [84, 93, 55], [70, 78, 46], [23, 25, 15], [37, 38, 29], [34, 35, 26], [33, 37, 22], [74, 81, 48], [83, 92, 55], [78, 86, 52], [24, 26, 15], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
15
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, [34, 37, 22], [83, 92, 55], [85, 93, 56], [69, 77, 46], [18, 19, 12], [53, 53, 45], [135, 132, 115], [128, 125, 111], [40, 40, 36], [21, 23, 14], [72, 80, 48], [80, 88, 53], [39, 44, 26], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
16
- [nil, nil, nil, nil, nil, nil, nil, nil, [18, 20, 13], [58, 63, 38], [85, 93, 56], [55, 61, 36], [23, 25, 15], [43, 42, 35], [146, 142, 129], [176, 173, 156], [179, 175, 159], [146, 142, 129], [67, 65, 58], [27, 30, 19], [62, 68, 41], [80, 88, 53], [54, 60, 35], nil, nil, nil, nil, nil, nil, nil, nil, nil],
17
- [nil, nil, nil, nil, nil, nil, nil, nil, [23, 26, 16], [74, 81, 48], [69, 77, 46], [21, 23, 14], [31, 31, 25], [108, 105, 91], [153, 150, 134], [134, 132, 118], [173, 169, 154], [183, 179, 163], [134, 132, 118], [27, 26, 21], [25, 28, 16], [70, 78, 46], [72, 80, 48], [21, 23, 14], nil, nil, nil, nil, nil, nil, nil, nil],
18
- [nil, nil, nil, nil, nil, nil, nil, [8, 10, 6], [66, 73, 45], [58, 63, 37], [14, 15, 9], [3, 3, 2], [87, 85, 74], [160, 157, 139], [160, 157, 139], [134, 132, 118], [80, 78, 69], [173, 169, 154], [175, 171, 155], [76, 74, 65], [5, 5, 4], [14, 15, 9], [63, 70, 42], [66, 73, 45], [2, 3, 2], nil, nil, nil, nil, nil, nil, nil],
19
- [nil, nil, nil, nil, nil, nil, nil, [18, 19, 12], [59, 65, 40], [23, 23, 21], [0, 0, 0], [100, 98, 86], [160, 157, 139], [163, 160, 143], [138, 136, 121], [70, 68, 58], [173, 169, 154], [175, 171, 155], [183, 179, 163], [179, 175, 159], [92, 90, 82], [1, 1, 1], [27, 30, 19], [62, 68, 41], [16, 17, 11], nil, nil, nil, nil, nil, nil, nil],
20
- [nil, nil, nil, nil, nil, nil, [15, 15, 11], [62, 68, 42], [72, 70, 61], [87, 85, 74], [44, 43, 36], [77, 76, 65], [108, 105, 91], [149, 146, 130], [123, 119, 105], [158, 155, 140], [168, 164, 149], [144, 140, 126], [160, 156, 142], [118, 115, 104], [77, 76, 65], [53, 53, 45], [103, 102, 85], [76, 74, 65], [66, 72, 43], [20, 20, 13], nil, nil, nil, nil, nil, nil],
21
- [nil, nil, nil, nil, nil, nil, [35, 38, 23], [78, 86, 52], [135, 132, 115], [113, 109, 94], [129, 128, 109], [23, 25, 15], [33, 55, 8], [96, 108, 72], [87, 85, 74], [168, 164, 149], [158, 155, 140], [97, 94, 83], [96, 108, 72], [24, 40, 6], [30, 33, 20], [142, 141, 122], [104, 102, 90], [153, 150, 134], [75, 83, 49], [37, 41, 25], nil, nil, nil, nil, nil, nil],
22
- [nil, nil, nil, nil, nil, [2, 2, 1], [63, 70, 42], [87, 95, 60], [134, 132, 118], [77, 76, 65], [104, 102, 90], [5, 5, 4], [72, 133, 6], [100, 184, 10], [39, 44, 26], [160, 156, 142], [146, 142, 129], [47, 70, 19], [103, 188, 10], [56, 105, 5], [10, 10, 8], [128, 125, 111], [72, 70, 61], [149, 146, 130], [84, 93, 55], [54, 60, 36], [2, 3, 2], nil, nil, nil, nil, nil],
23
- [nil, nil, nil, nil, nil, [46, 51, 30], [67, 74, 44], [44, 48, 30], [114, 111, 97], [80, 78, 69], [103, 102, 85], [34, 35, 26], [33, 55, 8], [59, 97, 13], [82, 84, 65], [166, 162, 147], [156, 152, 138], [76, 85, 51], [59, 97, 13], [29, 46, 8], [43, 42, 35], [134, 132, 118], [92, 90, 82], [128, 125, 111], [39, 44, 26], [65, 72, 43], [43, 48, 29], nil, nil, nil, nil, nil],
24
- [nil, nil, nil, nil, [17, 19, 12], [63, 70, 42], [31, 35, 21], [5, 5, 4], [39, 39, 33], [70, 68, 58], [53, 53, 45], [103, 102, 85], [58, 56, 48], [77, 76, 65], [113, 109, 94], [171, 167, 151], [163, 160, 143], [108, 105, 91], [72, 70, 61], [64, 62, 54], [108, 105, 91], [59, 58, 50], [84, 82, 71], [39, 39, 33], [3, 3, 2], [39, 44, 26], [58, 64, 39], nil, nil, nil, nil, nil],
25
- [nil, nil, nil, [2, 3, 2], [43, 47, 28], [68, 75, 45], [15, 17, 11], [0, 0, 0], [0, 0, 0], [8, 8, 7], [12, 12, 11], [59, 58, 50], [92, 89, 75], [27, 26, 21], [100, 96, 82], [171, 167, 151], [163, 160, 143], [70, 68, 58], [44, 43, 36], [114, 111, 97], [58, 56, 48], [15, 14, 13], [5, 5, 4], [0, 0, 0], [0, 0, 0], [23, 25, 15], [69, 77, 46], [30, 33, 20], nil, nil, nil, nil],
26
- [nil, nil, nil, [37, 41, 26], [63, 70, 42], [27, 30, 19], [1, 1, 1], [0, 0, 0], [8, 8, 7], [32, 33, 30], [20, 20, 18], [6, 6, 5], [64, 62, 54], [31, 31, 25], [100, 96, 82], [171, 167, 151], [163, 160, 143], [70, 68, 58], [51, 49, 43], [70, 68, 58], [6, 6, 5], [23, 23, 21], [35, 35, 33], [6, 6, 5], [0, 0, 0], [1, 1, 1], [33, 37, 22], [58, 63, 37], [32, 35, 21], nil, nil, nil],
27
- [nil, nil, nil, [52, 58, 35], [80, 88, 53], [52, 58, 34], [10, 10, 8], [5, 5, 4], [32, 33, 30], [23, 23, 21], [0, 0, 0], [23, 23, 21], [59, 58, 50], [70, 68, 58], [72, 70, 61], [166, 162, 147], [153, 150, 134], [67, 65, 58], [76, 74, 65], [62, 61, 57], [19, 19, 17], [0, 0, 0], [31, 31, 25], [32, 33, 30], [3, 3, 2], [15, 17, 11], [55, 61, 36], [80, 88, 53], [39, 42, 25], nil, nil, nil],
28
- [nil, nil, nil, [23, 24, 16], [54, 60, 36], [83, 92, 55], [27, 30, 19], [44, 44, 40], [19, 19, 17], [1, 1, 1], [1, 1, 1], [49, 48, 45], [44, 44, 40], [103, 102, 85], [44, 44, 40], [158, 155, 140], [144, 140, 126], [64, 62, 54], [92, 89, 75], [49, 48, 45], [40, 40, 36], [0, 0, 0], [3, 3, 2], [19, 19, 17], [49, 48, 45], [36, 40, 24], [83, 92, 55], [44, 48, 30], [23, 25, 16], nil, nil, nil],
29
- [nil, nil, nil, [50, 55, 34], [49, 54, 33], [62, 68, 41], [67, 74, 44], [30, 33, 20], [12, 12, 11], [30, 30, 28], [20, 20, 18], [30, 30, 28], [12, 12, 11], [92, 89, 75], [51, 49, 43], [160, 156, 142], [144, 140, 126], [64, 62, 54], [77, 76, 65], [12, 12, 11], [35, 35, 33], [17, 17, 16], [35, 35, 33], [10, 10, 8], [34, 35, 26], [68, 75, 45], [58, 63, 37], [51, 56, 34], [43, 48, 29], nil, nil, nil],
30
- [nil, nil, [30, 33, 21], [68, 75, 45], [70, 78, 46], [39, 44, 26], [59, 65, 40], [67, 74, 44], [21, 23, 14], [8, 8, 7], [19, 19, 17], [32, 33, 30], [10, 10, 8], [15, 14, 13], [92, 89, 75], [168, 164, 149], [160, 157, 139], [70, 68, 58], [12, 12, 11], [10, 10, 8], [35, 35, 33], [17, 17, 16], [10, 10, 8], [21, 23, 14], [72, 80, 48], [55, 61, 36], [47, 52, 31], [72, 80, 48], [66, 72, 43], [25, 26, 18], nil, nil],
31
- [nil, nil, [22, 24, 14], [27, 30, 18], [55, 61, 36], [84, 93, 55], [44, 48, 30], [54, 60, 36], [74, 81, 48], [25, 28, 16], [1, 1, 1], [49, 48, 45], [32, 33, 30], [1, 1, 1], [92, 89, 75], [123, 119, 105], [118, 115, 104], [67, 63, 54], [1, 1, 1], [44, 44, 40], [40, 40, 36], [1, 1, 1], [30, 33, 20], [76, 85, 51], [52, 58, 34], [51, 56, 34], [81, 90, 54], [47, 52, 31], [26, 28, 17], nil, nil, nil],
32
- [nil, [30, 33, 21], [66, 72, 43], [80, 88, 53], [80, 88, 53], [45, 50, 29], [33, 37, 22], [51, 56, 34], [42, 47, 27], [68, 75, 45], [38, 42, 25], [19, 19, 17], [35, 35, 33], [12, 12, 11], [37, 35, 30], [70, 68, 58], [67, 63, 54], [27, 26, 21], [17, 17, 16], [35, 35, 33], [17, 17, 16], [39, 44, 26], [70, 78, 46], [42, 47, 27], [54, 60, 36], [31, 35, 21], [31, 35, 21], [63, 70, 42], [78, 86, 52], [65, 71, 42], nil, nil],
33
- [nil, [14, 15, 9], [36, 39, 23], [63, 70, 42], [81, 90, 54], [62, 68, 41], [51, 56, 34], [39, 44, 26], [14, 15, 9], [49, 54, 33], [69, 77, 46], [25, 28, 16], [20, 20, 18], [8, 8, 7], [6, 6, 5], [43, 42, 35], [37, 35, 30], [3, 3, 2], [12, 12, 11], [19, 19, 17], [30, 33, 20], [70, 78, 46], [44, 48, 30], [14, 15, 9], [44, 48, 30], [49, 54, 33], [52, 58, 34], [72, 80, 48], [54, 60, 36], [36, 39, 23], [12, 14, 11], nil],
34
- [nil, [5, 5, 5], nil, [53, 58, 35], [84, 93, 55], [84, 93, 55], [81, 90, 54], [69, 77, 46], [55, 61, 36], [15, 17, 11], [39, 44, 26], [68, 75, 45], [59, 65, 40], [18, 19, 12], [10, 10, 8], [62, 61, 57], [56, 55, 53], [6, 6, 5], [23, 25, 15], [63, 70, 42], [69, 77, 46], [36, 40, 24], [15, 17, 11], [58, 63, 37], [67, 74, 44], [80, 88, 53], [84, 93, 55], [83, 92, 55], [39, 43, 26], nil, [2, 2, 1], nil],
35
- [nil, nil, nil, [25, 29, 18], [45, 50, 29], [27, 30, 19], [22, 25, 15], [75, 83, 50], [84, 93, 55], [54, 60, 36], [15, 17, 11], [18, 19, 12], [42, 47, 27], [74, 81, 48], [12, 12, 11], [23, 23, 21], [19, 19, 17], [30, 33, 20], [74, 81, 48], [38, 42, 25], [15, 17, 11], [15, 17, 11], [62, 68, 41], [83, 92, 55], [21, 23, 14], [33, 37, 22], [49, 54, 33], [21, 23, 14], nil, nil, nil, [4, 4, 4]],
36
- [nil, nil, nil, [64, 71, 42], [43, 47, 28], [7, 7, 4], nil, [51, 56, 35], [83, 92, 55], [70, 78, 46], [47, 52, 31], [38, 42, 25], [31, 35, 21], [54, 60, 36], [17, 17, 16], [51, 51, 48], [46, 46, 43], [27, 30, 19], [52, 58, 34], [30, 33, 20], [39, 44, 26], [49, 54, 33], [76, 85, 51], [85, 93, 56], [43, 48, 29], [14, 14, 10], [8, 8, 7], [49, 54, 33], [62, 67, 41], nil, nil, nil],
37
- [nil, nil, nil, [34, 38, 24], [37, 39, 24], nil, nil, [34, 37, 22], [75, 83, 50], [35, 39, 24], [1, 1, 1], [43, 48, 29], [66, 72, 43], [20, 21, 12], [3, 1, 1], [2, 2, 2], [2, 2, 2], [3, 3, 3], [27, 30, 18], [66, 72, 43], [35, 38, 23], [2, 1, 1], [42, 46, 28], [76, 85, 51], [5, 5, 4], nil, [2, 3, 2], [36, 40, 24], [22, 25, 15], nil, nil, nil],
38
- [nil, nil, nil, nil, nil, nil, [14, 15, 10], [67, 74, 44], [29, 32, 19], nil, nil, nil, [25, 29, 18], nil, nil, nil, nil, nil, nil, [23, 25, 16], nil, nil, nil, [29, 32, 19], [52, 58, 35], nil, nil, nil, nil, nil, nil, nil],
39
- [nil, nil, nil, nil, nil, nil, nil, [22, 24, 15], nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, [23, 26, 16], nil, nil, nil, nil, nil, nil, nil],
40
- [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil],
41
- ]
42
-
43
- PIXELS.each do |row|
44
- row.each { |color| color.freeze if color }
45
- row.freeze
46
- end
47
- PIXELS.freeze
48
- end
49
- end
50
- end