@akonwi/kit 0.3.4 → 0.5.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.
package/dist/kit CHANGED
Binary file
package/dist/plugin.d.ts CHANGED
@@ -2,11 +2,38 @@ export { Type } from "typebox";
2
2
 
3
3
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
4
4
  import type { Api, Model, Static, TSchema } from "@earendil-works/pi-ai";
5
+ import type {
6
+ SyntaxPalette,
7
+ ThemeConfig,
8
+ ThemeColorTokens as ThemeTokens,
9
+ } from "./themes";
5
10
  import type { ToastInput } from "./toasts";
6
11
 
12
+ export type { SyntaxPalette, ThemeConfig, ThemeTokens };
13
+
7
14
  export type Disposer = () => void;
8
15
 
16
+ export type KitTextStyle = {
17
+ fg?: string;
18
+ bg?: string;
19
+ bold?: boolean;
20
+ dim?: boolean;
21
+ italic?: boolean;
22
+ underline?: boolean;
23
+ strikethrough?: boolean;
24
+ };
25
+
26
+ export type KitText = {
27
+ readonly __kitText: true;
28
+ readonly text: string;
29
+ readonly style?: KitTextStyle;
30
+ };
31
+
32
+ export type KitTextContent = string | KitText | readonly (string | KitText)[];
33
+
9
34
  interface UI {
35
+ text: (text: string, style?: KitTextStyle) => KitText;
36
+ theme: () => ThemeConfig;
10
37
  toast: (toast: ToastInput) => void;
11
38
  select(input: {
12
39
  title: string;
@@ -161,6 +188,26 @@ type ModelAPI = {
161
188
  getCurrent: () => Model<Api> | undefined;
162
189
  };
163
190
 
191
+ export type ChromeContributionSide = "left" | "right";
192
+
193
+ export type ChromeContributionOptions = {
194
+ side?: ChromeContributionSide;
195
+ onClick?: () => void | Promise<void>;
196
+ };
197
+
198
+ type ChromeContributionAPI = {
199
+ set: (
200
+ id: string,
201
+ content: KitTextContent,
202
+ options?: ChromeContributionOptions,
203
+ ) => void;
204
+ clear: (id: string) => void;
205
+ hide: (id: string) => Disposer;
206
+ };
207
+
208
+ type FooterAPI = ChromeContributionAPI;
209
+ type HeaderAPI = ChromeContributionAPI;
210
+
164
211
  type SystemAPI = {
165
212
  readonly cwd: string;
166
213
  open: (url: string | URL) => Promise<void>;
@@ -172,6 +219,8 @@ export type EventContext = {
172
219
  session: SessionAPI;
173
220
  settings: SettingsAPI;
174
221
  model: ModelAPI;
222
+ footer: FooterAPI;
223
+ header: HeaderAPI;
175
224
  system: SystemAPI;
176
225
  };
177
226
 
@@ -201,6 +250,8 @@ export interface PluginAPI {
201
250
  session: SessionAPI;
202
251
  settings: SettingsAPI;
203
252
  model: ModelAPI;
253
+ footer: FooterAPI;
254
+ header: HeaderAPI;
204
255
  system: SystemAPI;
205
256
  on(handler: EventHandler): Disposer;
206
257
  on<Type extends string>(type: Type, handler: EventHandler<Type>): Disposer;
@@ -0,0 +1,137 @@
1
+ import type { RGBA } from "@opentui/core";
2
+
3
+ /** All color tokens consumed by shell components. */
4
+ export type ThemeTokens = {
5
+ // Backgrounds
6
+ bg: string;
7
+ bgSurface: string;
8
+ bgMuted: string;
9
+ bgAccent: string;
10
+ bgTransparent: string;
11
+ modalBackdrop: RGBA;
12
+
13
+ // Borders
14
+ borderDefault: string;
15
+ borderFocused: string;
16
+ borderAccent: string;
17
+ borderDebug: string;
18
+ borderStatus: string;
19
+ composerBashBorder: string;
20
+ composerBashExcludedBorder: string;
21
+
22
+ // Text
23
+ textPrimary: string;
24
+ textSecondary: string;
25
+ textMuted: string;
26
+ textPlaceholder: string;
27
+ textDebug: string;
28
+
29
+ // Semantic (message roles)
30
+ userText: string;
31
+ userTextFocused: string;
32
+ userBorder: string;
33
+ assistantText: string;
34
+ toolText: string;
35
+ reviewText: string;
36
+ errorText: string;
37
+ warningText: string;
38
+ debugLabel: string;
39
+
40
+ // Secondary
41
+ metaText: string;
42
+ attachmentText: string;
43
+
44
+ // Cursor
45
+ cursor: string;
46
+
47
+ // Picker
48
+ pickerBg: string;
49
+ pickerBorder: string;
50
+ pickerFocusedBg: string;
51
+ pickerFocusedText: string;
52
+ pickerItemText: string;
53
+ pickerScrollThumb: string;
54
+ pickerScrollTrack: string;
55
+
56
+ // Scrollbar
57
+ scrollbarFg: string;
58
+ scrollbarBg: string;
59
+
60
+ // Spinner / panel
61
+ panelText: string;
62
+
63
+ // Progress bar
64
+ progressNormal: string;
65
+ progressWarning: string;
66
+ progressCritical: string;
67
+
68
+ // Toggle
69
+ toggleOn: string;
70
+
71
+ // Diff
72
+ diffAddedBg: string;
73
+ diffRemovedBg: string;
74
+ diffAddedContentBg: string;
75
+ diffRemovedContentBg: string;
76
+ diffAddedLineNumberBg: string;
77
+ diffRemovedLineNumberBg: string;
78
+ diffCursorBg: string;
79
+ diffCursorGutterBg: string;
80
+ diffCursorAddedBg: string;
81
+ diffCursorRemovedBg: string;
82
+ };
83
+
84
+ /** Named color slots for syntax highlighting rules. */
85
+ export type SyntaxPalette = {
86
+ text: string;
87
+ heading: string;
88
+ bold: string;
89
+ italic: string;
90
+ link: string;
91
+ list: string;
92
+ quote: string;
93
+ codeInline: string;
94
+ codeBlock: string;
95
+ strikethrough: string;
96
+ conceal: string;
97
+ comment: string;
98
+ string: string;
99
+ escape: string;
100
+ number: string;
101
+ keyword: string;
102
+ keywordType: string;
103
+ function: string;
104
+ operator: string;
105
+ variable: string;
106
+ member: string;
107
+ builtin: string;
108
+ type: string;
109
+ punctuation: string;
110
+ tag: string;
111
+ tagAttribute: string;
112
+ tagDelimiter: string;
113
+ attribute: string;
114
+ label: string;
115
+ };
116
+
117
+ /** Color tokens safe to expose outside the shell. */
118
+ export type ThemeColorTokens = Omit<ThemeTokens, "modalBackdrop">;
119
+
120
+ /** A fully resolved theme with all tokens filled in (except modalBackdrop). */
121
+ export type ResolvedTheme = {
122
+ tokens: ThemeColorTokens;
123
+ syntaxPalette: SyntaxPalette;
124
+ };
125
+
126
+ /** Public resolved theme config exposed to plugins. */
127
+ export type ThemeConfig = ResolvedTheme & { name: string };
128
+
129
+ /**
130
+ * A partial theme definition for overrides.
131
+ * User themes provide partial overrides
132
+ * that get merged on top of the system theme.
133
+ */
134
+ export type ThemeDefinition = {
135
+ tokens?: Partial<ThemeColorTokens>;
136
+ syntaxPalette?: Partial<SyntaxPalette>;
137
+ };
@@ -13,6 +13,8 @@ Discovery is non-recursive. Only direct `.ts` files in those directories are loa
13
13
 
14
14
  Project plugins load after user plugins. Built-in plugins load before both.
15
15
 
16
+ Built-in plugins initialize during core app setup. User and project plugins load in the background after the shell is ready, so slow dependency installation or bundling does not block basic startup. Commands, tools, and chrome contributions from those external plugins become available once loading finishes.
17
+
16
18
  If an external plugin registers a command, tool, or debug section that already exists, Kit treats that as a plugin failure and reports it with a persistent toast.
17
19
 
18
20
  Kit does **not** load plugins from `.agents/plugins/`. Plugins execute code and are Kit-specific functionality, while `.agents/` is reserved for compatibility-oriented resources such as prompts, skills, and MCP config.
@@ -123,7 +125,51 @@ const ok = await kit.ui.confirm({
123
125
  });
124
126
  ```
125
127
 
126
- These helpers use Kit-owned dialogs and return `undefined` when selection/input is cancelled. `confirm` returns `false` for cancel/escape. The public plugin UI API is intentionally limited to `toast`, `select`, `input`, and `confirm` so Kit can keep ownership of rendering, focus, theme, and compatibility.
128
+ These helpers use Kit-owned dialogs and return `undefined` when selection/input is cancelled. `confirm` returns `false` for cancel/escape. The public plugin UI API is intentionally limited to `toast`, `select`, `input`, `confirm`, and the `text`/`theme` helpers so Kit can keep ownership of rendering, focus, theme, and compatibility.
129
+
130
+ ## Header and footer status contributions
131
+
132
+ Plugins can contribute short text items to the header and bottom footer. Kit owns the rendering and layout; plugins provide text or styled text chunks.
133
+
134
+ ```ts
135
+ kit.footer.set("build", "build: passing", { side: "right" });
136
+ kit.footer.set("mode", "watching", { side: "left" });
137
+ kit.header.set("branch", "main", { side: "right" });
138
+
139
+ const theme = kit.ui.theme();
140
+
141
+ kit.footer.set(
142
+ "ci",
143
+ [
144
+ kit.ui.text("✓", { fg: theme.tokens.toolText, bold: true }),
145
+ " tests ",
146
+ kit.ui.text("passing", { fg: theme.tokens.toolText }),
147
+ ],
148
+ {
149
+ side: "right",
150
+ onClick: () => kit.system.open("https://github.com/org/repo/actions"),
151
+ },
152
+ );
153
+
154
+ // Clear an item
155
+ kit.footer.clear("build");
156
+ kit.header.clear("branch");
157
+
158
+ // Hide a known item contributed by another plugin or built-in.
159
+ // The disposer restores it.
160
+ const showDefaultLocation = kit.footer.hide("VcsStatusPlugin:location");
161
+ const showDefaultModel = kit.header.hide("HeaderBar:model");
162
+ showDefaultLocation();
163
+ showDefaultModel();
164
+ ```
165
+
166
+ Header/footer item IDs passed to `set`/`clear` are scoped to the plugin and are cleaned up automatically when the plugin is disposed or reloaded. `hide` accepts the full item ID to support replacing known built-in contributions.
167
+
168
+ Use `kit.ui.text(text, style)` to style part or all of a contribution. Supported style fields are `fg`, `bg`, `bold`, `dim`, `italic`, `underline`, and `strikethrough`. Use `kit.ui.theme()` when setting or updating contributions to read the current resolved theme config (`name`, `tokens`, and `syntaxPalette`) and blend with Kit's colors. `onClick` is a whole-contribution action; Kit maps it to terminal mouse events and does not expose raw mouse events to plugins.
169
+
170
+ Built-in header item IDs are `HeaderBar:title`, `HeaderBar:model`, `HeaderBar:bell`, and `HeaderBar:speech`.
171
+
172
+ Built-in internal plugins may use additional app-owned capabilities that are not part of the public plugin SDK. For example, built-ins can read VCS state while the public SDK only exposes chrome contribution rendering.
127
173
 
128
174
  ## Tool approval hooks
129
175
 
@@ -155,7 +201,7 @@ kit.onToolCall(async (toolCall, ctx) => {
155
201
 
156
202
  ## Reloading
157
203
 
158
- Use `/reload` after editing plugin files. Kit re-discovers plugin files, re-bundles them into Kit's plugin cache, and imports the fresh bundles so changed `.ts` contents are picked up.
204
+ Use `/reload` after editing plugin files. Kit re-discovers plugin files, re-bundles them into Kit's plugin cache, and imports the fresh bundles so changed `.ts` contents are picked up. External plugin loading continues in the background after the session reload completes.
159
205
 
160
206
  Plugin modules are loaded synchronously, so top-level `await` is not supported in plugin files. Async command, event, and tool handlers are supported.
161
207
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akonwi/kit",
3
- "version": "0.3.4",
3
+ "version": "0.5.0",
4
4
  "author": "Akonwi Ngoh <akonwi@gmail.com>",
5
5
  "description": "A TUI coding agent",
6
6
  "license": "MIT",