zyrouter 0.1.3 → 0.1.4

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 CHANGED
@@ -11,7 +11,7 @@ to `~/.zyrouter/backups/`, writes the ZyRouter settings, and sends one small tes
11
11
 
12
12
  | Tool | File it writes |
13
13
  | --- | --- |
14
- | Codex (CLI & VS Code) | `~/.codex/config.toml` and the `ZYROUTER_API_KEY` user environment variable |
14
+ | Codex (CLI, VS Code & App) | `~/.codex/config.toml` and the `ZYROUTER_API_KEY` user environment variable |
15
15
  | Claude Code | `~/.claude/settings.json` |
16
16
  | OpenCode | `~/.config/opencode/opencode.json` (key written in the file); an existing ZyRouter entry in `~/.local/share/opencode/auth.json` is updated too |
17
17
  | OpenClaw | `~/.openclaw/openclaw.json` |
package/lib/main.mjs CHANGED
@@ -42,7 +42,7 @@ function toolCatalog(ctx) {
42
42
  return [
43
43
  {
44
44
  id: "codex",
45
- name: "Codex (CLI & VS Code)",
45
+ name: "Codex (CLI, VS Code & App)",
46
46
  protocol: "responses",
47
47
  // Many Codex users sign in with ChatGPT; switching it to ZyRouter must be picked, not pressed through with Enter.
48
48
  optIn: true,
@@ -294,11 +294,13 @@ export async function run(argv, overrides = {}) {
294
294
  const unknown = wanted.filter((id) => !tools.some((tool) => tool.id === id));
295
295
  if (unknown.length) throw new Error(`Aplikasi tidak dikenal: ${unknown.join(", ")}. Pilihan: ${tools.map((tool) => tool.id).join(", ")}`);
296
296
  } else if (canAsk && ctx.tty) {
297
+ // Nothing starts checked: a pre-checked app would be written instead of the one the cursor is on.
297
298
  const ids = await pickFromMenu(ctx, {
298
299
  title: "Pilih aplikasi yang mau diatur",
299
- hint: "↑↓ pindah · spasi centang · a semua · enter lanjut",
300
+ hint: "↑↓ pindah · spasi centang banyak · a semua · enter lanjut",
300
301
  multi: true,
301
- rows: tools.map((tool) => ({ label: tool.name, value: tool.id, note: toolNote(tool), checked: preselected.includes(tool) })),
302
+ initialValue: (preselected[0] || detected[0])?.id,
303
+ rows: tools.map((tool) => ({ label: tool.name, value: tool.id, note: toolNote(tool) })),
302
304
  });
303
305
  selected = tools.filter((tool) => ids.includes(tool.id));
304
306
  } else if (canAsk) {
package/lib/ui.mjs CHANGED
@@ -105,9 +105,14 @@ export async function readSecret(ctx, label) {
105
105
  return result.trim();
106
106
  }
107
107
 
108
+ /** What Enter applies in a multi menu: the checked rows, or the row under the cursor when none is checked. */
109
+ function multiMenuResult(items, checked, cursor) {
110
+ return checked.size ? items.filter((item) => checked.has(item.value)) : [items[cursor]];
111
+ }
112
+
108
113
  /**
109
114
  * Arrow-key menu. `rows` mixes { header } lines with { label, value, note, checked } items.
110
- * Single choice returns a value; multi choice returns the checked values.
115
+ * Single choice returns a value; multi choice returns the checked values, or the highlighted one if none is checked.
111
116
  */
112
117
  export async function pickFromMenu(ctx, { title, hint, rows, multi = false, initialValue }) {
113
118
  const { style } = ctx;
@@ -137,6 +142,7 @@ export async function pickFromMenu(ctx, { title, hint, rows, multi = false, init
137
142
  lines.push(` ${pointer} ${box}${label}${row.note ? ` ${style.gray(row.note)}` : ""}`);
138
143
  }
139
144
  if (start + height < rows.length) lines.push(style.gray(" ↓ lainnya"));
145
+ if (multi) lines.push(` ${style.gray("Enter akan mengatur:")} ${style.bold(multiMenuResult(items, checked, cursor).map((item) => item.label).join(", "))}`);
140
146
  if (drawn) process.stdout.write(`\x1b[${drawn}A\x1b[0J`);
141
147
  process.stdout.write(`${lines.join("\n")}\n`);
142
148
  drawn = lines.length;
@@ -155,7 +161,7 @@ export async function pickFromMenu(ctx, { title, hint, rows, multi = false, init
155
161
  if (checked.size === items.length) checked.clear();
156
162
  else items.forEach((item) => checked.add(item.value));
157
163
  } else if (key.name === "return" || key.name === "enter") {
158
- return done(multi ? items.filter((item) => checked.has(item.value)).map((item) => item.value) : items[cursor].value);
164
+ return done(multi ? multiMenuResult(items, checked, cursor).map((item) => item.value) : items[cursor].value);
159
165
  }
160
166
  render();
161
167
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zyrouter",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Connect Codex, Claude Code, OpenCode, OpenClaw and Hermes Agent to ZyRouter with one command.",
5
5
  "type": "module",
6
6
  "bin": {