@lnar/cli 0.0.1-dev.f1de48c → 0.0.1-dev.f1f5888
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/dist/browser.d.ts +1 -0
- package/dist/browser.js +68 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +19 -9
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/up.js +19 -0
- package/dist/commands/up.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const openBrowser: (url: string) => boolean;
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OS のデフォルトブラウザで URL を開く。
|
|
3
|
+
*
|
|
4
|
+
* 依存を増やさず、プラットフォームごとの組み込みコマンドを spawn する。
|
|
5
|
+
* macOS → `open -- <url>`
|
|
6
|
+
* Linux → `xdg-open -- <url>`
|
|
7
|
+
* Windows → `rundll32 url.dll,FileProtocolHandler <url>`
|
|
8
|
+
*
|
|
9
|
+
* セキュリティ:
|
|
10
|
+
* - URL は http / https スキームのみ許可(javascript:, file: 等は拒否)
|
|
11
|
+
* - macOS / Linux では `--` セパレータで先頭が `-` の URL をフラグと誤認させない
|
|
12
|
+
* - Windows は cmd.exe メタ文字解釈を避けるため `rundll32 url.dll,FileProtocolHandler`
|
|
13
|
+
* を使用(cmd /c start 経由は `&` 等で injection 余地が残る)
|
|
14
|
+
*
|
|
15
|
+
* CI / SSH / コンテナ等の "browser を出せない" 環境では子プロセスが失敗するが、
|
|
16
|
+
* 呼び出し側で URL を必ず stdout に表示するフォールバックを残すため、ここでは
|
|
17
|
+
* 例外を握り潰して boolean で結果だけ返す。
|
|
18
|
+
*
|
|
19
|
+
* 強制無効化: `LNAR_NO_BROWSER=1` を export しておくと自動オープンを抑止する。
|
|
20
|
+
*/
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
import { platform } from 'node:os';
|
|
23
|
+
const isSafeHttpUrl = (url) => {
|
|
24
|
+
try {
|
|
25
|
+
const parsed = new URL(url);
|
|
26
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const resolveOpenCommand = (url) => {
|
|
33
|
+
const os = platform();
|
|
34
|
+
if (os === 'darwin') {
|
|
35
|
+
// `--` で URL がフラグ扱いされないようにする
|
|
36
|
+
return { command: 'open', args: ['--', url] };
|
|
37
|
+
}
|
|
38
|
+
if (os === 'win32') {
|
|
39
|
+
// cmd.exe を経由しないことで `&`, `|` 等のメタ文字解釈を回避
|
|
40
|
+
return { command: 'rundll32', args: ['url.dll,FileProtocolHandler', url] };
|
|
41
|
+
}
|
|
42
|
+
return { command: 'xdg-open', args: ['--', url] };
|
|
43
|
+
};
|
|
44
|
+
export const openBrowser = (url) => {
|
|
45
|
+
if (process.env.LNAR_NO_BROWSER === '1') {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (!isSafeHttpUrl(url)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const { command, args } = resolveOpenCommand(url);
|
|
52
|
+
try {
|
|
53
|
+
const child = spawn(command, args, {
|
|
54
|
+
detached: true,
|
|
55
|
+
stdio: 'ignore',
|
|
56
|
+
});
|
|
57
|
+
// spawn 自体が失敗 (コマンドが PATH に無い等) しても unhandled error にしない。
|
|
58
|
+
child.on('error', () => {
|
|
59
|
+
/* swallow — フォールバックは呼び出し側の stdout に任せる */
|
|
60
|
+
});
|
|
61
|
+
child.unref();
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAOnC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAW,EAAE;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,GAAW,EAAe,EAAE;IACtD,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpB,6BAA6B;QAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;IAChD,CAAC;IACD,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,yCAAyC;QACzC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,6BAA6B,EAAE,GAAG,CAAC,EAAE,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAW,EAAW,EAAE;IAClD,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,GAAG,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QACH,0DAA0D;QAC1D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACrB,0CAA0C;QAC5C,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -23,10 +23,13 @@ program
|
|
|
23
23
|
.description('Authenticate (if needed) and install lnar as a background service that runs forever.')
|
|
24
24
|
.option('--api-base-url <url>', 'lnar API base URL')
|
|
25
25
|
.option('--client-id <id>', 'OAuth client_id (default: lnar-cli)')
|
|
26
|
+
.option('--no-browser', 'Do not open the authorization URL in a browser automatically')
|
|
26
27
|
.action(async (opts) => {
|
|
27
28
|
await runUp({
|
|
28
29
|
apiBaseUrl: opts.apiBaseUrl,
|
|
29
30
|
clientId: opts.clientId,
|
|
31
|
+
// commander の --no-X は opts.browser=false で渡る
|
|
32
|
+
noBrowser: opts.browser === false,
|
|
30
33
|
});
|
|
31
34
|
});
|
|
32
35
|
program
|
|
@@ -49,10 +52,12 @@ program
|
|
|
49
52
|
.description('Re-authorize this device via the OAuth Device Code flow (normally not needed — `lnar up` handles login).')
|
|
50
53
|
.option('--api-base-url <url>', 'lnar API base URL')
|
|
51
54
|
.option('--client-id <id>', 'OAuth client_id (default: lnar-cli)')
|
|
55
|
+
.option('--no-browser', 'Do not open the authorization URL in a browser automatically')
|
|
52
56
|
.action(async (opts) => {
|
|
53
57
|
await runLogin({
|
|
54
58
|
apiBaseUrl: opts.apiBaseUrl,
|
|
55
59
|
clientId: opts.clientId,
|
|
60
|
+
noBrowser: opts.browser === false,
|
|
56
61
|
});
|
|
57
62
|
});
|
|
58
63
|
program
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/login.d.ts
CHANGED
|
@@ -2,5 +2,7 @@ export type LoginOptions = {
|
|
|
2
2
|
apiBaseUrl?: string;
|
|
3
3
|
clientId?: string;
|
|
4
4
|
scopes?: ReadonlyArray<string>;
|
|
5
|
+
/** true なら認可 URL を自動でブラウザに開かない (env `LNAR_NO_BROWSER=1` 相当)。 */
|
|
6
|
+
noBrowser?: boolean;
|
|
5
7
|
};
|
|
6
8
|
export declare const runLogin: (options?: LoginOptions) => Promise<void>;
|
package/dist/commands/login.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { openBrowser } from '../browser.js';
|
|
1
2
|
import { DEFAULT_API_BASE_URL, DEFAULT_CLIENT_ID, saveConfig } from '../config.js';
|
|
2
|
-
import { OAuthError, pollForToken, requestDeviceAuthorization, sleep
|
|
3
|
+
import { OAuthError, pollForToken, requestDeviceAuthorization, sleep } from '../oauth-client.js';
|
|
3
4
|
const DEFAULT_SCOPES = ['monitoring:read', 'monitoring:write'];
|
|
4
5
|
const resolveBaseUrl = (override) => {
|
|
5
6
|
const value = override ?? process.env.LNAR_API_BASE_URL ?? DEFAULT_API_BASE_URL;
|
|
@@ -11,15 +12,22 @@ const resolveBaseUrl = (override) => {
|
|
|
11
12
|
}
|
|
12
13
|
return value;
|
|
13
14
|
};
|
|
14
|
-
const printAuthorizationInstructions = (verificationUri, verificationUriComplete, userCode, expiresInSeconds) => {
|
|
15
|
+
const printAuthorizationInstructions = (verificationUri, verificationUriComplete, userCode, expiresInSeconds, browserOpened) => {
|
|
15
16
|
const minutes = Math.max(1, Math.round(expiresInSeconds / 60));
|
|
16
17
|
process.stdout.write('\n');
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
if (browserOpened) {
|
|
19
|
+
process.stdout.write('Opening your browser to authorize this device…\n');
|
|
20
|
+
process.stdout.write('If it does not open automatically, visit:\n');
|
|
21
|
+
process.stdout.write(` ${verificationUriComplete}\n\n`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
process.stdout.write('To authorize this device, visit:\n');
|
|
25
|
+
process.stdout.write(` ${verificationUri}\n`);
|
|
26
|
+
process.stdout.write('and enter the code:\n\n');
|
|
27
|
+
process.stdout.write(` ${userCode}\n\n`);
|
|
28
|
+
process.stdout.write('Or open the URL with the code pre-filled:\n');
|
|
29
|
+
process.stdout.write(` ${verificationUriComplete}\n\n`);
|
|
30
|
+
}
|
|
23
31
|
process.stdout.write(`Waiting for authorization (this code expires in ${minutes} minute${minutes === 1 ? '' : 's'})…\n`);
|
|
24
32
|
};
|
|
25
33
|
export const runLogin = async (options = {}) => {
|
|
@@ -37,7 +45,9 @@ export const runLogin = async (options = {}) => {
|
|
|
37
45
|
}
|
|
38
46
|
throw err;
|
|
39
47
|
}
|
|
40
|
-
|
|
48
|
+
const shouldOpenBrowser = !(options.noBrowser ?? process.env.LNAR_NO_BROWSER === '1');
|
|
49
|
+
const browserOpened = shouldOpenBrowser && openBrowser(auth.verification_uri_complete);
|
|
50
|
+
printAuthorizationInstructions(auth.verification_uri, auth.verification_uri_complete, auth.user_code, auth.expires_in, browserOpened);
|
|
41
51
|
// RFC 8628 §3.5: ポーリング間隔はサーバ指定の `interval` 以上、
|
|
42
52
|
// `slow_down` を受け取ったら +5 秒 (サーバ側で自動加算済みだが、念のためここでも対応)。
|
|
43
53
|
let intervalSeconds = Math.max(1, auth.interval || 5);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/up.js
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 1. `~/.config/lnar/auth.json` を読んで、認証済みでなければ device flow を起動する
|
|
5
5
|
* 2. OS の常駐サービスとして登録 (macOS=launchd / Linux=systemd / Windows=Task Scheduler)
|
|
6
|
+
* 3. インストール直後に初回 sync を 1 回だけ同期実行し、daemon の最初の cycle を
|
|
7
|
+
* 待たずダッシュボードへの反映を即時化する。Tailscale が `tailscale up` で
|
|
8
|
+
* 同期的に "phone home" するのと同じ思想。失敗しても daemon 側 polling が
|
|
9
|
+
* 後続 cycle で再試行するので、ここはベストエフォート扱いにする。
|
|
6
10
|
*
|
|
7
11
|
* 認証済みかどうかは「資格情報ファイルが存在し、accessToken or apiKey が入っているか」で
|
|
8
12
|
* 判断する。トークンの有効期限は daemon 側の API クライアントが refresh するので、
|
|
@@ -12,6 +16,20 @@
|
|
|
12
16
|
import { loadConfig } from '../config.js';
|
|
13
17
|
import { runDaemonInstall } from '../service/install.js';
|
|
14
18
|
import { runLogin } from './login.js';
|
|
19
|
+
import { runSync } from './sync.js';
|
|
20
|
+
const runInitialSync = async () => {
|
|
21
|
+
process.stdout.write('\nRunning initial sync…\n');
|
|
22
|
+
try {
|
|
23
|
+
await runSync();
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
// runSync は ApiError / 401 では process.exit(1) を直接呼ぶので、ここに到達する
|
|
27
|
+
// のは予期しない例外のみ。daemon サービスのインストール自体は成功しているので、
|
|
28
|
+
// 続く polling cycle が同じ scan を再試行できる。lnar up 自体は warn で済ませる。
|
|
29
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
30
|
+
process.stderr.write(`lnar up: initial sync failed (${message}). The daemon will retry on its next cycle.\n`);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
15
33
|
export const runUp = async (options = {}) => {
|
|
16
34
|
const config = await loadConfig();
|
|
17
35
|
if (config == null) {
|
|
@@ -23,5 +41,6 @@ export const runUp = async (options = {}) => {
|
|
|
23
41
|
process.stdout.write(`Using existing credentials (${config.apiBaseUrl}).\n\n`);
|
|
24
42
|
}
|
|
25
43
|
await runDaemonInstall();
|
|
44
|
+
await runInitialSync();
|
|
26
45
|
};
|
|
27
46
|
//# sourceMappingURL=up.js.map
|
package/dist/commands/up.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"up.js","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"up.js","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAqB,QAAQ,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,cAAc,GAAG,KAAK,IAAmB,EAAE;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,8DAA8D;QAC9D,6CAA6C;QAC7C,4DAA4D;QAC5D,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,iCAAiC,OAAO,+CAA+C,CACxF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,UAAqB,EAAE,EAAiB,EAAE;IACpE,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACxF,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,MAAM,CAAC,UAAU,QAAQ,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lnar/cli",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.f1f5888",
|
|
4
4
|
"description": "Lnar CLI — scans local AI agents (Claude / Claude Code, Codex CLI, Cursor, Gemini CLI, ChatGPT) for connected MCP servers and reports them to your lnar account.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|