pterm 0.0.22 → 0.0.24
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 +71 -0
- package/index.js +8 -1
- package/package.json +1 -1
- package/util.js +85 -0
package/README.md
CHANGED
|
@@ -149,6 +149,42 @@ Launch a script directly with query parameters. Query parameters are passed thro
|
|
|
149
149
|
pterm start 'run.js?mode=Default'
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
+
## download
|
|
153
|
+
|
|
154
|
+
Clone an app repo into Pinokio's app directory without launching it.
|
|
155
|
+
|
|
156
|
+
### syntax
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
pterm download <uri> [name] [--branch=<branch>]
|
|
160
|
+
pterm download <uri> [name] -b <branch>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
- `uri`: required git repository URI
|
|
164
|
+
- `name`: (optional) target folder name under `PINOKIO_HOME/api`
|
|
165
|
+
- `--branch` / `-b`: (optional) clone a specific branch
|
|
166
|
+
|
|
167
|
+
Behavior:
|
|
168
|
+
|
|
169
|
+
- if `name` is omitted, Pinokio uses the same default destination folder naming as `git clone <uri>`
|
|
170
|
+
- if `name` is provided, Pinokio clones into `PINOKIO_HOME/api/<name>`
|
|
171
|
+
- if the target folder already exists, the command fails with `already exists`
|
|
172
|
+
- the command does not dedupe by repo URL
|
|
173
|
+
|
|
174
|
+
### examples
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
pterm download https://github.com/example/my-launcher.git
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
pterm download https://github.com/example/my-launcher.git my-launcher-dev
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
pterm download https://github.com/example/my-launcher.git my-launcher-dev --branch=feature-x
|
|
186
|
+
```
|
|
187
|
+
|
|
152
188
|
## search
|
|
153
189
|
|
|
154
190
|
Search installed or available apps.
|
|
@@ -179,6 +215,41 @@ pterm search --q="text generation"
|
|
|
179
215
|
pterm search "tts speech synthesis" --mode=balanced --min-match=2 --limit=8
|
|
180
216
|
```
|
|
181
217
|
|
|
218
|
+
## registry search
|
|
219
|
+
|
|
220
|
+
Search the remote Pinokio registry.
|
|
221
|
+
|
|
222
|
+
### syntax
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
pterm registry search [query words...]
|
|
226
|
+
pterm registry search --q="<query>" [--limit=<n>] [--sort=relevance|popular|trending|latest|created|checkins|name] [--platform=mac|windows|linux] [--gpu=nvidia|amd|apple]
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
- `--limit`: (optional) max number of app results to return.
|
|
230
|
+
- `--sort`: (optional) result ordering. Default is `relevance`.
|
|
231
|
+
- `--platform`: (optional) filter by observed platform support from public check-ins.
|
|
232
|
+
- `--gpu`: (optional) filter by observed GPU support from public check-ins.
|
|
233
|
+
|
|
234
|
+
By default, this command queries `https://api.pinokio.co/v1/search`. Override with `PINOKIO_REGISTRY_API_BASE`.
|
|
235
|
+
|
|
236
|
+
### examples
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
pterm registry search tts
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
pterm registry search "speech synthesis" --limit=5
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
PINOKIO_REGISTRY_API_BASE=https://api.pinokio.co pterm registry search comfyui --platform=mac --gpu=apple
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
PINOKIO_REGISTRY_API_BASE=https://api.pinokio.co pterm registry search comfyui --sort=popular
|
|
251
|
+
```
|
|
252
|
+
|
|
182
253
|
## which
|
|
183
254
|
|
|
184
255
|
Resolve the executable path for a command name through Pinokio's environment.
|
package/index.js
CHANGED
|
@@ -58,7 +58,14 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
58
58
|
} else if (cmd === "filepicker") {
|
|
59
59
|
await util.filepicker(argv)
|
|
60
60
|
} else if (cmd === "download") {
|
|
61
|
-
await util.
|
|
61
|
+
await util.appDownload(argv)
|
|
62
|
+
} else if (cmd === "registry") {
|
|
63
|
+
const subcmd = argv._.length > 1 ? String(argv._[1]).toLowerCase() : ""
|
|
64
|
+
if (subcmd === "search") {
|
|
65
|
+
await util.registrySearch(argv)
|
|
66
|
+
} else {
|
|
67
|
+
console.error("supported subcommands: search")
|
|
68
|
+
}
|
|
62
69
|
} else if (cmd === "search") {
|
|
63
70
|
await util.search(argv)
|
|
64
71
|
} else if (cmd === "stars") {
|
package/package.json
CHANGED
package/util.js
CHANGED
|
@@ -7,6 +7,17 @@ class Util {
|
|
|
7
7
|
process.stdout.write(JSON.stringify(payload, null, 2))
|
|
8
8
|
process.stdout.write("\n")
|
|
9
9
|
}
|
|
10
|
+
formatRpcError(payload) {
|
|
11
|
+
if (typeof payload !== "string") {
|
|
12
|
+
return JSON.stringify(payload)
|
|
13
|
+
}
|
|
14
|
+
const [firstLine] = payload.split(/\r?\n/)
|
|
15
|
+
return firstLine || payload
|
|
16
|
+
}
|
|
17
|
+
registryBase() {
|
|
18
|
+
const value = String(process.env.PINOKIO_REGISTRY_API_BASE || "https://api.pinokio.co").trim()
|
|
19
|
+
return value.replace(/\/$/, "")
|
|
20
|
+
}
|
|
10
21
|
async search(argv) {
|
|
11
22
|
const query = (argv._.slice(1).join(" ") || argv.q || "").trim()
|
|
12
23
|
const params = { q: query }
|
|
@@ -33,6 +44,35 @@ class Util {
|
|
|
33
44
|
})
|
|
34
45
|
this.printJson(response.data)
|
|
35
46
|
}
|
|
47
|
+
async registrySearch(argv) {
|
|
48
|
+
const query = (argv._.slice(2).join(" ") || argv.q || "").trim()
|
|
49
|
+
if (!query) {
|
|
50
|
+
console.error("required argument: <query>")
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
const params = { q: query }
|
|
54
|
+
const limitRaw = argv.limit
|
|
55
|
+
const sortRaw = typeof argv.sort === "string" ? argv.sort.trim().toLowerCase() : ""
|
|
56
|
+
const platformRaw = typeof argv.platform === "string" ? argv.platform.trim().toLowerCase() : ""
|
|
57
|
+
const gpuRaw = typeof argv.gpu === "string" ? argv.gpu.trim().toLowerCase() : ""
|
|
58
|
+
if (limitRaw !== undefined && limitRaw !== null && limitRaw !== "") {
|
|
59
|
+
const limit = Number.parseInt(String(limitRaw), 10)
|
|
60
|
+
if (Number.isFinite(limit) && limit > 0) {
|
|
61
|
+
params.limit = String(limit)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (["relevance", "popular", "trending", "latest", "created", "checkins", "name"].includes(sortRaw)) {
|
|
65
|
+
params.sort = sortRaw
|
|
66
|
+
}
|
|
67
|
+
if (platformRaw === "mac" || platformRaw === "windows" || platformRaw === "linux") {
|
|
68
|
+
params.platform = platformRaw
|
|
69
|
+
}
|
|
70
|
+
if (gpuRaw === "nvidia" || gpuRaw === "amd" || gpuRaw === "apple") {
|
|
71
|
+
params.gpu = gpuRaw
|
|
72
|
+
}
|
|
73
|
+
const response = await axios.get(`${this.registryBase()}/v1/search`, { params })
|
|
74
|
+
this.printJson(response.data)
|
|
75
|
+
}
|
|
36
76
|
async status(argv) {
|
|
37
77
|
if (argv._.length <= 1) {
|
|
38
78
|
console.error("required argument: <app_id>")
|
|
@@ -216,6 +256,51 @@ class Util {
|
|
|
216
256
|
let response = await axios.post("http://localhost:42000/go", { url })
|
|
217
257
|
return response
|
|
218
258
|
}
|
|
259
|
+
async appDownload(argv) {
|
|
260
|
+
if (argv._.length <= 1) {
|
|
261
|
+
console.error("required argument: <uri>")
|
|
262
|
+
process.exitCode = 1
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
const uri = String(argv._[1]).trim()
|
|
266
|
+
const name = argv._.length > 2 ? String(argv._[2]).trim() : ""
|
|
267
|
+
const branch = typeof argv.b === "string"
|
|
268
|
+
? argv.b.trim()
|
|
269
|
+
: (typeof argv.branch === "string" ? argv.branch.trim() : "")
|
|
270
|
+
const rpc = new RPC("ws://localhost:42000")
|
|
271
|
+
let exitCode = 0
|
|
272
|
+
await rpc.run({
|
|
273
|
+
method: "app.download",
|
|
274
|
+
params: {
|
|
275
|
+
uri,
|
|
276
|
+
...(name ? { name } : {}),
|
|
277
|
+
...(branch ? { branch } : {})
|
|
278
|
+
}
|
|
279
|
+
}, (packet) => {
|
|
280
|
+
if (packet.type === "result") {
|
|
281
|
+
if (!packet.data || packet.data.ok === false) {
|
|
282
|
+
exitCode = 1
|
|
283
|
+
const message = packet.data && packet.data.error ? packet.data.error : "download failed"
|
|
284
|
+
if (packet.data && packet.data.path) {
|
|
285
|
+
console.error(`${message}: ${packet.data.path}`)
|
|
286
|
+
} else {
|
|
287
|
+
console.error(message)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
rpc.close()
|
|
291
|
+
} else if (packet.type === "stream") {
|
|
292
|
+
process.stdout.write(packet.data.raw)
|
|
293
|
+
} else if (packet.type === "error") {
|
|
294
|
+
exitCode = 1
|
|
295
|
+
console.error(this.formatRpcError(packet.data))
|
|
296
|
+
rpc.close()
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
if (exitCode !== 0) {
|
|
300
|
+
process.exitCode = exitCode
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// Keep the legacy URL download flow for `pterm run <url>`.
|
|
219
304
|
async download(argv) {
|
|
220
305
|
if (argv._.length > 1) {
|
|
221
306
|
let uri = argv._[1]
|