kward 0.71.0 → 0.72.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 +41 -1
- data/Gemfile.lock +2 -2
- data/README.md +4 -0
- data/doc/agent-tools.md +15 -6
- data/doc/authentication.md +22 -1
- data/doc/code-search.md +42 -2
- data/doc/configuration.md +106 -3
- data/doc/context-budgeting.md +136 -0
- data/doc/context-tools.md +16 -3
- data/doc/editor.md +394 -0
- data/doc/extensibility.md +16 -7
- data/doc/files.md +100 -0
- data/doc/getting-started.md +25 -18
- data/doc/git.md +122 -0
- data/doc/memory.md +24 -4
- data/doc/personas.md +34 -5
- data/doc/plugins.md +72 -1
- data/doc/releasing.md +37 -9
- data/doc/rpc.md +74 -4
- data/doc/session-management.md +35 -1
- data/doc/shell.md +286 -0
- data/doc/tabs.md +122 -0
- data/doc/troubleshooting.md +77 -1
- data/doc/usage.md +53 -7
- data/doc/web-search.md +12 -4
- data/doc/workspace-tools.md +51 -12
- data/examples/plugins/space_invaders.rb +377 -0
- data/lib/kward/agent.rb +1 -1
- data/lib/kward/cli/commands.rb +33 -2
- data/lib/kward/cli/git.rb +150 -0
- data/lib/kward/cli/interactive_turn.rb +73 -9
- data/lib/kward/cli/plugins.rb +54 -4
- data/lib/kward/cli/prompt_interface.rb +32 -1
- data/lib/kward/cli/runtime_helpers.rb +133 -3
- data/lib/kward/cli/sessions.rb +2 -2
- data/lib/kward/cli/settings.rb +218 -9
- data/lib/kward/cli/slash_commands.rb +415 -2
- data/lib/kward/cli/tabs.rb +695 -0
- data/lib/kward/cli.rb +158 -26
- data/lib/kward/config_files.rb +123 -1
- data/lib/kward/context_budget_meter.rb +44 -0
- data/lib/kward/conversation.rb +12 -4
- data/lib/kward/editor_mode.rb +25 -0
- data/lib/kward/ekwsh.rb +362 -0
- data/lib/kward/plugin_registry.rb +61 -0
- data/lib/kward/project_files.rb +52 -0
- data/lib/kward/prompt_history.rb +82 -0
- data/lib/kward/prompt_interface/composer_controller.rb +69 -1
- data/lib/kward/prompt_interface/composer_renderer.rb +109 -13
- data/lib/kward/prompt_interface/composer_state.rb +96 -27
- data/lib/kward/prompt_interface/editor/auto_close_pairs.rb +123 -0
- data/lib/kward/prompt_interface/editor/auto_indent.rb +509 -0
- data/lib/kward/prompt_interface/editor/buffer.rb +109 -0
- data/lib/kward/prompt_interface/editor/controller.rb +1018 -0
- data/lib/kward/prompt_interface/editor/endwise.rb +321 -0
- data/lib/kward/prompt_interface/editor/file_marker.rb +40 -0
- data/lib/kward/prompt_interface/editor/indent_navigation.rb +61 -0
- data/lib/kward/prompt_interface/editor/kill_ring.rb +78 -0
- data/lib/kward/prompt_interface/editor/modes/emacs.rb +259 -0
- data/lib/kward/prompt_interface/editor/modes/modern.rb +353 -0
- data/lib/kward/prompt_interface/editor/modes/vibe.rb +1962 -0
- data/lib/kward/prompt_interface/editor/renderer.rb +243 -0
- data/lib/kward/prompt_interface/editor/search.rb +76 -0
- data/lib/kward/prompt_interface/editor/selections.rb +120 -0
- data/lib/kward/prompt_interface/editor/state.rb +1249 -0
- data/lib/kward/prompt_interface/editor/status_text.rb +23 -0
- data/lib/kward/prompt_interface/editor/syntax_highlighter.rb +420 -0
- data/lib/kward/prompt_interface/editor/undo_history.rb +46 -0
- data/lib/kward/prompt_interface/editor/vibe_state.rb +44 -0
- data/lib/kward/prompt_interface/file_overlay.rb +211 -0
- data/lib/kward/prompt_interface/git_prompt.rb +299 -0
- data/lib/kward/prompt_interface/interactive/controller.rb +186 -0
- data/lib/kward/prompt_interface/interactive/renderer.rb +71 -0
- data/lib/kward/prompt_interface/interactive/state.rb +62 -0
- data/lib/kward/prompt_interface/key_handler.rb +387 -35
- data/lib/kward/prompt_interface/overlay_renderer.rb +21 -2
- data/lib/kward/prompt_interface/project_browser.rb +524 -0
- data/lib/kward/prompt_interface/question_prompt.rb +98 -50
- data/lib/kward/prompt_interface/runtime_state.rb +43 -0
- data/lib/kward/prompt_interface/screen.rb +16 -0
- data/lib/kward/prompt_interface/selection_prompt.rb +7 -13
- data/lib/kward/prompt_interface/stream_state.rb +7 -0
- data/lib/kward/prompt_interface/transcript_buffer.rb +6 -0
- data/lib/kward/prompt_interface.rb +286 -8
- data/lib/kward/prompts/commands.rb +5 -0
- data/lib/kward/prompts.rb +2 -0
- data/lib/kward/rpc/server.rb +42 -3
- data/lib/kward/rpc/session_manager.rb +35 -47
- data/lib/kward/rpc/session_tree_rows.rb +9 -115
- data/lib/kward/rpc/tool_event_normalizer.rb +1 -1
- data/lib/kward/session_store.rb +44 -0
- data/lib/kward/session_tree_nodes.rb +136 -0
- data/lib/kward/session_tree_renderer.rb +9 -131
- data/lib/kward/tab_store.rb +47 -0
- data/lib/kward/text_boundary.rb +25 -0
- data/lib/kward/tools/context_budget_stats.rb +54 -0
- data/lib/kward/tools/context_for_task.rb +202 -0
- data/lib/kward/tools/read_file.rb +8 -4
- data/lib/kward/tools/registry.rb +62 -16
- data/lib/kward/tools/tool_call.rb +10 -0
- data/lib/kward/version.rb +1 -1
- data/lib/kward/workers/git_guard.rb +68 -0
- data/lib/kward/workers/live_view.rb +49 -0
- data/lib/kward/workers/manager.rb +288 -0
- data/lib/kward/workers/store.rb +72 -0
- data/lib/kward/workers/tool_policy.rb +23 -0
- data/lib/kward/workers/worker.rb +82 -0
- data/lib/kward/workers/write_lock.rb +38 -0
- data/lib/kward/workers.rb +7 -0
- data/lib/kward/workspace.rb +110 -24
- data/templates/default/fulldoc/html/css/kward.css +107 -36
- data/templates/default/kward_navigation.rb +12 -1
- data/templates/default/layout/html/layout.erb +4 -2
- data/templates/default/layout/html/setup.rb +6 -0
- metadata +53 -1
data/doc/git.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Git
|
|
2
|
+
|
|
3
|
+
Kward has a small interactive Git workflow built into the terminal UI. It lets you review the current working tree, inspect per-file diffs, stage or unstage files, write a commit message, and create a commit without leaving the chat.
|
|
4
|
+
|
|
5
|
+
Use it when you have just finished a change with Kward and want one last pass before committing. It is intentionally focused: it is not a full Git client, just the common review-and-commit loop.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
From an interactive Kward session inside a Git repository, run:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
/git
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Kward opens a Git overlay showing the same short status style you would see from:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git status --short --untracked-files=normal
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
M lib/kward/cli.rb
|
|
25
|
+
A doc/git.md
|
|
26
|
+
?? tmp/example.txt
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use the overlay to review and shape the commit:
|
|
30
|
+
|
|
31
|
+
| Key | Action |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `↑` / `↓` | Move between changed files. |
|
|
34
|
+
| `Enter` | Open the selected file in the diff viewer. |
|
|
35
|
+
| `s` | Stage or unstage the selected file. |
|
|
36
|
+
| `Tab` | Switch to commit-message entry. |
|
|
37
|
+
| `Esc` | Cancel and return to chat. |
|
|
38
|
+
|
|
39
|
+
When you press `Tab`, the prompt changes from `Git>` to `Commit>`. Type the commit message and press `Enter` to commit. Press `Tab` again to return to the file list without losing the draft message.
|
|
40
|
+
|
|
41
|
+
Use `Shift+Enter` to insert a newline if you need a multi-line commit message.
|
|
42
|
+
|
|
43
|
+
## Review changes with the diff viewer
|
|
44
|
+
|
|
45
|
+
Highlight a file in the `/git` overlay and press `Enter`.
|
|
46
|
+
|
|
47
|
+
Kward opens a read-only diff viewer in the composer area. It shows classic Git diff output with added and removed lines colorized when terminal color is enabled.
|
|
48
|
+
|
|
49
|
+
Useful keys in the diff viewer:
|
|
50
|
+
|
|
51
|
+
| Key | Action |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `↑` / `↓` | Move through the diff one line at a time. |
|
|
54
|
+
| `Page Up` / `Page Down` | Scroll by a page. |
|
|
55
|
+
| `Home` / `End` | Move within the current line. |
|
|
56
|
+
| `/` or `Ctrl+F` | Search within the diff. |
|
|
57
|
+
| `Enter` | Confirm the current search. |
|
|
58
|
+
| `Esc` | Cancel search, or close the diff viewer. |
|
|
59
|
+
| `Ctrl+Q` | Close the diff viewer. |
|
|
60
|
+
|
|
61
|
+
After you close the viewer, Kward returns to the Git overlay with the file list refreshed.
|
|
62
|
+
|
|
63
|
+
The diff viewer is read-only. It is meant for checking what changed, not editing. If you spot something you want to fix, close the viewer, return to chat, and ask Kward to make the change or open the file with the built-in editor using `$path/to/file` (see [Configuration](configuration.md) for editor modes and settings).
|
|
64
|
+
|
|
65
|
+
## Example workflow
|
|
66
|
+
|
|
67
|
+
A typical end-to-end flow looks like this:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
/git
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
1. Use `↑` and `↓` to scan the changed files.
|
|
74
|
+
2. Press `Enter` on a file that looks risky.
|
|
75
|
+
3. Search the diff with `/` if you need to find a symbol or error message.
|
|
76
|
+
4. Press `Esc` to close the diff viewer.
|
|
77
|
+
5. Press `s` on files you want in this commit.
|
|
78
|
+
6. Press `Tab` to write the commit message.
|
|
79
|
+
7. Press `Enter` to commit.
|
|
80
|
+
|
|
81
|
+
If no files are staged when you submit the commit message, Kward stages all current workspace changes before committing. If at least one file is already staged, Kward commits only the staged changes.
|
|
82
|
+
|
|
83
|
+
That means you can use `/git` in two ways:
|
|
84
|
+
|
|
85
|
+
- **Simple commit:** do not stage anything manually; write a message and Kward commits all current changes.
|
|
86
|
+
- **Selective commit:** stage specific files with `s`; Kward commits only what is staged.
|
|
87
|
+
|
|
88
|
+
## How staged changes work
|
|
89
|
+
|
|
90
|
+
The `s` key toggles the selected file:
|
|
91
|
+
|
|
92
|
+
- unstaged files are staged with `git add -- <path>`
|
|
93
|
+
- staged files are unstaged with `git restore --staged -- <path>`
|
|
94
|
+
|
|
95
|
+
The status list refreshes after each toggle, so you can see what will be included before committing.
|
|
96
|
+
|
|
97
|
+
For untracked files, the diff viewer shows the file as a new file with every line added. That makes it possible to review new files before staging them.
|
|
98
|
+
|
|
99
|
+
Renamed or copied files (status codes `R` and `C`) appear in the list with their destination path after the `->` arrow, and the diff viewer shows the destination file.
|
|
100
|
+
|
|
101
|
+
## Git branch indicator
|
|
102
|
+
|
|
103
|
+
In the interactive composer status line, Kward also shows the current Git branch or short commit SHA when the workspace is inside a repository. The indicator turns yellow when the working tree has uncommitted changes.
|
|
104
|
+
|
|
105
|
+
This is just a lightweight status hint. Use `/git` when you want to review or commit the changes.
|
|
106
|
+
|
|
107
|
+
If the working tree is clean when you run `/git`, the overlay shows `No uncommitted changes.` and there is nothing to stage or commit.
|
|
108
|
+
|
|
109
|
+
## Notes and limitations
|
|
110
|
+
|
|
111
|
+
- `/git` is available in the interactive terminal UI, not in one-shot prompts or the RPC backend.
|
|
112
|
+
- The command must run inside a Git repository.
|
|
113
|
+
- The diff viewer compares tracked files against `HEAD` with `git diff HEAD -- <path>`.
|
|
114
|
+
- The commit command uses `git commit -m <message>`.
|
|
115
|
+
- Kward does not push, pull, merge, rebase, amend, or manage branches from this overlay.
|
|
116
|
+
- Commit success still depends on your local Git configuration, hooks, and repository state.
|
|
117
|
+
|
|
118
|
+
For AI-assisted review without committing, you can still pipe a diff into a one-shot prompt:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git diff | kward "Review this diff"
|
|
122
|
+
```
|
data/doc/memory.md
CHANGED
|
@@ -51,7 +51,7 @@ Add a workspace-specific hint when it only applies to the current project:
|
|
|
51
51
|
/memory add "This workspace uses Minitest."
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
Use global core memory sparingly. It has
|
|
54
|
+
Use global core memory sparingly. It applies everywhere, so it has a wider blast radius than workspace memory.
|
|
55
55
|
|
|
56
56
|
## Let Kward summarize useful memories
|
|
57
57
|
|
|
@@ -61,6 +61,12 @@ Auto-summary is off by default. Enable it if you want Kward to learn recurring p
|
|
|
61
61
|
/memory auto-summary enable
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
Disable it again:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
/memory auto-summary disable
|
|
68
|
+
```
|
|
69
|
+
|
|
64
70
|
This only runs when memory is enabled. It does not run for one-shot prompts.
|
|
65
71
|
|
|
66
72
|
You can also ask Kward to summarize the current session manually:
|
|
@@ -69,10 +75,14 @@ You can also ask Kward to summarize the current session manually:
|
|
|
69
75
|
/memory summarize
|
|
70
76
|
```
|
|
71
77
|
|
|
78
|
+
`/memory learn` is an alias for `/memory summarize`.
|
|
79
|
+
|
|
72
80
|
Kward is conservative about inferred memories and refuses to automatically persist emotional, intimate, romantic, or dependency-forming memories.
|
|
73
81
|
|
|
74
82
|
## Inspect what Kward remembers
|
|
75
83
|
|
|
84
|
+
Running `/memory` with no argument prints a summary of all available subcommands.
|
|
85
|
+
|
|
76
86
|
List active memories for the current workspace:
|
|
77
87
|
|
|
78
88
|
```text
|
|
@@ -108,6 +118,12 @@ Promote a workspace hint when it should become a stronger rule:
|
|
|
108
118
|
/memory promote soft_001
|
|
109
119
|
```
|
|
110
120
|
|
|
121
|
+
`/memory promote` also works on workspace core memories, promoting them to global scope so they apply everywhere:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
/memory promote core_003
|
|
125
|
+
```
|
|
126
|
+
|
|
111
127
|
Relax a global memory back to the current workspace:
|
|
112
128
|
|
|
113
129
|
```text
|
|
@@ -124,7 +140,7 @@ Kward uses three layers:
|
|
|
124
140
|
|
|
125
141
|
Core memories override soft memories. Soft memories are treated as hints, not facts.
|
|
126
142
|
|
|
127
|
-
Kward does not inject every stored memory into every prompt. It retrieves a bounded set that appears relevant to the current turn.
|
|
143
|
+
Kward does not inject every stored memory into every prompt. It retrieves a bounded set that appears relevant to the current turn: up to 6 core and 6 soft memories. Core memories are included by scope match (global and current workspace). Soft memories are scored by text and tag overlap with the current input, confidence level, and expiry, and only the top-scoring ones are injected.
|
|
128
144
|
|
|
129
145
|
## Where memory is stored
|
|
130
146
|
|
|
@@ -136,12 +152,16 @@ Default files:
|
|
|
136
152
|
~/.kward/memory/events.jsonl
|
|
137
153
|
```
|
|
138
154
|
|
|
155
|
+
The memory directory is created with mode `0700` and each file with mode `0600`.
|
|
156
|
+
|
|
139
157
|
`events.jsonl` stores a small audit trail for actions such as enable, add, retrieve, summarize, promote, and forget.
|
|
140
158
|
|
|
141
159
|
When a soft memory is forgotten, its text is replaced with `[forgotten]` while inactive audit metadata can remain.
|
|
142
160
|
|
|
143
|
-
|
|
161
|
+
Soft memories have a time-to-live of 60 days by default. Each time a soft memory is retrieved, its `last_seen_at` timestamp is updated and its hit count is incremented. If a soft memory is not retrieved within its TTL window, it expires and is no longer injected into prompts. Forgotten and expired memories remain in the file for audit but are not shown in `/memory list`.
|
|
162
|
+
|
|
163
|
+
If `KWARD_CONFIG_PATH` is set, memory files live beside that config file instead of under `~/.kward`. See [Configuration](configuration.md) for the config-file representation.
|
|
144
164
|
|
|
145
165
|
## RPC support
|
|
146
166
|
|
|
147
|
-
The experimental RPC backend exposes memory methods
|
|
167
|
+
The experimental RPC backend exposes memory methods including `memory/status`, `memory/enable`, `memory/disable`, `memory/autoSummary/enable`, `memory/autoSummary/disable`, `memory/list`, `memory/add`, `memory/addCore`, `memory/forget`, `memory/promote`, `memory/relax`, `memory/inspect`, `memory/why`, and `memory/summarize`. See the [RPC documentation](rpc.md) for the full protocol.
|
data/doc/personas.md
CHANGED
|
@@ -108,7 +108,7 @@ Assistant> I found the failing test.
|
|
|
108
108
|
Samantha> I found the failing test.
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
This is not only decorative. It is the name Kward uses when rendering assistant messages in the terminal transcript. If
|
|
111
|
+
This is not only decorative. It is the name Kward uses when rendering assistant messages in the terminal transcript. If the active persona has no `label` field, Kward uses `Assistant>` instead — the character `key` is not used as a fallback label. If no persona is active at all, Kward also uses `Assistant>`.
|
|
112
112
|
|
|
113
113
|
For RPC clients, the active label is also exposed as `activePersonaLabel` so a UI can show the same speaker identity.
|
|
114
114
|
|
|
@@ -163,6 +163,19 @@ You can also define characters as a map:
|
|
|
163
163
|
}
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
+
In the map form, the key is the character key. You can also use a bare string as the definition, which becomes the instruction; the transcript label then falls back to `Assistant>` unless you use a hash with `label`:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"personas": {
|
|
171
|
+
"characters": {
|
|
172
|
+
"duck": "You are a patient rubber duck."
|
|
173
|
+
},
|
|
174
|
+
"default": "duck"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
166
179
|
The array form is easier to read and is recommended for new configs.
|
|
167
180
|
|
|
168
181
|
`personas.crew` is accepted as a legacy alias for `personas.characters`.
|
|
@@ -179,13 +192,25 @@ Set `personas.default` to the character key you want by default:
|
|
|
179
192
|
}
|
|
180
193
|
```
|
|
181
194
|
|
|
195
|
+
`personas.default` can also be a raw instruction string instead of a character key. When the value does not match any character, Kward uses it directly as the persona instruction:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"personas": {
|
|
200
|
+
"default": "You are a calm assistant."
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
This is a quick way to set a persona without defining a `characters` entry.
|
|
206
|
+
|
|
182
207
|
You can also change the default from interactive Kward:
|
|
183
208
|
|
|
184
209
|
```text
|
|
185
210
|
/settings
|
|
186
211
|
```
|
|
187
212
|
|
|
188
|
-
|
|
213
|
+
Choose **Personalization**, then **Default persona** to pick from your configured characters. The same menu also offers **Active instructions summary**, which shows the active persona label and whether `PRINCIPLES.md` and workspace `AGENTS.md` are present.
|
|
189
214
|
|
|
190
215
|
## Workspace-specific personas
|
|
191
216
|
|
|
@@ -268,7 +293,7 @@ anthropic_reasoning_effort
|
|
|
268
293
|
copilot_reasoning_effort
|
|
269
294
|
```
|
|
270
295
|
|
|
271
|
-
Personas do not choose the model and do not set reasoning effort by themselves. What personas can do is add extra character direction based on the active reasoning effort.
|
|
296
|
+
Personas do not choose the model and do not set reasoning effort by themselves. What personas can do is add extra character direction based on the active reasoning effort. See [Configuration](configuration.md) for the full provider, model, and reasoning config reference.
|
|
272
297
|
|
|
273
298
|
In plain English:
|
|
274
299
|
|
|
@@ -324,7 +349,7 @@ Example:
|
|
|
324
349
|
}
|
|
325
350
|
```
|
|
326
351
|
|
|
327
|
-
If no bucket matches, no time-of-day modifier is added.
|
|
352
|
+
If no bucket matches, no time-of-day modifier is added. Hours 12:00-20:59 (noon through early evening) have no bucket, so no time-of-day modifier is applied during that window.
|
|
328
353
|
|
|
329
354
|
## Weekday modifiers
|
|
330
355
|
|
|
@@ -404,7 +429,11 @@ From the shell:
|
|
|
404
429
|
kward sysprompt
|
|
405
430
|
```
|
|
406
431
|
|
|
407
|
-
`kward sysprompt` shows the assembled prompt sections, including the persona text that would be used for a new conversation.
|
|
432
|
+
`kward sysprompt` shows the assembled prompt sections, including the persona text that would be used for a new conversation. Add `--raw` to print the raw system prompt content without section formatting, which is useful for scripting or piping to another tool:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
kward sysprompt --raw
|
|
436
|
+
```
|
|
408
437
|
|
|
409
438
|
## When to use personas
|
|
410
439
|
|
data/doc/plugins.md
CHANGED
|
@@ -21,6 +21,8 @@ Plugins run inside the Kward process with your user permissions. Install only pl
|
|
|
21
21
|
| Repository rules | `AGENTS.md` |
|
|
22
22
|
| Local Ruby code or integration | plugin |
|
|
23
23
|
|
|
24
|
+
See [Extensibility](extensibility.md) for the full overview of Kward's extension points and prompt assembly order.
|
|
25
|
+
|
|
24
26
|
## Where plugins live
|
|
25
27
|
|
|
26
28
|
Kward loads top-level Ruby files from:
|
|
@@ -56,6 +58,8 @@ Start Kward and run:
|
|
|
56
58
|
/hello World
|
|
57
59
|
```
|
|
58
60
|
|
|
61
|
+
When developing plugins, use `/reload` inside Kward to reload all plugin files without restarting. This picks up changes to existing plugins and registers new ones, then rebuilds the system message.
|
|
62
|
+
|
|
59
63
|
## Add a slash command
|
|
60
64
|
|
|
61
65
|
Use plugin commands for local actions that should not call the model.
|
|
@@ -77,7 +81,7 @@ A plugin command cannot replace a built-in command or prompt-template command.
|
|
|
77
81
|
|
|
78
82
|
Prompt context is short text injected into future model requests.
|
|
79
83
|
|
|
80
|
-
Use it for stable facts the model should know, not for large files or secrets.
|
|
84
|
+
Use it for stable facts the model should know, not for large files or secrets. The block should return a string (injected into the system prompt) or `nil` (skipped). The example below uses Ruby's `next` to return `nil` early when the condition does not match.
|
|
81
85
|
|
|
82
86
|
```ruby
|
|
83
87
|
Kward.plugin do |plugin|
|
|
@@ -109,6 +113,71 @@ end
|
|
|
109
113
|
|
|
110
114
|
Only one footer is active. If multiple plugins register footers, the later one replaces the earlier one and Kward prints a warning.
|
|
111
115
|
|
|
116
|
+
## Add an interactive command
|
|
117
|
+
|
|
118
|
+
Interactive commands take over the composer region with a Kward-driven render and
|
|
119
|
+
input loop. The plugin receives a controller object with a canvas API for
|
|
120
|
+
drawing colored cells and reading keys. This is useful for games, dashboards,
|
|
121
|
+
viewers, and similar full-region interactive experiences.
|
|
122
|
+
|
|
123
|
+
`interactive_command` accepts `description:` and `argument_hint:` keyword arguments, which appear in the slash command list and completion overlay just like regular plugin commands. `rows:` sets the fixed canvas height (minimum 1), and `fps:` sets the target frame rate (1–120, default 30).
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
Kward.plugin do |plugin|
|
|
127
|
+
plugin.interactive_command "demo", rows: 10, fps: 30, description: "Canvas demo" do |ui, ctx|
|
|
128
|
+
x = 0
|
|
129
|
+
ui.on_tick do |ui|
|
|
130
|
+
ui.clear_frame
|
|
131
|
+
ui.put(0, x, "X", :red)
|
|
132
|
+
x = (x + 1) % ui.width
|
|
133
|
+
key = ui.poll_key
|
|
134
|
+
return :exit if key == :ctrl_c || key == "q"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Run it with `/demo` from the interactive TUI. The canvas renders inside the
|
|
141
|
+
composer area for the specified number of rows. The transcript above stays
|
|
142
|
+
intact.
|
|
143
|
+
|
|
144
|
+
### Controller API
|
|
145
|
+
|
|
146
|
+
The `ui` controller object passed to the handler block exposes:
|
|
147
|
+
|
|
148
|
+
| Method | Description |
|
|
149
|
+
| --- | --- |
|
|
150
|
+
| `put(row, col, char, *colors)` | Place a character at a zero-based position with optional ANSI color styles |
|
|
151
|
+
| `clear_frame` | Reset all canvas cells to blank |
|
|
152
|
+
| `render` | Mark the canvas as ready for Kward to draw |
|
|
153
|
+
| `poll_key` | Return the next pending key (non-blocking, nil if none) |
|
|
154
|
+
| `exit` | Request that the interactive loop exit |
|
|
155
|
+
| `on_tick { \|ui\| }` | Register a tick callback invoked each frame at the configured fps |
|
|
156
|
+
| `width` | Canvas width in terminal columns |
|
|
157
|
+
| `height` | Canvas height in terminal rows |
|
|
158
|
+
| `fps` | Target frame rate |
|
|
159
|
+
|
|
160
|
+
Keys are returned as symbols (`:left`, `:right`, `:up`, `:down`, `:return`,
|
|
161
|
+
`:backspace`, `:space`, `:pageup`, `:pagedown`) or raw strings for keys
|
|
162
|
+
without a named mapping. Ctrl+C always exits the loop immediately.
|
|
163
|
+
|
|
164
|
+
The tick callback runs at the configured frame rate (1–120 fps, default 30).
|
|
165
|
+
Returning `:exit` from the tick callback ends the loop, same as calling
|
|
166
|
+
`ui.exit`.
|
|
167
|
+
|
|
168
|
+
### Lifecycle
|
|
169
|
+
|
|
170
|
+
- The composer state is saved on entry and fully restored on exit (input text,
|
|
171
|
+
cursor, and transcript viewport).
|
|
172
|
+
- Interactive mode is a distinct state from the busy-input spinner lifecycle —
|
|
173
|
+
no spinner or busy chrome is shown.
|
|
174
|
+
- Ctrl+C, the plugin calling `exit`, or the tick callback returning `:exit`
|
|
175
|
+
all exit cleanly and restore the prior composer state.
|
|
176
|
+
- Resize during interactive mode forces a clean exit and restore.
|
|
177
|
+
|
|
178
|
+
Interactive commands require the TUI prompt interface. They are not available
|
|
179
|
+
in piped/non-interactive mode or through RPC.
|
|
180
|
+
|
|
112
181
|
## Observe transcript events
|
|
113
182
|
|
|
114
183
|
Use transcript events when you need to log or react to live activity:
|
|
@@ -151,6 +220,8 @@ Handlers receive a `ctx` object. Common methods:
|
|
|
151
220
|
- `ctx.session_path`
|
|
152
221
|
- `ctx.refresh_system_message!`
|
|
153
222
|
|
|
223
|
+
These methods are available in all handler types: commands, footers, prompt context renderers, and transcript event observers. `ctx.say` outputs to the active frontend (terminal or RPC) wherever it is called.
|
|
224
|
+
|
|
154
225
|
The transcript is read-only. Use context methods instead of mutating Kward internals.
|
|
155
226
|
|
|
156
227
|
## RPC support
|
data/doc/releasing.md
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
# Releasing Kward
|
|
2
2
|
|
|
3
|
+
Kward requires Ruby >= 3.2 (`spec.required_ruby_version` in `kward.gemspec`). If you develop with a newer Ruby, verify tests pass against the minimum supported version before releasing.
|
|
4
|
+
|
|
3
5
|
Release steps before publishing:
|
|
4
6
|
|
|
5
|
-
1. Update `CHANGELOG.md` for the version.
|
|
7
|
+
1. Update `CHANGELOG.md` for the version. Move `[Unreleased]` entries under a new version heading.
|
|
6
8
|
2. Update `Kward::VERSION` in `lib/kward/version.rb`.
|
|
7
|
-
3. Run the test suite:
|
|
9
|
+
3. Run the full test suite:
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
12
|
bundle exec rake test
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
4.
|
|
15
|
+
4. Run focused tests for any areas you changed during the release prep itself (docs, config, etc.):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
ruby -Itest test/test_cli.rb
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
5. Preview docs locally if you changed documentation or public APIs:
|
|
14
22
|
|
|
15
23
|
```bash
|
|
16
24
|
bundle exec rake docs:serve
|
|
@@ -18,24 +26,36 @@ Release steps before publishing:
|
|
|
18
26
|
|
|
19
27
|
The preview builds `_yardoc/`, serves it with WEBrick, and rebuilds in a fresh process when documentation sources, library code, or templates change. Refresh your browser after rebuilds.
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
6. Generate and check documentation:
|
|
22
30
|
|
|
23
31
|
```bash
|
|
24
|
-
bundle exec rake rdoc
|
|
25
32
|
bundle exec rake docs:build
|
|
26
33
|
bundle exec rake docs:check
|
|
27
34
|
```
|
|
28
35
|
|
|
29
|
-
`docs:check` validates generated internal links, images, and scripts. Pushes to `main` deploy the generated YARD site to GitHub Pages.
|
|
36
|
+
`docs:check` validates generated internal links, images, and scripts. Pushes to `main` deploy the generated YARD site to GitHub Pages. You can also run `bundle exec rake rdoc` to generate a separate RDoc site as a sanity check, but it is not deployed.
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
7. Build the gem locally:
|
|
32
39
|
|
|
33
40
|
```bash
|
|
34
41
|
gem build kward.gemspec
|
|
35
42
|
```
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
8. Inspect the packaged files and confirm no local config, sessions, logs, or secrets are included. The gemspec uses `git ls-files` and excludes `test/`, `plan/`, `.ruby-lsp/`, `.gitignore`, and `AGENTS.md`. To verify what is packaged:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
tar tf kward-VERSION.gem
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
9. Install the built gem locally and smoke test the `kward` executable in a clean workspace.
|
|
51
|
+
|
|
52
|
+
Commit the version bump and create a git tag:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git commit -am "Bump to VERSION"
|
|
56
|
+
git tag vVERSION
|
|
57
|
+
git push && git push --tags
|
|
58
|
+
```
|
|
39
59
|
|
|
40
60
|
Publish the built gem from the release checkout:
|
|
41
61
|
|
|
@@ -44,3 +64,11 @@ gem push kward-VERSION.gem
|
|
|
44
64
|
```
|
|
45
65
|
|
|
46
66
|
RubyGems MFA is required for publishing. Prefer RubyGems trusted publishing for automated releases if CI publishing is added later, so long-lived API keys do not need to be stored in CI secrets.
|
|
67
|
+
|
|
68
|
+
If a published gem has a serious problem, you can yank it within 24 hours of pushing:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
gem yank kward --version VERSION
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Yanking removes the gem from the default install index but does not delete the version entirely. After yanking, fix the issue, bump the version, and release again.
|
data/doc/rpc.md
CHANGED
|
@@ -6,6 +6,8 @@ Kward RPC is an experimental backend protocol for UI clients. It is versioned as
|
|
|
6
6
|
|
|
7
7
|
This page is for people building UI clients or integrations. If you use Kward from the terminal, you can skip it.
|
|
8
8
|
|
|
9
|
+
Prompt history search is a CLI terminal feature only. RPC clients own their composer/input UX and Kward does not currently expose prompt-history read, append, or search methods over RPC.
|
|
10
|
+
|
|
9
11
|
## Launch
|
|
10
12
|
|
|
11
13
|
```bash
|
|
@@ -48,14 +50,14 @@ Result fields:
|
|
|
48
50
|
Detailed capability fields include:
|
|
49
51
|
|
|
50
52
|
- `transcript`: Tauren transcript format support, including normalized messages, image/tool support, compaction summaries, and restored assistant reasoning as Pi-compatible `thinking` content blocks.
|
|
51
|
-
- `sessions`: explicit RPC session mode, JSONL persistence, supported session methods, startup auto-resume capability/default, immediate transcript support for auto-resume, RPC list support, supported linear-session fork methods, supported compaction, and explicit unsupported import/
|
|
53
|
+
- `sessions`: explicit RPC session mode, JSONL persistence, supported session methods, startup auto-resume capability/default, immediate transcript support for auto-resume, RPC list support, supported linear-session fork methods, supported compaction, supported tree navigation with labels and branch summarization, and explicit unsupported import/update features.
|
|
52
54
|
- `turns`: async turn mode, per-session concurrency, provider-gated native busy-input steering, queued follow-up input, best-effort cancellation, and recent in-memory event replay behavior.
|
|
53
|
-
- `events`: `turn/event` notification details, assistant/reasoning event names, normalized tool metadata, diff result support, configured workspace guardrail status, and explicit unsupported shell changed-file detection/session update flags.
|
|
55
|
+
- `events`: `turn/event` notification details, assistant/reasoning event names, normalized tool metadata, diff result support, configured workspace guardrail status, focused context and context-budget stats tool support, and explicit unsupported shell changed-file detection/session update flags.
|
|
54
56
|
- `attachments`: supported input attachment contract for `turns/start`, with accepted base64 image MIME types and a stable max byte value.
|
|
55
57
|
- `models`: model/reasoning RPC methods, explicit OpenRouter catalog listing, exposed model fields, and no scoped model support.
|
|
56
58
|
- `runtime`: supported state/stats methods with message-count stats and OpenAI/Codex context usage. Cumulative token and cost stats are not computed.
|
|
57
59
|
- `runtimeSettings`: live `runtime/updateSetting` support for `defaultModel` and `defaultThinkingLevel`, plus `runtime/reload`.
|
|
58
|
-
- `auth`: Tauren auth provider format, OpenAI and Anthropic OAuth, OpenRouter API-key login, and provider logout for stored credentials.
|
|
60
|
+
- `auth`: Tauren auth provider format, OpenAI and Anthropic OAuth, OpenRouter API-key login, GitHub/Copilot status reporting, and provider logout for stored credentials. GitHub OAuth login is CLI-only; RPC reports `supported: false` for the GitHub provider with a reason string.
|
|
59
61
|
- `memory`: opt-in structured memory support, interactive prompt injection only, JSON/JSONL local storage, and dedicated `memory/*` methods.
|
|
60
62
|
- `commands`: supported `commands/list` capability for prompt, skill, and plugin command sources, plus plugin execution through `commands/run` or plugin slash turns.
|
|
61
63
|
- `startupResources`: supported startup resource listing for context, skills, prompts, and plugins.
|
|
@@ -63,6 +65,10 @@ Detailed capability fields include:
|
|
|
63
65
|
- `composer`: composer-only UI features. Interactive session diff totals are explicitly unsupported over RPC (`composer.sessionDiff.supported: false`) because RPC clients already receive per-tool diff results and no live composer status payload is exposed. Clipboard copy is also unsupported over RPC (`composer.copy.supported: false`) because UI clients own clipboard access.
|
|
64
66
|
- `security`: trusted-local behavior; no workspace mutation guard or tool approval, shell/file mutation can run. File-tool workspace guardrails are reported under `capabilities.events.tools.workspaceGuardrails` and `runtime/state.workspaceGuardrailsEnabled`.
|
|
65
67
|
- `export`: supported transcript export formats. Currently `markdown` and `html`; default is `markdown`.
|
|
68
|
+
- `workers`: experimental agent worker pipeline. Reports `supported: false` by default; set to `supported: true` with `methods: ["workers/list", "workers/show"]` when Kward is launched with `--experimental-workers`.
|
|
69
|
+
- `starterPack`: explicitly unsupported (`supported: false`, reason `cliOnlyInstallCommand`). Use `kward init` from the shell.
|
|
70
|
+
- `shell`: explicitly unsupported (`supported: false`, reason `interactiveTuiOnly`) because `/shell` is the local embedded TUI shell.
|
|
71
|
+
- `logging`: local redacted telemetry logging support, the log directory, enabled categories, `methods: ["logging/stats", "logging/tokenCsv"]`, `usageCsv` sub-capability with bucket support, JSONL format, rotation (10 MB, manual retention), config key `logging`, env prefix `KWARD_LOGGING`, and redacted-metadata-only content.
|
|
66
72
|
|
|
67
73
|
### `shutdown`
|
|
68
74
|
|
|
@@ -217,6 +223,37 @@ Closes the RPC session. Empty unnamed session files may be cleaned up.
|
|
|
217
223
|
|
|
218
224
|
Returns session metadata and full conversation messages. Assistant `reasoning_summary` values and existing `thinking`/`reasoning` content parts are restored as normalized `{ "type": "thinking", "thinking": "..." }` blocks before assistant text; reasoning is not merged into normal text blocks.
|
|
219
225
|
|
|
226
|
+
### `sessions/tree`
|
|
227
|
+
|
|
228
|
+
Params:
|
|
229
|
+
|
|
230
|
+
- `sessionId`
|
|
231
|
+
|
|
232
|
+
Returns the full branching session tree as flattened Tauren-compatible rows (`tauren-tree-items-v1`). Each row includes `entryId`, `parentId`, `role`, `text` (compact display text), `current` (whether it is the active leaf), `depth`, `isLast`, `ancestorContinues`, `activePath`, `selectable`, `label`, `labelTimestamp`, and `prefix` (tree-drawing connector string). User-message entries are selectable; assistant/tool entries are not.
|
|
233
|
+
|
|
234
|
+
### `sessions/tree/setLabel`
|
|
235
|
+
|
|
236
|
+
Params:
|
|
237
|
+
|
|
238
|
+
- `sessionId`
|
|
239
|
+
- `entryId`
|
|
240
|
+
- `label`: optional display label override for the entry.
|
|
241
|
+
|
|
242
|
+
Persists a label override for one tree entry and returns `{ "ok": true }`.
|
|
243
|
+
|
|
244
|
+
### `sessions/tree/navigate`
|
|
245
|
+
|
|
246
|
+
Params:
|
|
247
|
+
|
|
248
|
+
- `sessionId`
|
|
249
|
+
- `entryId`: a selectable entry ID from `sessions/tree`.
|
|
250
|
+
- `summarize`: optional boolean; when true, Kward summarizes the abandoned branch before moving.
|
|
251
|
+
- `customInstructions`: optional additional guidance for the summarizer.
|
|
252
|
+
|
|
253
|
+
Moves the active branch to the selected tree entry. If the entry is a user message, its parent becomes the new active leaf and the user message text is returned as `editorText` so clients can place it into the composer for editing/resubmission. When `summarize` is true, a branch summary is generated and appended to the session before moving.
|
|
254
|
+
|
|
255
|
+
Returns `{ "session": {}, "editorText": "...", "cancelled": false, "aborted": false }`. Fields with no value are omitted.
|
|
256
|
+
|
|
220
257
|
## Turn methods
|
|
221
258
|
|
|
222
259
|
Turns are asynchronous. A session queues turns sequentially; only one turn runs per session at a time.
|
|
@@ -276,6 +313,7 @@ Known event types:
|
|
|
276
313
|
|
|
277
314
|
- `turnQueued`
|
|
278
315
|
- `turnSteered`
|
|
316
|
+
- `steeringApplied`
|
|
279
317
|
- `turnStarted`
|
|
280
318
|
- `reasoningDelta`
|
|
281
319
|
- `assistantDelta`
|
|
@@ -292,6 +330,8 @@ Lifecycle payloads include `status` for `turnQueued`, `turnStarted`, and `turnFi
|
|
|
292
330
|
|
|
293
331
|
`modelRetry` is emitted before Kward retries a transient model request failure. Its payload includes `provider`, `model`, `attempt`, `maxAttempts`, `delaySeconds`, and `error`.
|
|
294
332
|
|
|
333
|
+
`steeringApplied` is emitted after queued steering input has been appended to conversation context. Its payload includes `count`, the number of steering messages applied.
|
|
334
|
+
|
|
295
335
|
`toolCall` and `toolResult` payloads include canonical Tauren-normalized fields:
|
|
296
336
|
|
|
297
337
|
- `toolCallId`: tool call ID.
|
|
@@ -379,7 +419,7 @@ Refreshes config-backed runtime state and returns `{ "ok": true, "message": "Res
|
|
|
379
419
|
|
|
380
420
|
## Logging methods
|
|
381
421
|
|
|
382
|
-
The `logging` capability reports local redacted telemetry logging support, the log directory, enabled categories,
|
|
422
|
+
The `logging` capability reports local redacted telemetry logging support, the log directory, enabled categories, `methods: ["logging/stats", "logging/tokenCsv"]`, `usageCsv` sub-capability with bucket support, JSONL format with 10 MB rotation and manual retention, config key `logging`, env prefix `KWARD_LOGGING`, and redacted-metadata-only content. Logging methods require logging to be enabled by config or environment for at least one category.
|
|
383
423
|
|
|
384
424
|
### `logging/stats`
|
|
385
425
|
|
|
@@ -391,6 +431,15 @@ Accepted units are minutes, hours, days, weeks, months, and years. Ranges use UT
|
|
|
391
431
|
|
|
392
432
|
Returns structured stats for enabled categories only, including the requested range, log directory, record counts by category/event, `usageStats` token totals, performance duration summaries, tool call summaries, and error counts by event/class/provider/code. Error messages are not included in the stats response.
|
|
393
433
|
|
|
434
|
+
### `logging/tokenCsv`
|
|
435
|
+
|
|
436
|
+
Params:
|
|
437
|
+
|
|
438
|
+
- `range`: optional duration string; defaults to `1 week`.
|
|
439
|
+
- `bucket`: optional aggregation bucket: `second`, `minute`, `hour`, `day`, `week`, `month`, or `year`.
|
|
440
|
+
|
|
441
|
+
Returns `{ "csv": "..." }` with token usage data as CSV. Accepted range units and calendar-period behavior match `logging/stats`. This is the RPC equivalent of `kward stats tokens`.
|
|
442
|
+
|
|
394
443
|
## Memory methods
|
|
395
444
|
|
|
396
445
|
Memory is disabled by default. Auto-summary is also disabled by default. RPC memory methods operate on the same local storage as the CLI: `<config-dir>/memory/core.json`, `<config-dir>/memory/soft.jsonl`, and `<config-dir>/memory/events.jsonl`. Retrieved memory is injected only for normal session turns when memory is enabled.
|
|
@@ -639,6 +688,27 @@ Completes the login using the submitted code.
|
|
|
639
688
|
|
|
640
689
|
Returns login status for a login ID.
|
|
641
690
|
|
|
691
|
+
## Worker methods (experimental)
|
|
692
|
+
|
|
693
|
+
Worker methods are available only when Kward is launched with `--experimental-workers`. The `workers` capability reports `supported: false` by default and `supported: true` with `methods: ["workers/list", "workers/show"]` when the flag is active.
|
|
694
|
+
|
|
695
|
+
### `workers/list`
|
|
696
|
+
|
|
697
|
+
Params:
|
|
698
|
+
|
|
699
|
+
- `sessionId`: active RPC session ID.
|
|
700
|
+
|
|
701
|
+
Returns the list of agent workers for the session.
|
|
702
|
+
|
|
703
|
+
### `workers/show`
|
|
704
|
+
|
|
705
|
+
Params:
|
|
706
|
+
|
|
707
|
+
- `sessionId`: active RPC session ID.
|
|
708
|
+
- `workerId`: worker ID.
|
|
709
|
+
|
|
710
|
+
Returns details for a specific worker.
|
|
711
|
+
|
|
642
712
|
## Security and privacy notes
|
|
643
713
|
|
|
644
714
|
- RPC is intended for a trusted local UI and can read/write files, run shell commands, update secrets, and use OAuth.
|