note-connector 0.1.0 → 0.2.1

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/bin.js CHANGED
@@ -12,7 +12,7 @@ const program = new Command();
12
12
  program.name("note-connector").description("ChatGPT connector for note.com").version(APP_VERSION);
13
13
  program
14
14
  .command("start", { isDefault: true })
15
- .description("Start note-connector in background (MCP + tunnel); terminal can close after setup")
15
+ .description("ChatGPT Connector: install deps (uv, repo, Playwright) and start in background")
16
16
  .option("--no-tunnel", "Do not start a public tunnel")
17
17
  .option("-p, --port <number>", "Local port", (v) => parseInt(v, 10))
18
18
  .option("--no-open", "Do not open ChatGPT / note.com in the browser")
@@ -1,2 +1,2 @@
1
- import { type StartOptions } from "./runtime.js";
1
+ import type { StartOptions } from "./runtime.js";
2
2
  export declare function runDaemonWorker(opts: StartOptions, logFile: string): Promise<void>;
@@ -10,7 +10,6 @@ import { resolveGatewayPort } from "./net.js";
10
10
  import { isNoteAuthenticated, startNoteLoginInBackground } from "./note-auth.js";
11
11
  import { TunnelManager } from "./tunnel/manager.js";
12
12
  import { saveRuntime, cliPidPath, loadLastMcpAccess } from "./daemon-state.js";
13
- import { ensureInitialized } from "./runtime.js";
14
13
  async function verifyHealth(port) {
15
14
  try {
16
15
  const res = await fetch(`http://127.0.0.1:${port}/healthz`, { signal: AbortSignal.timeout(5000) });
@@ -36,7 +35,6 @@ function watchFirstChatGptAccess(sinceIso, logFile) {
36
35
  setInterval(tick, 2000);
37
36
  }
38
37
  export async function runDaemonWorker(opts, logFile) {
39
- await ensureInitialized();
40
38
  const startedAt = new Date().toISOString();
41
39
  fs.writeFileSync(cliPidPath(), String(process.pid));
42
40
  const config = loadConfig();
package/dist/paths.js CHANGED
@@ -27,6 +27,10 @@ export function resolveNoteConnectorRepo() {
27
27
  /* ignore */
28
28
  }
29
29
  }
30
+ const defaultRepo = path.join(configDir(), "repo");
31
+ if (fs.existsSync(path.join(defaultRepo, "src", "note_mcp"))) {
32
+ return defaultRepo;
33
+ }
30
34
  const here = path.dirname(fileURLToPath(import.meta.url));
31
35
  const fromDevLayout = path.resolve(here, "..", "..");
32
36
  if (fs.existsSync(path.join(fromDevLayout, "src", "note_mcp"))) {
@@ -37,9 +41,9 @@ export function resolveNoteConnectorRepo() {
37
41
  return fromGlobal;
38
42
  }
39
43
  throw new Error("note-connector Python 本体が見つかりません。\n"
40
- + " git clone https://github.com/drillan/note-mcp.git\n"
41
44
  + " note-connector config set repoPath /path/to/note-connector\n"
42
- + "または NOTE_CONNECTOR_REPO=/path/to/note-connector を設定してください。");
45
+ + "または NOTE_CONNECTOR_REPO=/path/to/note-connector を設定してください。\n"
46
+ + "git clone https://github.com/yuga-hashimoto/note-connector.git");
43
47
  }
44
48
  /** @deprecated use resolveNoteConnectorRepo */
45
49
  export function repoRootFromPackage() {
package/dist/runtime.d.ts CHANGED
@@ -5,8 +5,6 @@ export interface StartOptions {
5
5
  noClipboard?: boolean;
6
6
  skipNoteLogin?: boolean;
7
7
  }
8
- /** Create config + token + optional Tailscale domain (runs on every start, idempotent). */
9
- export declare function ensureInitialized(): Promise<void>;
10
8
  /** @deprecated Use `note-connector` or `note-connector start` */
11
9
  export declare function runSetup(): Promise<void>;
12
10
  export declare function runStart(opts: StartOptions): Promise<void>;
package/dist/runtime.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { buildMcpEndpoint, loadConfig, loadOrCreateToken, saveConfig } from "./config.js";
4
- import { ensureConfigDir, configDir } from "./paths.js";
4
+ import { configDir } from "./paths.js";
5
5
  import { startPythonServer } from "./spawn-python.js";
6
6
  import { resolveGatewayPort } from "./net.js";
7
7
  import { discoverTailscaleFqdn } from "./tunnel/tailscale.js";
8
8
  import { runOnboarding } from "./onboarding.js";
9
9
  import { isNoteAuthenticated, startNoteLoginInBackground } from "./note-auth.js";
10
10
  import { spawnDaemon } from "./daemon.js";
11
+ import { setupDependencies } from "./setup-dependencies.js";
11
12
  import { TunnelManager } from "./tunnel/manager.js";
12
13
  async function verifyHealth(port) {
13
14
  try {
@@ -18,40 +19,45 @@ async function verifyHealth(port) {
18
19
  return false;
19
20
  }
20
21
  }
21
- /** Create config + token + optional Tailscale domain (runs on every start, idempotent). */
22
- export async function ensureInitialized() {
23
- const firstRun = !fs.existsSync(path.join(configDir(), "config.json"));
24
- ensureConfigDir();
25
- let config = loadConfig();
26
- const fqdn = discoverTailscaleFqdn();
27
- if (fqdn && !config.tunnel.domain) {
28
- config = { ...config, tunnel: { ...config.tunnel, domain: fqdn } };
29
- saveConfig(config);
30
- if (firstRun) {
31
- console.log(`Tailscale FQDN saved: ${fqdn}`);
32
- }
33
- }
34
- else {
35
- saveConfig(config);
36
- }
37
- loadOrCreateToken();
38
- if (firstRun) {
39
- console.log(`Ready (~/.note-connector). Starting…`);
40
- }
41
- }
42
22
  /** @deprecated Use `note-connector` or `note-connector start` */
43
23
  export async function runSetup() {
44
- await ensureInitialized();
45
24
  console.log("Setup is included in start. Just run: note-connector");
46
25
  }
47
26
  export async function runStart(opts) {
48
- await ensureInitialized();
27
+ console.log("note-connector — ChatGPT Connector セットアップ中…");
28
+ const report = await setupDependencies();
29
+ for (const w of report.warnings) {
30
+ console.warn(`⚠ ${w}`);
31
+ }
32
+ loadOrCreateToken();
33
+ const fqdn = discoverTailscaleFqdn();
34
+ if (fqdn) {
35
+ const config = loadConfig();
36
+ if (!config.tunnel.domain) {
37
+ saveConfig({ ...config, tunnel: { ...config.tunnel, domain: fqdn } });
38
+ console.log(`Tailscale FQDN: ${fqdn}`);
39
+ }
40
+ }
41
+ console.log("依存関係の準備が完了しました。");
49
42
  await spawnDaemon(opts);
50
- return;
51
43
  }
52
44
  /** Foreground mode (debug): keep terminal attached. */
53
45
  export async function runStartForeground(opts) {
54
- await ensureInitialized();
46
+ console.log("note-connector — ChatGPT Connector セットアップ中…");
47
+ const report = await setupDependencies();
48
+ for (const w of report.warnings) {
49
+ console.warn(`⚠ ${w}`);
50
+ }
51
+ loadOrCreateToken();
52
+ const fqdn = discoverTailscaleFqdn();
53
+ if (fqdn) {
54
+ const config = loadConfig();
55
+ if (!config.tunnel.domain) {
56
+ saveConfig({ ...config, tunnel: { ...config.tunnel, domain: fqdn } });
57
+ console.log(`Tailscale FQDN: ${fqdn}`);
58
+ }
59
+ }
60
+ console.log("依存関係の準備が完了しました。");
55
61
  const config = loadConfig();
56
62
  const preferred = opts.port ?? config.gatewayPort;
57
63
  let port;
@@ -0,0 +1,8 @@
1
+ export interface SetupReport {
2
+ uvInstalled: boolean;
3
+ repoReady: boolean;
4
+ pythonDepsReady: boolean;
5
+ playwrightReady: boolean;
6
+ warnings: string[];
7
+ }
8
+ export declare function setupDependencies(): Promise<SetupReport>;
@@ -0,0 +1,105 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { loadConfig, saveConfig } from "./config.js";
5
+ import { configDir, resolveNoteConnectorRepo } from "./paths.js";
6
+ const DEFAULT_REPO = "https://github.com/yuga-hashimoto/note-connector.git";
7
+ const MIN_NODE_MAJOR = 20;
8
+ function commandExists(cmd) {
9
+ try {
10
+ execFileSync("command", ["-v", cmd], { stdio: "ignore" });
11
+ return true;
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
17
+ function installUvUnix() {
18
+ console.log("Installing uv (Python toolchain)…");
19
+ execFileSync("sh", ["-c", "curl -LsSf https://astral.sh/uv/install.sh | sh"], { stdio: "inherit", env: { ...process.env, CARGO_HOME: process.env.CARGO_HOME } });
20
+ const home = process.env.HOME ?? "";
21
+ const cargoBin = path.join(home, ".cargo", "bin");
22
+ const localBin = path.join(home, ".local", "bin");
23
+ const pathEnv = process.env.PATH ?? "";
24
+ if (!pathEnv.includes(cargoBin)) {
25
+ process.env.PATH = `${cargoBin}:${localBin}:${pathEnv}`;
26
+ }
27
+ }
28
+ function ensureUv() {
29
+ if (commandExists("uv"))
30
+ return;
31
+ if (process.platform === "win32") {
32
+ throw new Error("uv が見つかりません。https://docs.astral.sh/uv/ からインストールしてください。");
33
+ }
34
+ installUvUnix();
35
+ if (!commandExists("uv")) {
36
+ throw new Error("uv のインストールに失敗しました。PATH に ~/.local/bin または ~/.cargo/bin を追加してください。");
37
+ }
38
+ }
39
+ function repoHasPython(root) {
40
+ return fs.existsSync(path.join(root, "pyproject.toml")) && fs.existsSync(path.join(root, "src", "note_mcp"));
41
+ }
42
+ function cloneRepo(target) {
43
+ console.log(`Cloning note-connector → ${target}`);
44
+ fs.mkdirSync(path.dirname(target), { recursive: true });
45
+ execFileSync("git", ["clone", "--depth", "1", DEFAULT_REPO, target], { stdio: "inherit" });
46
+ }
47
+ function ensureRepoPath(config) {
48
+ if (config.repoPath && repoHasPython(config.repoPath)) {
49
+ return path.resolve(config.repoPath);
50
+ }
51
+ try {
52
+ return resolveNoteConnectorRepo();
53
+ }
54
+ catch {
55
+ /* fall through */
56
+ }
57
+ const target = path.join(configDir(), "repo");
58
+ if (!repoHasPython(target)) {
59
+ if (fs.existsSync(target)) {
60
+ throw new Error(`Incomplete repo at ${target}. Remove it or set repoPath.`);
61
+ }
62
+ cloneRepo(target);
63
+ }
64
+ const updated = { ...config, repoPath: target };
65
+ saveConfig(updated);
66
+ process.env.NOTE_CONNECTOR_REPO = target;
67
+ return target;
68
+ }
69
+ function runUvSync(repo) {
70
+ console.log("Installing Python dependencies (uv sync)…");
71
+ execFileSync("uv", ["sync"], { cwd: repo, stdio: "inherit", env: process.env });
72
+ }
73
+ function ensurePlaywright(repo) {
74
+ console.log("Installing Playwright Chromium (初回のみ時間がかかります)…");
75
+ execFileSync("uv", ["run", "playwright", "install", "chromium"], {
76
+ cwd: repo,
77
+ stdio: "inherit",
78
+ env: process.env,
79
+ });
80
+ }
81
+ function ensureNodeVersion() {
82
+ const major = parseInt(process.versions.node.split(".")[0] ?? "0", 10);
83
+ if (major < MIN_NODE_MAJOR) {
84
+ throw new Error(`Node.js ${MIN_NODE_MAJOR}+ が必要です(現在: ${process.versions.node})`);
85
+ }
86
+ }
87
+ export async function setupDependencies() {
88
+ const warnings = [];
89
+ ensureNodeVersion();
90
+ const config = loadConfig();
91
+ ensureUv();
92
+ const repo = ensureRepoPath(config);
93
+ runUvSync(repo);
94
+ ensurePlaywright(repo);
95
+ if (!commandExists("tailscale") && config.tunnel.provider === "tailscale" && !config.tunnel.publicUrl) {
96
+ warnings.push("Tailscale CLI がありません。tunnel.publicUrl を設定するか Tailscale をインストールしてください。");
97
+ }
98
+ return {
99
+ uvInstalled: true,
100
+ repoReady: true,
101
+ pythonDepsReady: true,
102
+ playwrightReady: true,
103
+ warnings,
104
+ };
105
+ }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "note-connector",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "description": "note-connector \u2014 ChatGPT connector for note.com (MCP + Apps SDK UI)",
7
+ "description": "ChatGPT Connector for note.com MCP server with Apps SDK UI. One command setup: uv, Playwright, tunnel.",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "bin": {
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "repository": {
41
41
  "type": "git",
42
- "url": "git+https://github.com/drillan/note-mcp.git"
42
+ "url": "git+https://github.com/yuga-hashimoto/note-connector.git"
43
43
  },
44
- "homepage": "https://github.com/drillan/note-mcp#readme"
44
+ "homepage": "https://github.com/yuga-hashimoto/note-connector#readme"
45
45
  }