@andespindola/brainlink 0.1.0-beta.32 → 0.1.0-beta.33

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
@@ -553,7 +553,8 @@ blink server --host 127.0.0.1 --port 4321 --watch
553
553
  ```
554
554
 
555
555
  By default, the server uses `$HOME/.brainlink/vault`. Pass `--vault ./vault` only when you want to inspect a custom vault.
556
- By default, `blink server` also opens the graph URL in your default browser. Use `--no-open` to keep it headless.
556
+ By default, `blink server` tries to open the graph in a dedicated app window (`--app=<url>` on compatible browsers).
557
+ If app-window launch is unavailable, it falls back to the default browser. Use `--no-open` to keep it headless.
557
558
 
558
559
  The graph UI shows:
559
560
 
@@ -843,7 +844,8 @@ blink server --vault ./vault --watch --no-open
843
844
  ```
844
845
 
845
846
  Starts the local read-only graph UI and HTTP API.
846
- By default, it opens the graph URL in your default browser. Use `--no-open` to skip that behavior.
847
+ By default, it tries to open a dedicated app window for the graph URL and falls back to browser open when app-window mode is unavailable.
848
+ Use `--no-open` to skip that behavior.
847
849
 
848
850
  The HTTP server only binds to loopback hosts such as `127.0.0.1`, `localhost` or `::1`.
849
851
 
@@ -1,5 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { mkdir, writeFile } from 'node:fs/promises';
3
+ import { existsSync } from 'node:fs';
3
4
  import { dirname, relative, resolve } from 'node:path';
4
5
  import { platform } from 'node:os';
5
6
  import { spawn } from 'node:child_process';
@@ -26,28 +27,67 @@ const resolveAddContent = (options) => {
26
27
  }
27
28
  return readFileSync(options.contentFile, 'utf8');
28
29
  };
30
+ const spawnDetached = (command, args) => {
31
+ try {
32
+ const child = spawn(command, args, { detached: true, stdio: 'ignore' });
33
+ child.unref();
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ };
40
+ const openGraphInAppWindow = (url) => {
41
+ if (platform() === 'darwin') {
42
+ const macCandidates = [
43
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
44
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
45
+ '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'
46
+ ]
47
+ .filter((candidate) => existsSync(candidate))
48
+ .map((binary) => ({ binary, args: [`--app=${url}`, '--new-window'] }));
49
+ for (const candidate of macCandidates) {
50
+ if (spawnDetached(candidate.binary, candidate.args)) {
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ }
56
+ if (platform() === 'win32') {
57
+ const appArgument = `--app=${url}`;
58
+ return (spawnDetached('cmd', ['/c', 'start', '', 'chrome', appArgument, '--new-window']) ||
59
+ spawnDetached('cmd', ['/c', 'start', '', 'msedge', appArgument, '--new-window']) ||
60
+ spawnDetached('cmd', ['/c', 'start', '', 'chromium', appArgument, '--new-window']));
61
+ }
62
+ const appArgument = `--app=${url}`;
63
+ return (spawnDetached('google-chrome', [appArgument, '--new-window']) ||
64
+ spawnDetached('chromium-browser', [appArgument, '--new-window']) ||
65
+ spawnDetached('chromium', [appArgument, '--new-window']) ||
66
+ spawnDetached('microsoft-edge', [appArgument, '--new-window']) ||
67
+ spawnDetached('microsoft-edge-stable', [appArgument, '--new-window']));
68
+ };
29
69
  const openUrlInBrowser = (url) => {
30
70
  const openDisabled = process.env.BRAINLINK_NO_BROWSER === '1' ||
31
71
  process.env.BRAINLINK_NO_BROWSER === 'true' ||
32
72
  process.env.CI === 'true';
33
73
  if (openDisabled) {
34
- return;
74
+ return { opened: false, mode: 'none' };
75
+ }
76
+ if (openGraphInAppWindow(url)) {
77
+ return { opened: true, mode: 'app-window' };
35
78
  }
36
79
  try {
37
80
  if (platform() === 'darwin') {
38
- const child = spawn('open', [url], { detached: true, stdio: 'ignore' });
39
- child.unref();
40
- return;
81
+ return { opened: spawnDetached('open', [url]), mode: 'browser' };
41
82
  }
42
83
  if (platform() === 'win32') {
43
- const child = spawn('cmd', ['/c', 'start', '', url], { detached: true, stdio: 'ignore' });
44
- child.unref();
45
- return;
84
+ return { opened: spawnDetached('cmd', ['/c', 'start', '', url]), mode: 'browser' };
46
85
  }
47
- const child = spawn('xdg-open', [url], { detached: true, stdio: 'ignore' });
48
- child.unref();
86
+ return { opened: spawnDetached('xdg-open', [url]), mode: 'browser' };
87
+ }
88
+ catch {
89
+ return { opened: false, mode: 'none' };
49
90
  }
50
- catch { }
51
91
  };
52
92
  export const registerWriteCommands = (program) => {
53
93
  program
@@ -251,10 +291,20 @@ export const registerWriteCommands = (program) => {
251
291
  shouldIndex: options.index,
252
292
  shouldWatch: Boolean(options.watch)
253
293
  });
254
- if (options.open !== false) {
255
- openUrlInBrowser(server.url);
256
- }
257
- print(options.json, { url: server.url, watch: Boolean(options.watch), readonly: true, openedInBrowser: options.open !== false }, () => `Brainlink graph server running at ${server.url}${options.open !== false ? ' (opened in browser)' : ''}`);
294
+ const openResult = options.open !== false ? openUrlInBrowser(server.url) : { opened: false, mode: 'none' };
295
+ print(options.json, {
296
+ url: server.url,
297
+ watch: Boolean(options.watch),
298
+ readonly: true,
299
+ openedUi: openResult.opened,
300
+ openMode: openResult.mode
301
+ }, () => `Brainlink graph server running at ${server.url}${openResult.opened
302
+ ? openResult.mode === 'app-window'
303
+ ? ' (opened in dedicated app window)'
304
+ : ' (opened in browser)'
305
+ : options.open === false
306
+ ? ' (auto-open disabled)'
307
+ : ''}`);
258
308
  });
259
309
  program
260
310
  .command('quickstart')
@@ -540,7 +540,8 @@ blink server --vault ./vault --host 127.0.0.1 --port 4321 --no-open
540
540
  ```
541
541
 
542
542
  This starts a local frontend for inspecting the knowledge graph.
543
- By default it opens the graph URL in your default browser. Use `--no-open` to keep the server headless.
543
+ By default it tries to open the graph in a dedicated app window and falls back to the default browser when app-window mode is unavailable.
544
+ Use `--no-open` to keep the server headless.
544
545
 
545
546
  Without `--vault`, the graph UI serves `$HOME/.brainlink/vault`.
546
547
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.32",
3
+ "version": "0.1.0-beta.33",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",