wings-plugin-sdk 0.6.0 → 0.8.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/README.md +6 -0
- package/package.json +11 -5
- package/poll.d.ts +7 -0
- package/poll.js +28 -0
- package/wings.d.ts +45 -2
package/README.md
CHANGED
|
@@ -55,6 +55,12 @@ to fill. Every `wings.on*` call returns a function that removes the listener, so
|
|
|
55
55
|
`wings-plugin-sdk/react`, or your own `useEffect`, cleans up when a component goes. The API reference is
|
|
56
56
|
[plugins/README.md](https://github.com/josippapez/Wings/blob/main/plugins/README.md) in the Wings repo.
|
|
57
57
|
|
|
58
|
+
## Polling
|
|
59
|
+
|
|
60
|
+
Wings is often in the background, and a timer that runs `git` or a network call then costs battery for nothing.
|
|
61
|
+
`pollWhileFocused(tick, ms)` from `wings-plugin-sdk/poll` runs `tick` every `ms` only while a Wings window is in
|
|
62
|
+
front, and once at once when you come back. It uses `wings.onFocus`.
|
|
63
|
+
|
|
58
64
|
## Pack
|
|
59
65
|
|
|
60
66
|
A plugin in its own repo doesn't need to commit what it builds. `wings-plugin pack` builds it into a temporary
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wings-plugin-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "The wings API types, the page frame, React hooks and the build command for Wings plugins.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,14 +17,15 @@
|
|
|
17
17
|
"types": "./shell.d.ts",
|
|
18
18
|
"default": "./shell.js"
|
|
19
19
|
},
|
|
20
|
+
"./poll": {
|
|
21
|
+
"types": "./poll.d.ts",
|
|
22
|
+
"default": "./poll.js"
|
|
23
|
+
},
|
|
20
24
|
"./build": {
|
|
21
25
|
"types": "./build.d.ts",
|
|
22
26
|
"default": "./build.mjs"
|
|
23
27
|
}
|
|
24
28
|
},
|
|
25
|
-
"scripts": {
|
|
26
|
-
"test": "node --test"
|
|
27
|
-
},
|
|
28
29
|
"bin": {
|
|
29
30
|
"wings-plugin": "bin.mjs"
|
|
30
31
|
},
|
|
@@ -34,6 +35,8 @@
|
|
|
34
35
|
"react.d.ts",
|
|
35
36
|
"shell.js",
|
|
36
37
|
"shell.d.ts",
|
|
38
|
+
"poll.js",
|
|
39
|
+
"poll.d.ts",
|
|
37
40
|
"build.mjs",
|
|
38
41
|
"build.d.ts",
|
|
39
42
|
"bin.mjs",
|
|
@@ -66,5 +69,8 @@
|
|
|
66
69
|
"react": "^19.1.0",
|
|
67
70
|
"react-dom": "^19.1.0",
|
|
68
71
|
"typescript": "~6.0.3"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"test": "node --test"
|
|
69
75
|
}
|
|
70
|
-
}
|
|
76
|
+
}
|
package/poll.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference path="./wings.d.ts" />
|
|
2
|
+
/**
|
|
3
|
+
* Calls `tick` every `ms` while Wings is focused. When Wings loses focus the timer stops; when it regains focus,
|
|
4
|
+
* `tick` runs once at once and the timer starts again. `tick` is not called for the state Wings starts in, so
|
|
5
|
+
* a plugin keeps doing its own first check. Returns a function that stops everything.
|
|
6
|
+
*/
|
|
7
|
+
export function pollWhileFocused(tick: () => void, ms: number, w?: Pick<Wings, "focused" | "onFocus">): () => void;
|
package/poll.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// A timer that runs only while the user is in Wings.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Calls `tick` every `ms` while Wings is focused. When Wings loses focus the timer stops; when it regains focus,
|
|
5
|
+
* `tick` runs once at once and the timer starts again. `tick` is not called for the state Wings starts in, so
|
|
6
|
+
* a plugin keeps doing its own first check. Returns a function that stops everything.
|
|
7
|
+
*/
|
|
8
|
+
export function pollWhileFocused(tick, ms, w = globalThis.wings) {
|
|
9
|
+
let timer;
|
|
10
|
+
let wasFocused = w.focused;
|
|
11
|
+
const start = () => (timer ??= setInterval(tick, ms));
|
|
12
|
+
const stop = () => {
|
|
13
|
+
clearInterval(timer);
|
|
14
|
+
timer = undefined;
|
|
15
|
+
};
|
|
16
|
+
if (wasFocused) start();
|
|
17
|
+
const off = w.onFocus(({ focused }) => {
|
|
18
|
+
if (focused === wasFocused) return;
|
|
19
|
+
wasFocused = focused;
|
|
20
|
+
if (!focused) return stop();
|
|
21
|
+
tick();
|
|
22
|
+
start();
|
|
23
|
+
});
|
|
24
|
+
return () => {
|
|
25
|
+
off();
|
|
26
|
+
stop();
|
|
27
|
+
};
|
|
28
|
+
}
|
package/wings.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ interface WingsPane {
|
|
|
11
11
|
/** What runs in the pane right now, like `zsh` or `claude`. */
|
|
12
12
|
command: string;
|
|
13
13
|
project: string;
|
|
14
|
+
/** The id of that project, the same as `project().id`. Needs Wings 0.1.22. */
|
|
15
|
+
projectId: string;
|
|
14
16
|
/** Set while Claude Code runs in the pane. `startedAt` is when that `claude` started, in ms; a resumed session's transcript also has what came before. */
|
|
15
17
|
session: { sessionId: string; name: string | null; state: string; startedAt: number } | null;
|
|
16
18
|
/** The focused pane of the tab on screen. At most one pane has it, and none while no tab is open. */
|
|
@@ -98,10 +100,26 @@ interface WingsExecOptions {
|
|
|
98
100
|
onOutput?: (line: string) => void;
|
|
99
101
|
}
|
|
100
102
|
|
|
103
|
+
/** A project (space) as pages see it. */
|
|
104
|
+
interface WingsProject {
|
|
105
|
+
id: string;
|
|
106
|
+
name: string;
|
|
107
|
+
path: string;
|
|
108
|
+
branch: string | null;
|
|
109
|
+
}
|
|
110
|
+
|
|
101
111
|
interface Wings {
|
|
102
112
|
// Every `on*` call returns a function that removes the listener, for cleaning up in a React effect.
|
|
103
113
|
/** Every terminal pane, on every change. */
|
|
104
114
|
onPanes(listener: (panes: WingsPane[]) => void): () => void;
|
|
115
|
+
/**
|
|
116
|
+
* Whether the user is in Wings: true while any Wings window (the main one or a view window) is in front, false
|
|
117
|
+
* while another app is. Called once with the current state, then on each change. Needs no permission. Pause timers
|
|
118
|
+
* while it is false and check once when it turns true, or use `pollWhileFocused` from `wings-plugin-sdk/poll`.
|
|
119
|
+
*/
|
|
120
|
+
onFocus(listener: (event: { focused: boolean }) => void): () => void;
|
|
121
|
+
/** The state `onFocus` last reported. True until Wings says otherwise, which it does as soon as the frame is ready. */
|
|
122
|
+
readonly focused: boolean;
|
|
105
123
|
/**
|
|
106
124
|
* A badge action was clicked. Return a promise: the button spins until it settles (up to 5 min), and a thrown
|
|
107
125
|
* error shows in the card. What it resolves to is ignored.
|
|
@@ -154,7 +172,7 @@ interface Wings {
|
|
|
154
172
|
/** Needs `permissions.notify`. A desktop notification, up to 3 a minute. The title is cut at 64 characters, the body at 256. */
|
|
155
173
|
notify(notification: { title: string; body?: string }): Promise<void>;
|
|
156
174
|
/** Needs `"diff"` in `contributes.ui`. Leave out `patch` to open it loading, then call `updateDiff`. */
|
|
157
|
-
openDiff(diff: { title: string; subtitle?: string; patch?: string; comments?: WingsComment[] }): Promise<{ id: string }>;
|
|
175
|
+
openDiff(diff: { title: string; subtitle?: string; /** The repo or folder the diff is of, so Send to agent offers the agent working there first. */ cwd?: string; patch?: string; comments?: WingsComment[] }): Promise<{ id: string }>;
|
|
158
176
|
/** Updates a viewer opened with `openDiff`; ignored once it's closed. `{ comments }` alone keeps the patch, like after a reply. */
|
|
159
177
|
updateDiff(id: string, update: { patch: string; comments?: WingsComment[] } | { comments: WingsComment[] } | { error: string }): Promise<void>;
|
|
160
178
|
/**
|
|
@@ -207,8 +225,33 @@ interface Wings {
|
|
|
207
225
|
* in a window of its own or as a tab in the project on screen (`tab` needs Wings 0.1.15). `as` must be in the
|
|
208
226
|
* view's `opens`, and defaults to the first. A window or tab that's already open comes to the front. The page
|
|
209
227
|
* gets the same `wings` object wherever it opens.
|
|
228
|
+
*
|
|
229
|
+
* `args` (JSON, up to 16 KB, only with `as: "tab"`) is what the tab's page reads with `viewArgs`. A tab that's
|
|
230
|
+
* already open with other args takes the new ones, drops its saved tab state and reloads; a view with `"multiple": true` always opens a
|
|
231
|
+
* new tab. Needs Wings 0.1.22.
|
|
232
|
+
*/
|
|
233
|
+
openView(id: string, options?: { as?: "sidebar" | "modal" | "window" | "tab"; args?: unknown }): Promise<void>;
|
|
234
|
+
/** Where this page shows. `null` in the plugin's main script. Needs Wings 0.1.22. */
|
|
235
|
+
placement(): "sidebar" | "tab" | "modal" | "window" | null;
|
|
236
|
+
/** What `openView` passed as `args` when it opened this tab, or `null`. Available at once. Needs Wings 0.1.22. */
|
|
237
|
+
viewArgs<T = unknown>(): T | null;
|
|
238
|
+
/**
|
|
239
|
+
* The project this page is about, or `null` when none is open. A tab page's project is the one the tab belongs to
|
|
240
|
+
* and never changes; any other page gets the project on screen. Needs Wings 0.1.22.
|
|
241
|
+
*/
|
|
242
|
+
project(): Promise<WingsProject | null>;
|
|
243
|
+
/**
|
|
244
|
+
* Calls the listener with the current project, then each time it changes: the project on screen switched (not for a
|
|
245
|
+
* tab page), or its branch or name changed. Needs Wings 0.1.22.
|
|
246
|
+
*/
|
|
247
|
+
onProject(listener: (project: WingsProject | null) => void): () => void;
|
|
248
|
+
/** In a tab page: the state it last saved with `setTabState`, or `null`. Outside a tab it is `null`. Opening the tab with new `args` clears it. Needs Wings 0.1.22. */
|
|
249
|
+
tabState<T = unknown>(): Promise<T | null>;
|
|
250
|
+
/**
|
|
251
|
+
* In a tab page: saves JSON state, up to 64 KB, on the tab. Wings keeps it across restarts and while the page is
|
|
252
|
+
* unloaded. Rejects outside a tab or when the state is too big. Needs Wings 0.1.22.
|
|
210
253
|
*/
|
|
211
|
-
|
|
254
|
+
setTabState(state: unknown): Promise<void>;
|
|
212
255
|
/** Closes a sidebar or view wherever it's open. */
|
|
213
256
|
closeView(id: string): Promise<void>;
|
|
214
257
|
/** Opens Wings Settings at the plugin's settings page, `contributes.settings`. Wings 0.1.15 and newer. */
|