@minimalcorp/tsunagi 0.1.42 → 0.1.44

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.
Files changed (76) hide show
  1. package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  2. package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
  3. package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
  5. package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
  6. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
  12. package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +1 -1
  13. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  14. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  15. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  16. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  17. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  18. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  19. package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
  20. package/.next/standalone/apps/web/.next/server/app/index.rsc +1 -1
  21. package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  22. package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
  23. package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  24. package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  25. package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  26. package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
  27. package/.next/standalone/apps/web/.next/server/app/settings.rsc +1 -1
  28. package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  29. package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  30. package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  31. package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  32. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  33. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  34. package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
  35. package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
  36. package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  37. package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
  38. package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
  39. package/LICENSE +126 -0
  40. package/README.md +154 -0
  41. package/dist/auto-migrate.js +5 -1
  42. package/dist/cli.js +12 -5
  43. package/dist/server/lib/llm-process.js +8 -7
  44. package/dist/server/lib/whisper-process.js +8 -7
  45. package/dist/server/routes/terminal.js +6 -2
  46. package/npm-shrinkwrap.json +199 -21
  47. package/package.json +3 -9
  48. /package/.next/standalone/apps/web/.next/static/{BNKOxgPR4vrQI79IAwnsk → b89JVAeQs5UYaMHr5WMOT}/_buildManifest.js +0 -0
  49. /package/.next/standalone/apps/web/.next/static/{BNKOxgPR4vrQI79IAwnsk → b89JVAeQs5UYaMHr5WMOT}/_clientMiddlewareManifest.js +0 -0
  50. /package/.next/standalone/apps/web/.next/static/{BNKOxgPR4vrQI79IAwnsk → b89JVAeQs5UYaMHr5WMOT}/_ssgManifest.js +0 -0
  51. /package/{llm-server → dist/llm-server}/README.md +0 -0
  52. /package/{llm-server → dist/llm-server}/download_model.py +0 -0
  53. /package/{llm-server → dist/llm-server}/requirements.txt +0 -0
  54. /package/{llm-server → dist/llm-server}/run.sh +0 -0
  55. /package/{prisma → dist/prisma}/migrations/20260129030443_init/migration.sql +0 -0
  56. /package/{prisma → dist/prisma}/migrations/20260130140855_add_task_planning_fields_and_base_branch/migration.sql +0 -0
  57. /package/{prisma → dist/prisma}/migrations/20260130163529_add_base_branch_commit/migration.sql +0 -0
  58. /package/{prisma → dist/prisma}/migrations/20260131171847_remove_completed_at/migration.sql +0 -0
  59. /package/{prisma → dist/prisma}/migrations/20260328000000_remove_sdk_dead_code/migration.sql +0 -0
  60. /package/{prisma → dist/prisma}/migrations/20260329000000_add_todos_and_planner_tabs/migration.sql +0 -0
  61. /package/{prisma → dist/prisma}/migrations/20260410000000_clear_stale_tab_todos/migration.sql +0 -0
  62. /package/{prisma → dist/prisma}/migrations/20260413000000_make_task_order_non_nullable/migration.sql +0 -0
  63. /package/{prisma → dist/prisma}/migrations/20260629000000_add_tab_mode/migration.sql +0 -0
  64. /package/{prisma → dist/prisma}/migrations/20260915000000_drop_planner_tabs/migration.sql +0 -0
  65. /package/{prisma → dist/prisma}/migrations/20260916000000_add_repository_order/migration.sql +0 -0
  66. /package/{prisma → dist/prisma}/migrations/20260918000000_add_tab_unread/migration.sql +0 -0
  67. /package/{prisma → dist/prisma}/migrations/20260924000000_add_app_settings/migration.sql +0 -0
  68. /package/{prisma → dist/prisma}/migrations/migration_lock.toml +0 -0
  69. /package/{prisma → dist/prisma}/schema.prisma +0 -0
  70. /package/{prisma.config.ts → dist/prisma.config.ts} +0 -0
  71. /package/{scripts → dist/scripts}/monaco-editor.sh +0 -0
  72. /package/{whisper-server → dist/whisper-server}/README.md +0 -0
  73. /package/{whisper-server → dist/whisper-server}/download_model.py +0 -0
  74. /package/{whisper-server → dist/whisper-server}/requirements.txt +0 -0
  75. /package/{whisper-server → dist/whisper-server}/run.sh +0 -0
  76. /package/{whisper-server → dist/whisper-server}/server.py +0 -0
package/LICENSE ADDED
@@ -0,0 +1,126 @@
1
+ # PolyForm Shield License 1.0.0
2
+
3
+ <https://polyformproject.org/licenses/shield/1.0.0>
4
+
5
+ ## Acceptance
6
+
7
+ In order to get any license under these terms, you must agree
8
+ to them as both strict obligations and conditions to all
9
+ your licenses.
10
+
11
+ ## Copyright License
12
+
13
+ The licensor grants you a copyright license for the
14
+ software to do everything you might do with the software
15
+ that would otherwise infringe the licensor's copyright
16
+ in it for any permitted purpose. However, you may
17
+ only distribute the software according to [Distribution
18
+ License](#distribution-license) and make changes or new works
19
+ based on the software according to [Changes and New Works
20
+ License](#changes-and-new-works-license).
21
+
22
+ ## Distribution License
23
+
24
+ The licensor grants you an additional copyright license
25
+ to distribute copies of the software. Your license
26
+ to distribute covers distributing the software with
27
+ changes and new works permitted by [Changes and New Works
28
+ License](#changes-and-new-works-license).
29
+
30
+ ## Notices
31
+
32
+ You must ensure that anyone who gets a copy of any part of
33
+ the software from you also gets a copy of these terms, as well
34
+ as the following copyright notice:
35
+
36
+ > Copyright 2026 minimalcorp
37
+
38
+ ## Changes and New Works License
39
+
40
+ The licensor grants you the copyright licenses in
41
+ [Copyright License](#copyright-license) for changes and
42
+ new works based on the software subject to this license.
43
+
44
+ ## Patent License
45
+
46
+ The licensor grants you a patent license for the software that
47
+ covers patent claims the licensor can license, or becomes able
48
+ to license, that you would infringe by using the software.
49
+
50
+ ## Noncompete
51
+
52
+ Any purpose is a permitted purpose, except for providing to others
53
+ any product that competes with the software.
54
+
55
+ If you use this software to market a product as a substitute for
56
+ the functionality or value of the software, it competes with the
57
+ software. A product may use this software for testing, staging,
58
+ or deploying the product, without necessarily competing with the
59
+ software, even if the product provides some of the same features
60
+ as the software.
61
+
62
+ ## Competition Conditions
63
+
64
+ If you use the software to provide a product that competes with
65
+ the software, that use is not allowed under the licenses granted
66
+ by these terms.
67
+
68
+ ## Fair Use
69
+
70
+ You may have "fair use" rights for the software under the
71
+ law. These terms do not limit them.
72
+
73
+ ## No Other Rights
74
+
75
+ These terms do not allow you to sublicense or transfer any of
76
+ your licenses to anyone else, or prevent the licensor from
77
+ granting licenses to anyone else. These terms do not imply
78
+ any other licenses.
79
+
80
+ ## Patent Defense
81
+
82
+ If you make any written claim that the software infringes or
83
+ contributes to infringement of any patent, your patent license
84
+ for the software granted under these terms ends immediately. If
85
+ your company makes such a claim, your patent license ends
86
+ immediately for work on behalf of your company.
87
+
88
+ ## Violations
89
+
90
+ The first time you are notified in writing that you have
91
+ violated any of these terms, or done anything with the software
92
+ not covered by your licenses, your licenses can nonetheless
93
+ continue if you come into full compliance with these terms,
94
+ and take practical steps to correct past violations, within
95
+ 32 days of receiving notice. Otherwise, all your licenses
96
+ end immediately.
97
+
98
+ ## No Liability
99
+
100
+ ***As far as the law allows, the software comes as is, without
101
+ any warranty or condition, and the licensor will not be liable
102
+ to you for any damages arising out of these terms or the use
103
+ or nature of the software, under any kind of legal claim.***
104
+
105
+ ## Definitions
106
+
107
+ The **licensor** is the individual or entity offering these
108
+ terms, and the **software** is the software the licensor makes
109
+ available under these terms.
110
+
111
+ **You** refers to the individual or entity agreeing to these
112
+ terms.
113
+
114
+ **Your company** is any legal entity, sole proprietorship,
115
+ or other kind of organization that you work for, plus all
116
+ organizations that have control over, are under the control of,
117
+ or are under common control with that organization. **Control**
118
+ means ownership of substantially all the assets of an entity,
119
+ or the power to direct its management and policies by vote,
120
+ contract, or otherwise. Control can be direct or indirect.
121
+
122
+ **Your licenses** are all the licenses granted to you for the
123
+ software under these terms.
124
+
125
+ **Use** means anything you do with the software requiring one
126
+ of your licenses.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # Tsunagi Monorepo
2
+
3
+ **Tsunagi (繋ぎ)** — 複数 GitHub 組織のプロジェクトをローカルで統合管理し、
4
+ Claude AI による AI 駆動開発を可視化・制御する Web UI ツール。
5
+
6
+ このリポジトリは npm workspaces ベースの monorepo です。
7
+
8
+ ## パッケージ
9
+
10
+ | パッケージ | 場所 | npm 公開 | 説明 |
11
+ | ------------------------------------ | ------------ | -------- | ---------------------------------------------------------------- |
12
+ | [`@minimalcorp/tsunagi`](./apps/web) | `apps/web/` | ✅ | Tsunagi 本体 (Next.js + Fastify + Prisma) |
13
+ | [`tsunagi-docs`](./apps/docs) | `apps/docs/` | ❌ | ユーザー向けドキュメントサイト (Nextra, GitHub Pages にデプロイ) |
14
+
15
+ ## クイックスタート(エンドユーザー向け)
16
+
17
+ Tsunagi を使いたいだけの場合は、npm から直接起動できます:
18
+
19
+ ```bash
20
+ npx @minimalcorp/tsunagi
21
+ ```
22
+
23
+ 詳細は [apps/web/README.md](./apps/web/README.md) または
24
+ [ドキュメントサイト](https://minimalcorp.github.io/tsunagi/) を参照してください。
25
+
26
+ ## 開発セットアップ
27
+
28
+ ```bash
29
+ # リポジトリをクローン
30
+ git clone https://github.com/minimalcorp/tsunagi.git
31
+ cd tsunagi
32
+
33
+ # 依存関係インストール(全ワークスペース)
34
+ npm install
35
+
36
+ # Tsunagi 本体を開発モードで起動
37
+ npm run dev
38
+
39
+ # ドキュメントサイトを開発モードで起動
40
+ npm run docs:dev
41
+ ```
42
+
43
+ ## よく使うコマンド(ルートから実行)
44
+
45
+ | コマンド | 説明 |
46
+ | ---------------------- | ------------------------------------------ |
47
+ | `npm run dev` | web + docs を並列起動(Ctrl+C で両方停止) |
48
+ | `npm run web:dev` | Tsunagi 本体のみ開発モードで起動 |
49
+ | `npm run docs:dev` | ドキュメントサイトのみ開発モードで起動 |
50
+ | `npm run build` | 全ワークスペースをビルド |
51
+ | `npm run lint` | 全ワークスペースで ESLint を実行 |
52
+ | `npm run type-check` | 全ワークスペースで TypeScript 型チェック |
53
+ | `npm run format` | Prettier で全ファイルをフォーマット |
54
+ | `npm run format:check` | Prettier でフォーマット差分チェック |
55
+
56
+ ## リリース
57
+
58
+ GitHub Actions の `Release` workflow を手動実行することで、`@minimalcorp/tsunagi`
59
+ の npm 公開、および docs の GitHub Pages デプロイを統合的に行えます:
60
+
61
+ 1. GitHub の Actions タブから `Release` workflow を選択
62
+ 2. 以下を入力して Run:
63
+ - **target**: `all` / `tsunagi` / `docs` のいずれか
64
+ - **version**: `patch` / `minor` / `major` (tsunagi にのみ適用)
65
+
66
+ 詳細は [.github/workflows/release.yml](./.github/workflows/release.yml) を参照。
67
+
68
+ ### 初回実行前の必須セットアップ
69
+
70
+ 初めて `Release` workflow を実行する前に、以下を手動で設定しておく必要があります。
71
+
72
+ 1. **npm Organization 準備**
73
+ - npmjs.com で `@minimalcorp` organization を作成(未作成の場合)
74
+ - `@minimalcorp/tsunagi` パッケージ名が未取得であることを確認
75
+
76
+ 2. **npm Trusted Publisher を事前登録** (npm 側)
77
+ - 本 workflow は **npm Trusted Publishing (OIDC)** を使用するため `NPM_TOKEN` は不要
78
+ - npmjs.com で Trusted Publisher を追加: organization=`minimalcorp`, repository=`tsunagi`, workflow=`release.yml`, environment=`production-release`
79
+ - パッケージがまだ存在しない段階でも "Pending Trusted Publisher" として事前登録可能
80
+
81
+ 3. **GitHub Pages を Actions ソースに設定**
82
+ - Settings → Pages → Source: `GitHub Actions` を選択(`Deploy from a branch` ではない)
83
+
84
+ 4. **`production-release` Environment の作成と承認者設定**(必須)
85
+ - Settings → Environments → `New environment` → 名前を `production-release` として作成
86
+ - **Required reviewers** を有効化し、リリース承認権限を持つメンバー(自分自身でも可)を追加
87
+ - Release workflow の `approve` job はこの Environment 配下で実行されるため、
88
+ workflow 実行時に GitHub UI で明示的な承認操作が必要になる
89
+ - `publish-tsunagi` / `deploy-docs` 両方がこの approval を通過した後でのみ実行される
90
+ - 承認画面で main の最新状態(他 PR の merge 状況等)を目視確認してから承認する
91
+ ことで、意図しない内容のリリースを防ぐ
92
+
93
+ 5. **`main` ブランチ保護の bypass 設定**(保護ルールを設定している場合)
94
+ - `Release` workflow は `npm version` で bump した commit と tag を `main` に直接 push する
95
+ - main に `Require a pull request before merging` 等の保護ルールがある場合、push がブロックされる
96
+ - `github-actions[bot]` は user role を持たないため、Bypass list に**明示的に**以下のいずれかを設定する必要がある:
97
+ - 独立した **Deploy key** を発行し Bypass に追加(推奨)
98
+ - 管理者ユーザーの **PAT** を `PAT_TOKEN` secret として登録し、workflow の `checkout` で使用
99
+ - 管理者ユーザー自身を Bypass に追加(workflow を本人が起動する運用)
100
+ - 保護ルールを main に設定していない場合は不要
101
+
102
+ これらを設定せずに workflow を実行すると、途中で失敗してバージョン番号だけが bump された中途半端な状態になる可能性があるので、**必ず事前に設定してください**。
103
+
104
+ ### リリース中の concurrent push について
105
+
106
+ Release workflow には以下の保護機構が組み込まれています:
107
+
108
+ - **同時実行の排他制御**: `concurrency: release` group により、2つ目の Release workflow は1つ目の完了を待機します
109
+ - **Push retry with rebase**: workflow の checkout から push までの間に別の PR が main に merge された場合でも、自動で rebase してから retry します(最大3回)。rebase により merge 済みの内容を取り込んだ上で version bump commit を再適用するため、npm publish は最新の main 状態で行われます
110
+ - **Environment 承認ゲート**: 人間が承認するタイミングで main の状態を目視確認できるため、意図しない内容のリリースを事前に察知できます
111
+
112
+ ## リポジトリ構成
113
+
114
+ ```
115
+ tsunagi/
116
+ ├── apps/
117
+ │ ├── web/ # @minimalcorp/tsunagi (Tsunagi 本体)
118
+ │ └── docs/ # tsunagi-docs (Nextra ドキュメントサイト)
119
+ ├── .github/workflows/
120
+ │ ├── ci.yml # PR CI (format / lint / type-check / build)
121
+ │ ├── release.yml # 統合リリース (npm publish + Pages deploy)
122
+ │ └── cla.yml # CLA Assistant bot
123
+ ├── .husky/ # Git hooks
124
+ ├── package.json # monorepo root (workspaces)
125
+ ├── .prettierrc.json # monorepo 共通 Prettier 設定
126
+ ├── LICENSE # PolyForm Shield 1.0.0
127
+ ├── CLA.md # Contributor License Agreement
128
+ ├── CONTRIBUTING.md # コントリビューションガイド
129
+ └── CLAUDE.md # Claude AI 向け作業ルール
130
+ ```
131
+
132
+ ## 対応 OS
133
+
134
+ - macOS
135
+ - Linux
136
+ - Windows は**非サポート**(WSL2 経由で動作する可能性はありますが保証されません)
137
+
138
+ ## 必須ランタイム
139
+
140
+ - **Node.js ≥ 20**
141
+ - **Git ≥ 2.42**(空リポジトリを扱うため `git worktree add --orphan` を使用)
142
+ - **Claude Code CLI**(`claude` コマンドが PATH 上に必要)
143
+
144
+ ## ライセンス
145
+
146
+ 本リポジトリは [PolyForm Shield License 1.0.0](./LICENSE) のもとで公開されています。
147
+ これは source-available ライセンスであり、**競合製品化は禁止**されていますが、
148
+ 個人利用・社内利用・通常の商用利用は自由です。詳細は [LICENSE](./LICENSE) を
149
+ 参照してください。
150
+
151
+ ## コントリビューション
152
+
153
+ Pull Request を送信する際は [CONTRIBUTING.md](./CONTRIBUTING.md) を参照し、
154
+ CLA Assistant bot の指示に従って [CLA](./CLA.md) への同意をお願いします。
@@ -3,7 +3,11 @@ import { promisify } from 'node:util';
3
3
  import * as os from 'node:os';
4
4
  import * as path from 'node:path';
5
5
  import * as fs from 'node:fs/promises';
6
+ import { fileURLToPath } from 'node:url';
6
7
  const execAsync = promisify(exec);
8
+ // bundle.mjs が dist/ にコピーする。npx は npm workspace 内だと cwd を workspace
9
+ // ルートに変えるため、cwd 依存にせず --config で明示する(相対パスは config 基準で解決される)。
10
+ const PRISMA_CONFIG = path.join(path.dirname(fileURLToPath(import.meta.url)), 'prisma.config.ts');
7
11
  function getTsunagiDataDir() {
8
12
  return process.env.TSUNAGI_DATA_DIR || path.join(os.homedir(), '.tsunagi');
9
13
  }
@@ -13,7 +17,7 @@ function getStateDir() {
13
17
  async function autoMigrate() {
14
18
  try {
15
19
  await fs.mkdir(getStateDir(), { recursive: true });
16
- const { stdout } = await execAsync('npx prisma migrate deploy');
20
+ const { stdout } = await execAsync(`npx prisma migrate deploy --config ${JSON.stringify(PRISMA_CONFIG)}`);
17
21
  // Extract "N migration(s) applied." line from prisma output
18
22
  const match = stdout.match(/(\d+)\s+migrations?\s+applied/i);
19
23
  if (match) {
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import * as fs from 'node:fs';
4
4
  import * as http from 'node:http';
5
5
  import * as path from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
+ import openBrowser from 'open';
7
8
  import { cleanupPluginState, ensureCleanPluginState } from './plugin-lifecycle.js';
8
9
  import { acquireSingleInstanceLock } from './single-instance-lock.js';
9
10
  /**
@@ -21,8 +22,13 @@ import { acquireSingleInstanceLock } from './single-instance-lock.js';
21
22
  * <pkg>/.next/standalone/apps/web/server.js ← Next.js standalone entry (bundled from apps/web/.next/standalone)
22
23
  * <pkg>/.next/standalone/apps/web/.next/static/
23
24
  * <pkg>/.next/standalone/node_modules/
24
- * <pkg>/prisma/schema.prisma
25
- * <pkg>/prisma.config.ts
25
+ * <pkg>/dist/prisma/schema.prisma ← bundled from apps/server/prisma
26
+ * <pkg>/dist/prisma/migrations/**
27
+ * <pkg>/dist/prisma.config.ts ← passed via --config by dist/auto-migrate.js
28
+ * <pkg>/dist/scripts/monaco-editor.sh ← $EDITOR for Ctrl+G (resolved by dist/server/routes/terminal.js)
29
+ * <pkg>/dist/docs/ ← bundled from apps/docs/out (served on DOCS_PORT)
30
+ * <pkg>/dist/whisper-server/ ← bundled from apps/whisper-server
31
+ * <pkg>/dist/llm-server/ ← bundled from apps/llm-server
26
32
  * <pkg>/tsunagi-marketplace/plugins/tsunagi-plugin/.claude-plugin/plugin.json
27
33
  */
28
34
  // ---------------------------------------------------------------------------
@@ -58,7 +64,7 @@ const PACKAGE_ROOT = path.resolve(DIST_DIR, '..');
58
64
  const AUTO_MIGRATE_JS = path.join(DIST_DIR, 'auto-migrate.js');
59
65
  const FASTIFY_ENTRY_JS = path.join(DIST_DIR, 'server', 'index.js');
60
66
  const NEXT_STANDALONE_ENTRY = path.join(PACKAGE_ROOT, '.next', 'standalone', 'apps', 'web', 'server.js');
61
- const DOCS_DIR = path.join(PACKAGE_ROOT, 'docs');
67
+ const DOCS_DIR = path.join(DIST_DIR, 'docs');
62
68
  const DOCS_PORT = 2793;
63
69
  const isDebug = !!process.env.TSUNAGI_DEBUG;
64
70
  const isDocker = fs.existsSync('/.dockerenv');
@@ -257,8 +263,9 @@ Promise.all([pollHealth(Number(PORT)), pollHealth(Number(NEXT_PORT))]).then(() =
257
263
  console.log(TSUNAGI_AA);
258
264
  const url = `http://localhost:${PORT}`;
259
265
  if (!isDocker) {
260
- const cmd = process.platform === 'darwin' ? 'open' : 'xdg-open';
261
- spawn(cmd, [url], { stdio: 'ignore', detached: true }).unref();
266
+ // macOS / Linux / WSL(Windows 側ブラウザ)の差異は open パッケージが吸収する。
267
+ // ブラウザを開けなくてもサーバーは継続する(URL は下で案内する)
268
+ openBrowser(url).catch(() => { });
262
269
  }
263
270
  console.log(`Open ${url}`);
264
271
  if (docsServer) {
@@ -28,15 +28,16 @@ const EXPECTED_MODEL_BYTES = 17_200_000_000;
28
28
  const STARTUP_TIMEOUT_MS = 90_000;
29
29
  // クラッシュ時にエラーメッセージへ含めるstderrの上限文字数。
30
30
  const STDERR_TAIL_MAX_CHARS = 4000;
31
- // このファイルは apps/server/src/lib (dev) または apps/cli/dist/server/lib
32
- // (npm配布物) のいずれかにいる。どちらの場合も3階層上に llm-server が
33
- // 兄弟ディレクトリとして存在するようレイアウトを揃えている
34
- // (apps/server/dist/lib → apps/server → apps → apps/llm-server,
35
- // apps/cli/dist/server/lib → apps/cli/dist → apps/cli → apps/cli/llm-server)。
31
+ // このファイルの位置から llm-server を探す:
32
+ // npm配布物: apps/cli/dist/server/lib → 2階層上 → apps/cli/dist/llm-server
33
+ // dev/build: apps/server/{src,dist}/lib → 3階層上 → apps/llm-server
36
34
  export function findLlmServerDir() {
37
35
  const here = path.dirname(fileURLToPath(import.meta.url));
38
- const candidate = path.join(here, '..', '..', '..', 'llm-server');
39
- return fs.existsSync(path.join(candidate, 'run.sh')) ? candidate : null;
36
+ const candidates = [
37
+ path.join(here, '..', '..', 'llm-server'),
38
+ path.join(here, '..', '..', '..', 'llm-server'),
39
+ ];
40
+ return candidates.find((c) => fs.existsSync(path.join(c, 'run.sh'))) ?? null;
40
41
  }
41
42
  function venvPython() {
42
43
  return path.join(VENV_DIR, 'bin', 'python3');
@@ -22,15 +22,16 @@ const EXPECTED_MODEL_BYTES = 1_614_000_000;
22
22
  const STARTUP_TIMEOUT_MS = 60_000;
23
23
  // クラッシュ時にエラーメッセージへ含めるstderrの上限文字数。
24
24
  const STDERR_TAIL_MAX_CHARS = 4000;
25
- // このファイルは apps/server/src/lib (dev) または apps/cli/dist/server/lib
26
- // (npm配布物) のいずれかにいる。どちらの場合も3階層上に whisper-server が
27
- // 兄弟ディレクトリとして存在するようレイアウトを揃えている
28
- // (apps/server/dist/lib → apps/server → apps → apps/whisper-server,
29
- // apps/cli/dist/server/lib → apps/cli/dist → apps/cli → apps/cli/whisper-server)。
25
+ // このファイルの位置から whisper-server を探す:
26
+ // npm配布物: apps/cli/dist/server/lib → 2階層上 → apps/cli/dist/whisper-server
27
+ // dev/build: apps/server/{src,dist}/lib → 3階層上 → apps/whisper-server
30
28
  export function findWhisperServerDir() {
31
29
  const here = path.dirname(fileURLToPath(import.meta.url));
32
- const candidate = path.join(here, '..', '..', '..', 'whisper-server');
33
- return fs.existsSync(path.join(candidate, 'run.sh')) ? candidate : null;
30
+ const candidates = [
31
+ path.join(here, '..', '..', 'whisper-server'),
32
+ path.join(here, '..', '..', '..', 'whisper-server'),
33
+ ];
34
+ return candidates.find((c) => fs.existsSync(path.join(c, 'run.sh'))) ?? null;
34
35
  }
35
36
  function venvPython() {
36
37
  return path.join(VENV_DIR, 'bin', 'python3');
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs/promises';
2
2
  import * as os from 'os';
3
3
  import * as path from 'path';
4
+ import { fileURLToPath } from 'url';
4
5
  import { ptyManager } from '../pty-manager.js';
5
6
  import { prisma } from '../lib/db.js';
6
7
  import { getWorktreePath } from '../lib/worktree-manager.js';
@@ -9,8 +10,11 @@ import { ensureClaudeOnboardingCompleted, removeLocalModelFromUserSettings, } fr
9
10
  import { LOCAL_LLM_UNSET_ENV_KEYS, LOCAL_MODEL_ALIAS, buildLocalLlmEnv, } from '../lib/local-llm-env.js';
10
11
  import { ensureActiveLoaded, getLocalLlmSettings } from '../lib/local-llm.js';
11
12
  import { LOCAL_LLM_PROXY_URL, buildClaudeCommand, isLocalLlmMode } from '../lib/claude-command.js';
12
- // サーバーはプロジェクトルートから起動されるため process.cwd() でルートを取得
13
- const TSUNAGI_EDITOR_PATH = path.resolve(process.cwd(), 'scripts/monaco-editor.sh');
13
+ // このファイル基準で解決する(cwd 非依存):
14
+ // dev: apps/server/src/routes → apps/server/scripts
15
+ // build: apps/server/dist/routes → apps/server/scripts
16
+ // npm bundle: <pkg>/dist/server/routes → <pkg>/dist/scripts
17
+ const TSUNAGI_EDITOR_PATH = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../scripts/monaco-editor.sh');
14
18
  // Fastify(API) の公開ポート。index.ts と同じ既定値・同じ環境変数(TSUNAGI_SERVER_PORT)を見る。
15
19
  // monaco-editor.sh など PTY 内のプロセスが API を叩く際の同一ホスト向けベース URL に使う。
16
20
  const SERVER_PORT = Number(process.env.TSUNAGI_SERVER_PORT) || 2791;