@ngosangns/ns-bridge 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ngosangns
4
+ Copyright (c) 2025-2026 Mike O'Brien (pi-provider-kiro)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,39 @@
1
- # Temporary Holding Version
1
+ # @ngosangns/ns-bridge
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ CLI for the [ns-bridge](https://github.com/ngosangns/ns-bridge) providers. It installs host packages and refreshes model catalogs in its own process, so Pi and OMP only read the files those commands write.
4
+
5
+ ```bash
6
+ npm install -g @ngosangns/ns-bridge
7
+ ns-bridge help
8
+ ```
9
+
10
+ ## Commands
11
+
12
+ Mutating commands preview. `--apply` runs them. `--dry-run` is the default.
13
+
14
+ ```bash
15
+ ns-bridge install [pi|omp|dsh|all] [--apply] [--profile <name>]
16
+ ns-bridge update [pi|omp|dsh|all] [--apply] [--profile <name>]
17
+ ns-bridge uninstall [pi|omp|dsh|all] [--apply] [--profile <name>]
18
+ ns-bridge models list [kiro|devin|grok|all]
19
+ ns-bridge models refresh [kiro|devin|grok|all] [--apply]
20
+ ns-bridge status
21
+ ```
22
+
23
+ | Host | Install | Update | Uninstall |
24
+ | --- | --- | --- | --- |
25
+ | pi | `pi install npm:@ngosangns/ns-pi-provider` | `pi update --extension npm:@ngosangns/ns-pi-provider` | `pi uninstall npm:@ngosangns/ns-pi-provider` |
26
+ | omp | `omp plugin install ns-omp-provider ns-omp-provider-kiro` | `omp plugin upgrade ns-omp-provider ns-omp-provider-kiro` | `omp plugin uninstall ns-omp-provider ns-omp-provider-kiro` |
27
+ | dsh | `dsh plugin --profile <name> add ns-dsh-llm-kiro ns-dsh-llm-devin ns-dsh-llm-grok` | `dsh plugin --profile <name> update …` | `dsh plugin --profile <name> remove …` |
28
+
29
+ DSH requires `--profile`. Profile `desktop` is refused: the Electron app owns it. `install` and `update` without `--profile` skip DSH and still preview Pi and OMP.
30
+
31
+ `models list` and `status` read the catalog files and do not import the provider cores:
32
+
33
+ - Kiro: `~/.ns-kiro-provider-models-cache.json`
34
+ - Devin: `$NS_DEVIN_MODEL_CACHE`, or `$XDG_DATA_HOME/ns-devin-provider/models.json`
35
+ - Grok: `~/.pi/agent/cache/ns-pi-provider/grok.models.json`
36
+
37
+ `models refresh --apply` writes those files from the bundled refresh. A missing file is reported as missing. The command does not print the in-memory fallback list.
38
+
39
+ Pi, OMP, and DSH read those files while they run. They do not refresh them.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Read the catalog files the hosts already use. This module does not import
3
+ * the vendor cores, so `ns-bridge status` and `models list` stay off the network.
4
+ */
5
+ export type Vendor = "kiro" | "devin" | "grok";
6
+ export interface CatalogPaths {
7
+ kiro: string;
8
+ devin: string;
9
+ grok: string;
10
+ }
11
+ export interface CatalogGroup {
12
+ label: string;
13
+ ids: string[];
14
+ fetchedAt?: number;
15
+ }
16
+ export interface CatalogReport {
17
+ vendor: Vendor;
18
+ path: string;
19
+ state: "missing" | "unreadable" | "ready";
20
+ groups: CatalogGroup[];
21
+ }
22
+ export declare function parseVendors(target: string | undefined): Vendor[] | {
23
+ error: string;
24
+ };
25
+ /** Same files the provider packages write. Overrides match those packages. */
26
+ export declare function catalogPaths(env?: NodeJS.ProcessEnv, home?: string): CatalogPaths;
27
+ export declare function readCatalogs(paths: CatalogPaths, vendors?: readonly Vendor[]): CatalogReport[];
28
+ export declare function formatCatalog(report: CatalogReport, mode: "list" | "status", now?: number): string[];
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Read the catalog files the hosts already use. This module does not import
3
+ * the vendor cores, so `ns-bridge status` and `models list` stay off the network.
4
+ */
5
+ import { readFileSync } from "node:fs";
6
+ import { homedir } from "node:os";
7
+ import { join } from "node:path";
8
+ const VENDORS = ["kiro", "devin", "grok"];
9
+ export function parseVendors(target) {
10
+ if (!target || target === "all")
11
+ return [...VENDORS];
12
+ if (target === "kiro" || target === "devin" || target === "grok")
13
+ return [target];
14
+ return { error: `unknown vendor ${target} (expected kiro, devin, grok, or all)` };
15
+ }
16
+ /** Same files the provider packages write. Overrides match those packages. */
17
+ export function catalogPaths(env = process.env, home = homedir()) {
18
+ const dataHome = env.XDG_DATA_HOME ?? join(home, ".local", "share");
19
+ return {
20
+ kiro: join(home, ".ns-kiro-provider-models-cache.json"),
21
+ devin: env.NS_DEVIN_MODEL_CACHE ?? join(dataHome, "ns-devin-provider", "models.json"),
22
+ grok: join(home, ".pi", "agent", "cache", "ns-pi-provider", "grok.models.json"),
23
+ };
24
+ }
25
+ export function readCatalogs(paths, vendors = VENDORS) {
26
+ return vendors.map((vendor) => readOne(vendor, paths[vendor]));
27
+ }
28
+ function readOne(vendor, path) {
29
+ let raw;
30
+ try {
31
+ raw = readFileSync(path, "utf8");
32
+ }
33
+ catch (error) {
34
+ const code = error.code;
35
+ if (code === "ENOENT")
36
+ return { vendor, path, state: "missing", groups: [] };
37
+ return { vendor, path, state: "unreadable", groups: [] };
38
+ }
39
+ const groups = vendor === "kiro" ? parseKiro(raw) : parseModelList(raw, vendor);
40
+ if (!groups)
41
+ return { vendor, path, state: "unreadable", groups: [] };
42
+ return { vendor, path, state: "ready", groups };
43
+ }
44
+ function parseKiro(raw) {
45
+ let parsed;
46
+ try {
47
+ parsed = JSON.parse(raw);
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ if (!isRecord(parsed) || !isRecord(parsed.regions))
53
+ return undefined;
54
+ const groups = [];
55
+ for (const [region, entry] of Object.entries(parsed.regions)) {
56
+ if (!isRecord(entry) || !Array.isArray(entry.models))
57
+ return undefined;
58
+ const ids = idsFrom(entry.models);
59
+ if (ids.length === 0)
60
+ continue;
61
+ groups.push({
62
+ label: region,
63
+ ids,
64
+ ...(typeof entry.fetchedAt === "number" ? { fetchedAt: entry.fetchedAt } : {}),
65
+ });
66
+ }
67
+ return groups;
68
+ }
69
+ function parseModelList(raw, label) {
70
+ let parsed;
71
+ try {
72
+ parsed = JSON.parse(raw);
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ if (!isRecord(parsed) || !Array.isArray(parsed.models))
78
+ return undefined;
79
+ return [
80
+ {
81
+ label,
82
+ ids: idsFrom(parsed.models),
83
+ ...(typeof parsed.fetchedAt === "number" ? { fetchedAt: parsed.fetchedAt } : {}),
84
+ },
85
+ ];
86
+ }
87
+ function idsFrom(models) {
88
+ const ids = [];
89
+ for (const entry of models) {
90
+ if (!isRecord(entry) || typeof entry.id !== "string" || entry.id.length === 0)
91
+ continue;
92
+ ids.push(entry.id);
93
+ }
94
+ return ids;
95
+ }
96
+ function isRecord(value) {
97
+ return typeof value === "object" && value !== null && !Array.isArray(value);
98
+ }
99
+ export function formatCatalog(report, mode, now = Date.now()) {
100
+ if (report.state === "missing")
101
+ return [`${report.vendor} no cache file ${report.path}`];
102
+ if (report.state === "unreadable")
103
+ return [`${report.vendor} unreadable cache ${report.path}`];
104
+ const ids = report.groups.flatMap((group) => group.ids);
105
+ const fetched = report.groups.find((group) => group.fetchedAt !== undefined)?.fetchedAt;
106
+ const when = fetched === undefined ? "" : ` fetched ${age(fetched, now)}`;
107
+ if (mode === "status") {
108
+ const lines = [`${report.vendor} ${ids.length} model(s)${when} ${report.path}`];
109
+ for (const group of report.groups) {
110
+ const shown = group.ids.slice(0, 8);
111
+ const extra = group.ids.length - shown.length;
112
+ const body = extra > 0 ? `${shown.join(", ")}, … (${extra} more)` : shown.join(", ");
113
+ const prefix = report.vendor === "kiro" ? `${group.label}: ` : "";
114
+ if (body)
115
+ lines.push(` ${prefix}${body}`);
116
+ }
117
+ return lines;
118
+ }
119
+ const lines = [`${report.vendor} ${report.path}${when}`];
120
+ for (const group of report.groups) {
121
+ if (report.vendor === "kiro") {
122
+ const regionWhen = group.fetchedAt === undefined ? "" : ` fetched ${age(group.fetchedAt, now)}`;
123
+ lines.push(` ${group.label}${regionWhen}`);
124
+ }
125
+ for (const id of group.ids)
126
+ lines.push(report.vendor === "kiro" ? ` ${id}` : ` ${id}`);
127
+ }
128
+ return lines;
129
+ }
130
+ function age(fetchedAt, now) {
131
+ const seconds = Math.max(0, Math.round((now - fetchedAt) / 1000));
132
+ if (seconds < 60)
133
+ return `${seconds}s ago`;
134
+ const minutes = Math.round(seconds / 60);
135
+ if (minutes < 60)
136
+ return `${minutes}m ago`;
137
+ const hours = Math.round(minutes / 60);
138
+ if (hours < 48)
139
+ return `${hours}h ago`;
140
+ return `${Math.round(hours / 24)}d ago`;
141
+ }
142
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `ns-bridge` command dispatcher.
3
+ *
4
+ * Mutating commands print the host argv and exit 0. `--apply` runs them.
5
+ * That matches the OKF tools in ns-docs: a preview is the default, and a write
6
+ * is an explicit flag.
7
+ */
8
+ import { type CatalogPaths } from "./catalog.js";
9
+ import { type ModelRefresh } from "./refresh.js";
10
+ export interface CommandResult {
11
+ code: number;
12
+ stdout: string;
13
+ stderr: string;
14
+ }
15
+ export type Runner = (argv: string[]) => Promise<CommandResult>;
16
+ export interface RunOptions {
17
+ log?: (line: string) => void;
18
+ err?: (line: string) => void;
19
+ runner?: Runner;
20
+ refreshers?: ModelRefresh;
21
+ paths?: CatalogPaths;
22
+ now?: number;
23
+ }
24
+ export declare function spawnRunner(): Runner;
25
+ export declare function run(argv: readonly string[], options?: RunOptions): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,238 @@
1
+ /**
2
+ * `ns-bridge` command dispatcher.
3
+ *
4
+ * Mutating commands print the host argv and exit 0. `--apply` runs them.
5
+ * That matches the OKF tools in ns-docs: a preview is the default, and a write
6
+ * is an explicit flag.
7
+ */
8
+ import { spawn } from "node:child_process";
9
+ import { catalogPaths, formatCatalog, parseVendors, readCatalogs } from "./catalog.js";
10
+ import { formatCommand, parseHosts, planHostCommands } from "./hosts.js";
11
+ import { defaultModelRefresh, refreshLine } from "./refresh.js";
12
+ const HELP = `ns-bridge — install, update, and refresh providers outside Pi, OMP, and DSH.
13
+
14
+ Mutating commands preview and do not spawn. Pass --apply to run them.
15
+ --dry-run is the default.
16
+
17
+ Usage:
18
+ ns-bridge install [pi|omp|dsh|all] [--apply] [--profile <name>]
19
+ ns-bridge update [pi|omp|dsh|all] [--apply] [--profile <name>]
20
+ ns-bridge uninstall [pi|omp|dsh|all] [--apply] [--profile <name>]
21
+ ns-bridge models list [kiro|devin|grok|all]
22
+ ns-bridge models refresh [kiro|devin|grok|all] [--apply]
23
+ ns-bridge status
24
+ ns-bridge help
25
+
26
+ Hosts:
27
+ pi pi install npm:@ngosangns/ns-pi-provider
28
+ pi update --extension npm:@ngosangns/ns-pi-provider
29
+ pi uninstall npm:@ngosangns/ns-pi-provider
30
+ omp omp plugin install ns-omp-provider ns-omp-provider-kiro
31
+ omp plugin upgrade ns-omp-provider ns-omp-provider-kiro
32
+ omp plugin uninstall ns-omp-provider ns-omp-provider-kiro
33
+ dsh dsh plugin --profile <name> add ns-dsh-llm-kiro ns-dsh-llm-devin ns-dsh-llm-grok
34
+ dsh plugin --profile <name> update …
35
+ dsh plugin --profile <name> remove …
36
+
37
+ DSH requires --profile. Profile "desktop" is refused: the Electron app owns it.
38
+ install/update without --profile skips DSH and still previews Pi and OMP.
39
+ These commands install the npm packages. A local Pi path stays until that install runs.
40
+
41
+ Model catalogs are files the hosts read. Providers do not refresh them.
42
+ This command writes those files:
43
+ ns-bridge models refresh --apply
44
+ `;
45
+ export function spawnRunner() {
46
+ return (argv) => new Promise((resolve) => {
47
+ const [command, ...args] = argv;
48
+ if (!command) {
49
+ resolve({ code: 127, stdout: "", stderr: "empty command" });
50
+ return;
51
+ }
52
+ const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
53
+ let stdout = "";
54
+ let stderr = "";
55
+ let settled = false;
56
+ const finish = (result) => {
57
+ if (settled)
58
+ return;
59
+ settled = true;
60
+ resolve(result);
61
+ };
62
+ child.stdout?.on("data", (chunk) => {
63
+ stdout += String(chunk);
64
+ });
65
+ child.stderr?.on("data", (chunk) => {
66
+ stderr += String(chunk);
67
+ });
68
+ child.on("error", (error) => {
69
+ finish({ code: 127, stdout, stderr: `${stderr}${error.message}` });
70
+ });
71
+ child.on("close", (code) => {
72
+ finish({ code: code ?? 1, stdout, stderr });
73
+ });
74
+ });
75
+ }
76
+ export async function run(argv, options = {}) {
77
+ const log = options.log ?? ((line) => console.log(line));
78
+ const err = options.err ?? ((line) => console.error(line));
79
+ const parsed = parseArgs(argv);
80
+ if ("error" in parsed) {
81
+ err(parsed.error);
82
+ err("run ns-bridge help");
83
+ return 1;
84
+ }
85
+ if (parsed.help || parsed.positionals.length === 0) {
86
+ log(HELP.trimEnd());
87
+ return 0;
88
+ }
89
+ const [command, target, extra] = parsed.positionals;
90
+ if (command === "help") {
91
+ log(HELP.trimEnd());
92
+ return 0;
93
+ }
94
+ if (command === "status") {
95
+ if (target) {
96
+ err(`status takes no arguments (got ${target})`);
97
+ return 1;
98
+ }
99
+ return printCatalogs(log, options, ["kiro", "devin", "grok"], "status");
100
+ }
101
+ if (command === "models") {
102
+ if (target !== "list" && target !== "refresh") {
103
+ err("usage: ns-bridge models list|refresh [kiro|devin|grok|all]");
104
+ return 1;
105
+ }
106
+ const vendors = parseVendors(extra);
107
+ if ("error" in vendors) {
108
+ err(vendors.error);
109
+ return 1;
110
+ }
111
+ if (parsed.positionals.length > 3) {
112
+ err(`unexpected argument ${parsed.positionals[3]}`);
113
+ return 1;
114
+ }
115
+ if (target === "list")
116
+ return printCatalogs(log, options, vendors, "list");
117
+ return refreshModels(log, err, parsed.apply, vendors, options);
118
+ }
119
+ if (command === "install" || command === "update" || command === "uninstall") {
120
+ if (parsed.positionals.length > 2) {
121
+ err(`unexpected argument ${extra}`);
122
+ return 1;
123
+ }
124
+ return runHost(command, target, parsed, log, err, options);
125
+ }
126
+ err(`unknown command ${command}`);
127
+ err("run ns-bridge help");
128
+ return 1;
129
+ }
130
+ function printCatalogs(log, options, vendors, mode) {
131
+ const paths = options.paths ?? catalogPaths();
132
+ const now = options.now ?? Date.now();
133
+ for (const report of readCatalogs(paths, vendors)) {
134
+ for (const line of formatCatalog(report, mode, now))
135
+ log(line);
136
+ }
137
+ return 0;
138
+ }
139
+ async function refreshModels(log, err, apply, vendors, options) {
140
+ if (!apply) {
141
+ log("# dry-run (pass --apply to run)");
142
+ for (const vendor of vendors)
143
+ log(`refresh ${vendor}`);
144
+ return 0;
145
+ }
146
+ const refreshers = options.refreshers ?? (await defaultModelRefresh());
147
+ for (const vendor of vendors) {
148
+ try {
149
+ log(refreshLine(vendor, await refreshers[vendor]()));
150
+ }
151
+ catch (error) {
152
+ err(`${vendor}: ${error instanceof Error ? error.message : String(error)}`);
153
+ return 1;
154
+ }
155
+ }
156
+ return 0;
157
+ }
158
+ async function runHost(action, target, parsed, log, err, options) {
159
+ const hosts = parseHosts(target);
160
+ if ("error" in hosts) {
161
+ err(hosts.error);
162
+ return 1;
163
+ }
164
+ const plan = planHostCommands(action, hosts, parsed.profile);
165
+ if (plan.error) {
166
+ err(plan.error);
167
+ return 1;
168
+ }
169
+ if (!parsed.apply) {
170
+ log("# dry-run (pass --apply to run)");
171
+ for (const argv of plan.commands)
172
+ log(formatCommand(argv));
173
+ if (plan.skipDsh)
174
+ log("# dsh skipped: pass --profile <name>");
175
+ return 0;
176
+ }
177
+ const runner = options.runner ?? spawnRunner();
178
+ for (const argv of plan.commands) {
179
+ log(formatCommand(argv));
180
+ const result = await runner(argv);
181
+ if (result.stdout.trim())
182
+ log(result.stdout.trimEnd());
183
+ if (result.code !== 0) {
184
+ if (result.stderr.trim())
185
+ err(result.stderr.trimEnd());
186
+ err(`${formatCommand(argv)} exited ${result.code}`);
187
+ return 2;
188
+ }
189
+ }
190
+ if (plan.skipDsh)
191
+ log("# dsh skipped: pass --profile <name>");
192
+ return 0;
193
+ }
194
+ function parseArgs(argv) {
195
+ const positionals = [];
196
+ let apply = false;
197
+ let profile;
198
+ let help = false;
199
+ for (let index = 0; index < argv.length; index += 1) {
200
+ const arg = argv[index] ?? "";
201
+ if (arg === "--") {
202
+ positionals.push(...argv.slice(index + 1));
203
+ break;
204
+ }
205
+ if (arg === "--help" || arg === "-h") {
206
+ help = true;
207
+ continue;
208
+ }
209
+ if (arg === "--apply") {
210
+ apply = true;
211
+ continue;
212
+ }
213
+ if (arg === "--dry-run") {
214
+ apply = false;
215
+ continue;
216
+ }
217
+ if (arg === "--profile") {
218
+ const value = argv[index + 1];
219
+ if (!value || value.startsWith("-"))
220
+ return { error: "--profile needs a name" };
221
+ profile = value;
222
+ index += 1;
223
+ continue;
224
+ }
225
+ if (arg.startsWith("--profile=")) {
226
+ const value = arg.slice("--profile=".length);
227
+ if (!value)
228
+ return { error: "--profile needs a name" };
229
+ profile = value;
230
+ continue;
231
+ }
232
+ if (arg.startsWith("-"))
233
+ return { error: `unknown flag ${arg}` };
234
+ positionals.push(arg);
235
+ }
236
+ return { positionals, apply, profile, help };
237
+ }
238
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /** Host package commands. Mutating commands are previews until `--apply`. */
2
+ export declare const PI_SOURCE = "npm:@ngosangns/ns-pi-provider";
3
+ export declare const OMP_PACKAGES: readonly ["ns-omp-provider", "ns-omp-provider-kiro"];
4
+ export declare const DSH_PACKAGES: readonly ["ns-dsh-llm-kiro", "ns-dsh-llm-devin", "ns-dsh-llm-grok"];
5
+ export type Host = "pi" | "omp" | "dsh";
6
+ export type HostAction = "install" | "update" | "uninstall";
7
+ export interface HostPlan {
8
+ commands: string[][];
9
+ /** `install all` has no profile, so DSH is left out of the preview. */
10
+ skipDsh: boolean;
11
+ error?: string;
12
+ }
13
+ export declare function parseHosts(target: string | undefined): Host[] | {
14
+ error: string;
15
+ };
16
+ /** Quote one argv element the way a shell would show it. */
17
+ export declare function formatCommand(argv: readonly string[]): string;
18
+ /**
19
+ * The commands `ns-bridge` would run. DSH always needs `--profile`.
20
+ * Profile `desktop` is refused: the Electron app owns that profile.
21
+ */
22
+ export declare function planHostCommands(action: HostAction, hosts: readonly Host[], profile: string | undefined): HostPlan;
package/dist/hosts.js ADDED
@@ -0,0 +1,65 @@
1
+ /** Host package commands. Mutating commands are previews until `--apply`. */
2
+ export const PI_SOURCE = "npm:@ngosangns/ns-pi-provider";
3
+ export const OMP_PACKAGES = ["ns-omp-provider", "ns-omp-provider-kiro"];
4
+ export const DSH_PACKAGES = ["ns-dsh-llm-kiro", "ns-dsh-llm-devin", "ns-dsh-llm-grok"];
5
+ const HOSTS = ["pi", "omp", "dsh"];
6
+ export function parseHosts(target) {
7
+ if (!target || target === "all")
8
+ return [...HOSTS];
9
+ if (target === "pi" || target === "omp" || target === "dsh")
10
+ return [target];
11
+ return { error: `unknown host ${target} (expected pi, omp, dsh, or all)` };
12
+ }
13
+ /** Quote one argv element the way a shell would show it. */
14
+ export function formatCommand(argv) {
15
+ return argv.map(quoteArg).join(" ");
16
+ }
17
+ function quoteArg(arg) {
18
+ if (arg.length === 0)
19
+ return "''";
20
+ if (/^[A-Za-z0-9_@./:=+-]+$/.test(arg))
21
+ return arg;
22
+ return `'${arg.replaceAll("'", `'\\''`)}'`;
23
+ }
24
+ /**
25
+ * The commands `ns-bridge` would run. DSH always needs `--profile`.
26
+ * Profile `desktop` is refused: the Electron app owns that profile.
27
+ */
28
+ export function planHostCommands(action, hosts, profile) {
29
+ const wantsDsh = hosts.includes("dsh");
30
+ if (wantsDsh && profile?.toLowerCase() === "desktop") {
31
+ return {
32
+ commands: [],
33
+ skipDsh: false,
34
+ error: 'profile "desktop" is managed by the DSH Electron app; pass another profile name',
35
+ };
36
+ }
37
+ if (wantsDsh && !profile) {
38
+ if (hosts.length === 1) {
39
+ return { commands: [], skipDsh: false, error: "dsh needs --profile <name>" };
40
+ }
41
+ }
42
+ const commands = [];
43
+ for (const host of hosts) {
44
+ if (host === "dsh" && !profile)
45
+ continue;
46
+ commands.push(commandFor(action, host, profile));
47
+ }
48
+ return { commands, skipDsh: wantsDsh && !profile };
49
+ }
50
+ function commandFor(action, host, profile) {
51
+ if (host === "pi") {
52
+ if (action === "install")
53
+ return ["pi", "install", PI_SOURCE];
54
+ if (action === "update")
55
+ return ["pi", "update", "--extension", PI_SOURCE];
56
+ return ["pi", "uninstall", PI_SOURCE];
57
+ }
58
+ if (host === "omp") {
59
+ const verb = action === "update" ? "upgrade" : action === "uninstall" ? "uninstall" : "install";
60
+ return ["omp", "plugin", verb, ...OMP_PACKAGES];
61
+ }
62
+ const verb = action === "update" ? "update" : action === "uninstall" ? "remove" : "add";
63
+ return ["dsh", "plugin", "--profile", profile ?? "", verb, ...DSH_PACKAGES];
64
+ }
65
+ //# sourceMappingURL=hosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../src/hosts.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "./cli.js";
3
+ const code = await run(process.argv.slice(2));
4
+ process.exit(code);
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}