pterm 0.0.15 → 0.0.17
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 +138 -2
- package/index.js +6 -0
- package/package.json +1 -1
- package/rpc.js +6 -1
- package/script.js +10 -1
- package/util.js +79 -1
package/README.md
CHANGED
|
@@ -108,9 +108,11 @@ Run a launcher. Equivalent to the user visiting a launcher page. Will run whiche
|
|
|
108
108
|
### syntax
|
|
109
109
|
|
|
110
110
|
```
|
|
111
|
-
pterm run <
|
|
111
|
+
pterm run <launcher_path_or_uri> [--open]
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
- `--open`: (optional) open URL results in the browser. Default behavior is to print the URL to stdout without opening a browser.
|
|
115
|
+
|
|
114
116
|
### examples
|
|
115
117
|
|
|
116
118
|
Launch the launcher in the current path
|
|
@@ -125,6 +127,141 @@ Launch from absolute path
|
|
|
125
127
|
pterm run /pinokio/api/test
|
|
126
128
|
```
|
|
127
129
|
|
|
130
|
+
Run from a launcher URI and auto-open the resulting URL in browser
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
pterm run https://github.com/example/my-launcher --open
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## search
|
|
137
|
+
|
|
138
|
+
Search installed or available apps.
|
|
139
|
+
|
|
140
|
+
### syntax
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
pterm search [query words...]
|
|
144
|
+
pterm search --q="<query>"
|
|
145
|
+
pterm search "<query>" [--mode=balanced|broad|strict] [--min-match=<n>] [--limit=<n>]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- `--mode`: (optional) search strategy. `broad` (default), `balanced`, or `strict`.
|
|
149
|
+
- `--min-match`: (optional) minimum number of query terms an app should match.
|
|
150
|
+
- `--limit`: (optional) max number of app results to return.
|
|
151
|
+
|
|
152
|
+
### examples
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
pterm search comfyui
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
pterm search --q="text generation"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
pterm search "tts speech synthesis" --mode=balanced --min-match=2 --limit=8
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## status
|
|
167
|
+
|
|
168
|
+
Get app status by app id.
|
|
169
|
+
|
|
170
|
+
### syntax
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
pterm status <app_id> [--probe] [--timeout=<ms>]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- `--probe`: (optional) actively probe app health.
|
|
177
|
+
- `--timeout`: (optional) probe timeout in milliseconds.
|
|
178
|
+
|
|
179
|
+
### examples
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
pterm status comfyanonymous-comfyui
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
pterm status comfyanonymous-comfyui --probe --timeout=5000
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## stars
|
|
190
|
+
|
|
191
|
+
List starred apps.
|
|
192
|
+
|
|
193
|
+
### syntax
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
pterm stars [query words...]
|
|
197
|
+
pterm stars --q="<query>"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### examples
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
pterm stars
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
pterm stars tts
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## star
|
|
211
|
+
|
|
212
|
+
Star an app so it is preferred on Pinokio home/search ranking.
|
|
213
|
+
|
|
214
|
+
### syntax
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
pterm star <app_id>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### example
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
pterm star comfyanonymous-comfyui
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## unstar
|
|
227
|
+
|
|
228
|
+
Remove star from an app.
|
|
229
|
+
|
|
230
|
+
### syntax
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
pterm unstar <app_id>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### example
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
pterm unstar comfyanonymous-comfyui
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## logs
|
|
243
|
+
|
|
244
|
+
Get app logs by app id.
|
|
245
|
+
|
|
246
|
+
### syntax
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
pterm logs <app_id> [--script=<name>] [--tail=<lines>]
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
- `--script`: (optional) filter to a script.
|
|
253
|
+
- `--tail`: (optional) return only the last N lines.
|
|
254
|
+
|
|
255
|
+
### examples
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
pterm logs comfyanonymous-comfyui
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
pterm logs comfyanonymous-comfyui --script=start --tail=200
|
|
263
|
+
```
|
|
264
|
+
|
|
128
265
|
## filepicker
|
|
129
266
|
|
|
130
267
|
Display a file picker dialog, which lets the user select one or more file or folder paths, powered by tkinter.
|
|
@@ -268,4 +405,3 @@ pterm push 'this is a notification' --sound
|
|
|
268
405
|
```
|
|
269
406
|
pterm push 'this is an image notification' --image=icon.png
|
|
270
407
|
```
|
|
271
|
-
|
package/index.js
CHANGED
|
@@ -56,6 +56,12 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
56
56
|
await util.download(argv)
|
|
57
57
|
} else if (cmd === "search") {
|
|
58
58
|
await util.search(argv)
|
|
59
|
+
} else if (cmd === "stars") {
|
|
60
|
+
await util.stars(argv)
|
|
61
|
+
} else if (cmd === "star") {
|
|
62
|
+
await util.setStar(argv, true)
|
|
63
|
+
} else if (cmd === "unstar") {
|
|
64
|
+
await util.setStar(argv, false)
|
|
59
65
|
} else if (cmd === "status") {
|
|
60
66
|
await util.status(argv)
|
|
61
67
|
} else if (cmd === "logs") {
|
package/package.json
CHANGED
package/rpc.js
CHANGED
|
@@ -2,6 +2,11 @@ const { WebSocket } = require('unws')
|
|
|
2
2
|
class RPC {
|
|
3
3
|
constructor(url) {
|
|
4
4
|
this.url = url
|
|
5
|
+
this.wsOptions = {
|
|
6
|
+
headers: {
|
|
7
|
+
"x-pinokio-client": "pterm"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
5
10
|
}
|
|
6
11
|
async status(rpc) {
|
|
7
12
|
let res = await new Promise((resolve, reject) => {
|
|
@@ -38,7 +43,7 @@ class RPC {
|
|
|
38
43
|
if (this.ws) {
|
|
39
44
|
this.ws.send(JSON.stringify(rpc))
|
|
40
45
|
} else {
|
|
41
|
-
this.ws = new WebSocket(this.url)
|
|
46
|
+
this.ws = new WebSocket(this.url, this.wsOptions)
|
|
42
47
|
this.ws.addEventListener('open', () => {
|
|
43
48
|
this.ws.send(JSON.stringify(rpc))
|
|
44
49
|
});
|
package/script.js
CHANGED
|
@@ -52,7 +52,14 @@ class Script {
|
|
|
52
52
|
stop()
|
|
53
53
|
});
|
|
54
54
|
let default_uri = await new Promise((resolve, reject) => {
|
|
55
|
-
rpc.run({
|
|
55
|
+
rpc.run({
|
|
56
|
+
uri,
|
|
57
|
+
mode: "open",
|
|
58
|
+
source: "pterm",
|
|
59
|
+
client: {
|
|
60
|
+
source: "pterm"
|
|
61
|
+
}
|
|
62
|
+
}, (packet) => {
|
|
56
63
|
if (packet.data && packet.data.uri) {
|
|
57
64
|
// start
|
|
58
65
|
//rpc.stop({ uri })
|
|
@@ -134,9 +141,11 @@ class Script {
|
|
|
134
141
|
});
|
|
135
142
|
await rpc.run({
|
|
136
143
|
uri,
|
|
144
|
+
source: "pterm",
|
|
137
145
|
client: {
|
|
138
146
|
cols,
|
|
139
147
|
rows,
|
|
148
|
+
source: "pterm"
|
|
140
149
|
}
|
|
141
150
|
}, (packet) => {
|
|
142
151
|
if (packet.type === "stop") {
|
package/util.js
CHANGED
|
@@ -9,8 +9,27 @@ class Util {
|
|
|
9
9
|
}
|
|
10
10
|
async search(argv) {
|
|
11
11
|
const query = (argv._.slice(1).join(" ") || argv.q || "").trim()
|
|
12
|
+
const params = { q: query }
|
|
13
|
+
const mode = typeof argv.mode === "string" ? argv.mode.trim().toLowerCase() : ""
|
|
14
|
+
const minMatchRaw = argv.minMatch ?? argv["min-match"] ?? argv.min_match
|
|
15
|
+
const limitRaw = argv.limit
|
|
16
|
+
if (mode === "broad" || mode === "balanced" || mode === "strict") {
|
|
17
|
+
params.mode = mode
|
|
18
|
+
}
|
|
19
|
+
if (minMatchRaw !== undefined && minMatchRaw !== null && minMatchRaw !== "") {
|
|
20
|
+
const minMatch = Number.parseInt(String(minMatchRaw), 10)
|
|
21
|
+
if (Number.isFinite(minMatch) && minMatch > 0) {
|
|
22
|
+
params.min_match = String(minMatch)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (limitRaw !== undefined && limitRaw !== null && limitRaw !== "") {
|
|
26
|
+
const limit = Number.parseInt(String(limitRaw), 10)
|
|
27
|
+
if (Number.isFinite(limit) && limit > 0) {
|
|
28
|
+
params.limit = String(limit)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
12
31
|
const response = await axios.get("http://localhost:42000/apps/search", {
|
|
13
|
-
params
|
|
32
|
+
params
|
|
14
33
|
})
|
|
15
34
|
this.printJson(response.data)
|
|
16
35
|
}
|
|
@@ -52,6 +71,65 @@ class Util {
|
|
|
52
71
|
const response = await axios.get(url)
|
|
53
72
|
this.printJson(response.data)
|
|
54
73
|
}
|
|
74
|
+
async stars(argv) {
|
|
75
|
+
const query = (argv._.slice(1).join(" ") || argv.q || "").trim().toLowerCase()
|
|
76
|
+
const [preferenceResponse, appResponse] = await Promise.all([
|
|
77
|
+
axios.get("http://localhost:42000/apps/preferences"),
|
|
78
|
+
axios.get("http://localhost:42000/info/apps")
|
|
79
|
+
])
|
|
80
|
+
const preferenceItems = preferenceResponse && preferenceResponse.data && preferenceResponse.data.items
|
|
81
|
+
? preferenceResponse.data.items
|
|
82
|
+
: {}
|
|
83
|
+
const apps = appResponse && appResponse.data && Array.isArray(appResponse.data.apps)
|
|
84
|
+
? appResponse.data.apps
|
|
85
|
+
: []
|
|
86
|
+
const appsById = new Map()
|
|
87
|
+
for (const app of apps) {
|
|
88
|
+
if (!app || !app.name) continue
|
|
89
|
+
appsById.set(app.name, app)
|
|
90
|
+
}
|
|
91
|
+
const starredApps = Object.entries(preferenceItems)
|
|
92
|
+
.filter(([, preference]) => preference && preference.starred)
|
|
93
|
+
.map(([appId, preference]) => {
|
|
94
|
+
const app = appsById.get(appId) || {}
|
|
95
|
+
return {
|
|
96
|
+
app_id: appId,
|
|
97
|
+
title: app.title || appId,
|
|
98
|
+
description: app.description || "",
|
|
99
|
+
icon: app.icon || "/pinokio-black.png",
|
|
100
|
+
...preference
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
.sort((a, b) => {
|
|
104
|
+
const aLast = typeof a.last_launch_at === "string" ? Date.parse(a.last_launch_at) || 0 : 0
|
|
105
|
+
const bLast = typeof b.last_launch_at === "string" ? Date.parse(b.last_launch_at) || 0 : 0
|
|
106
|
+
if (aLast !== bLast) {
|
|
107
|
+
return bLast - aLast
|
|
108
|
+
}
|
|
109
|
+
return String(a.title || a.app_id).localeCompare(String(b.title || b.app_id))
|
|
110
|
+
})
|
|
111
|
+
.filter((app) => {
|
|
112
|
+
if (!query) return true
|
|
113
|
+
const haystack = `${app.app_id || ""}\n${app.title || ""}\n${app.description || ""}`.toLowerCase()
|
|
114
|
+
return haystack.includes(query)
|
|
115
|
+
})
|
|
116
|
+
this.printJson({
|
|
117
|
+
q: query,
|
|
118
|
+
count: starredApps.length,
|
|
119
|
+
apps: starredApps
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
async setStar(argv, starred) {
|
|
123
|
+
if (argv._.length <= 1) {
|
|
124
|
+
console.error("required argument: <app_id>")
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
const appId = argv._[1]
|
|
128
|
+
const response = await axios.put(`http://localhost:42000/apps/preferences/${encodeURIComponent(appId)}`, {
|
|
129
|
+
starred: Boolean(starred)
|
|
130
|
+
})
|
|
131
|
+
this.printJson(response.data)
|
|
132
|
+
}
|
|
55
133
|
async filepicker(argv) {
|
|
56
134
|
const rpc = new RPC("ws://localhost:42000")
|
|
57
135
|
if (argv.path) {
|