@rnbsolucoes/axion-code 0.1.52 → 0.1.54

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
@@ -112,6 +112,27 @@ current platform into the local Axion Code bin directory and then executes it. I
112
112
  a source clone only, if no packaged binary exists, the wrapper can build from Go
113
113
  as a development fallback.
114
114
 
115
+ ### Terminal setup (multi-line composer)
116
+
117
+ In the chat composer, **Enter sends** and **Ctrl+J inserts a newline**. Terminals
118
+ do not report Shift+Enter or Ctrl+Enter as distinct keys to the app on Windows,
119
+ so those keys must be mapped to send a newline.
120
+
121
+ On the **first run**, Axion does this automatically for Windows Terminal: it maps
122
+ **Shift+Enter** and **Ctrl+Enter** to send a newline (only when those keys are
123
+ free — it never overwrites an existing binding), writes a `settings.json.axion-bak`
124
+ backup, and prints a one-line notice. Reopen the terminal tab to apply. This runs
125
+ at runtime (not via an npm `postinstall` hook) and only once, tracked by a marker
126
+ in the local bin directory.
127
+
128
+ Opt out with `AXION_SKIP_TERMINAL_SETUP=1`. Re-apply or repair anytime with:
129
+
130
+ ```powershell
131
+ axion terminal-setup
132
+ ```
133
+
134
+ On other terminals, bind Shift+Enter / Ctrl+Enter to send a newline (`\n`) manually.
135
+
115
136
  To classify the currently executed binary for support or security review, run:
116
137
 
117
138
  ```powershell
package/npm/bin/axion.mjs CHANGED
@@ -328,11 +328,133 @@ async function updateCommandHandler(args) {
328
328
  console.log("Axion Code update completed. Run axion again.");
329
329
  }
330
330
 
331
+ function applyTerminalSetup({ auto = false } = {}) {
332
+ // Map Shift+Enter and Ctrl+Enter to send a literal newline (LF). Axion's
333
+ // composer inserts a line break on LF, while plain Enter (CR) still sends.
334
+ // This is needed because terminals do not report Shift+Enter/Ctrl+Enter as
335
+ // distinct keys to the app on Windows. In auto mode it stays silent, never
336
+ // clobbers an existing user binding, and swallows failures.
337
+ if (!isWindows) {
338
+ if (!auto) {
339
+ console.log("axion terminal-setup currently automates Windows Terminal.");
340
+ console.log("On other terminals, bind Shift+Enter (and/or Ctrl+Enter) to send a newline (\\n).");
341
+ }
342
+ return { changed: false, reason: "unsupported" };
343
+ }
344
+ const localAppData = process.env.LOCALAPPDATA || join(process.env.USERPROFILE || root, "AppData", "Local");
345
+ const candidates = [
346
+ join(localAppData, "Packages", "Microsoft.WindowsTerminal_8wekyb3d8bbwe", "LocalState", "settings.json"),
347
+ join(localAppData, "Packages", "Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe", "LocalState", "settings.json"),
348
+ join(localAppData, "Microsoft", "Windows Terminal", "settings.json")
349
+ ];
350
+ const settingsPath = candidates.find((p) => existsSync(p));
351
+ if (!settingsPath) {
352
+ if (!auto) {
353
+ console.log("Windows Terminal settings.json not found.");
354
+ console.log("If you use another terminal, bind Shift+Enter / Ctrl+Enter to send a newline (\\n).");
355
+ }
356
+ return { changed: false, reason: "not-found" };
357
+ }
358
+ let settings;
359
+ try {
360
+ settings = JSON.parse(readFileSync(settingsPath, "utf8"));
361
+ } catch (err) {
362
+ if (!auto) {
363
+ console.error(`Could not parse ${settingsPath}: ${err.message}`);
364
+ process.exit(1);
365
+ }
366
+ return { changed: false, reason: "parse-error" };
367
+ }
368
+ if (!Array.isArray(settings.keybindings)) settings.keybindings = [];
369
+ const wanted = ["shift+enter", "ctrl+enter"];
370
+ // Windows Terminal may normalize an inline {command,keys} binding into an
371
+ // id-based one ({id,keys}) plus an entry in `actions`, so resolve both forms.
372
+ const effectiveCommand = (k) => {
373
+ if (!k) return null;
374
+ if (k.command) return k.command;
375
+ if (k.id) {
376
+ const a = (settings.actions || []).find((x) => x && x.id === k.id);
377
+ if (a && a.command) return a.command;
378
+ }
379
+ return null;
380
+ };
381
+ const isOurs = (k, keys) => {
382
+ if (!k || k.keys !== keys) return false;
383
+ const c = effectiveCommand(k);
384
+ return c && c.action === "sendInput" && c.input === "\n";
385
+ };
386
+ if (wanted.every((keys) => settings.keybindings.some((k) => isOurs(k, keys)))) {
387
+ if (!auto) console.log("Windows Terminal is already set up: Shift+Enter and Ctrl+Enter insert a newline.");
388
+ return { changed: false, reason: "already" };
389
+ }
390
+ if (auto) {
391
+ // Never overwrite a binding the user assigned to these keys themselves.
392
+ for (const keys of wanted) {
393
+ const existing = settings.keybindings.find((k) => k && k.keys === keys);
394
+ if (existing && !isOurs(existing, keys)) return { changed: false, reason: "conflict" };
395
+ }
396
+ }
397
+ settings.keybindings = settings.keybindings.filter((k) => !(k && wanted.includes(k.keys)));
398
+ for (const keys of wanted) {
399
+ settings.keybindings.push({ command: { action: "sendInput", input: "\n" }, keys });
400
+ }
401
+ const backup = `${settingsPath}.axion-bak`;
402
+ try {
403
+ copyFileSync(settingsPath, backup);
404
+ } catch {}
405
+ try {
406
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 4));
407
+ } catch (err) {
408
+ if (!auto) {
409
+ console.error(err.message);
410
+ process.exit(1);
411
+ }
412
+ return { changed: false, reason: "write-error" };
413
+ }
414
+ if (!auto) {
415
+ console.log("Windows Terminal configured: Shift+Enter and Ctrl+Enter now insert a newline in Axion (Enter still sends).");
416
+ console.log(`Settings: ${settingsPath}`);
417
+ console.log(`Backup: ${backup}`);
418
+ console.log("Reopen the terminal tab if the change does not take effect immediately.");
419
+ }
420
+ return { changed: true, settingsPath, backup };
421
+ }
422
+
423
+ function terminalSetupHandler() {
424
+ applyTerminalSetup({ auto: false });
425
+ }
426
+
427
+ function maybeFirstRunTerminalSetup() {
428
+ if (!isWindows || process.env.AXION_SKIP_TERMINAL_SETUP) return;
429
+ const marker = join(binDir, ".axion-terminal-setup-done");
430
+ if (existsSync(marker)) return;
431
+ try {
432
+ const res = applyTerminalSetup({ auto: true });
433
+ if (res.changed) {
434
+ console.log(
435
+ `Axion enabled Shift+Enter and Ctrl+Enter as newline keys in Windows Terminal ` +
436
+ `(reopen the tab to apply; backup at ${res.backup}, opt out with AXION_SKIP_TERMINAL_SETUP=1, ` +
437
+ `redo with 'axion terminal-setup').`
438
+ );
439
+ }
440
+ } catch {}
441
+ try {
442
+ mkdirSync(binDir, { recursive: true });
443
+ writeFileSync(marker, new Date().toISOString());
444
+ } catch {}
445
+ }
446
+
331
447
  const args = process.argv.slice(2);
332
448
  if (args[0] === "update") {
333
449
  await updateCommandHandler(args.slice(1));
334
450
  process.exit(0);
335
451
  }
452
+ if (args[0] === "terminal-setup") {
453
+ terminalSetupHandler();
454
+ process.exit(0);
455
+ }
456
+
457
+ maybeFirstRunTerminalSetup();
336
458
 
337
459
  const updateInfo = await readUpdateInfo();
338
460
  ensureBinary();
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rnbsolucoes/axion-code",
3
- "version": "0.1.52",
3
+ "version": "0.1.54",
4
4
  "description": "Axion Code CLI harness for the Axion ecosystem.",
5
5
  "type": "module",
6
6
  "repository": {