@minimalcorp/tsunagi 0.1.41 → 0.1.43
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/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0nhzci6._.js → [root-of-the-server]__0d7excn._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0vi01rl._.js → [root-of-the-server]__0w3_4.k._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0zf09ry._.js → [root-of-the-server]__0ze019p._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0ujaeyr._.js → [root-of-the-server]__13yhig0._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{_0soxqr.._.js → _0_2b4wf._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_0g.cd6a._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{_0bt-4.4._.js → _0s18_3n._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_settings_page_tsx_0i6itlb._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_[id]_page_tsx_0jshsm2._.js +12 -12
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0uej915._.js → node_modules_00z7dqq._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0k8xmjr._.js → node_modules_00~3~7_._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0bqsyfk._.js → node_modules_06uw9~g._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0smdx~2._.js → node_modules_07f58ia._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0fpqbi2._.js → node_modules_07ve26r._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0b6fjwn._.js → node_modules_0bq-u.l._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0pk6e0.._.js → node_modules_0f3mifg._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0_4__2k._.js → node_modules_0ih0wxv._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0r9vehj._.js → node_modules_0lgu9gx._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0bix9lu._.js → node_modules_0nwi8c2._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0w48uk8._.js → node_modules_0p2g6on._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_07-e6tb._.js → node_modules_0szd5t1._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0yoat72._.js → node_modules_0vtmkdp._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0bzw~9d._.js → node_modules_0z02r3w._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0fsewd2._.js → node_modules_0~pcd4h._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0l~40og._.js → node_modules_10mbxmu._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
- package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{0nhcl~svhi_26.js → 0.e10jueei8qv.js} +3 -3
- package/.next/standalone/apps/web/.next/static/chunks/{0g5hoj5w-z.~6.js → 04ie1rttuhc99.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{0q-u7bl7oa42n.js → 06sk6d3k059.n.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/09osn8dd42~wz.css +4 -0
- package/.next/standalone/apps/web/.next/static/chunks/0imnlpmbrdgiv.js +5 -0
- package/.next/standalone/apps/web/.next/static/chunks/{158q94mo2-6sx.js → 0u_07wgcigiqu.js} +8 -8
- package/.next/standalone/apps/web/.next/static/chunks/{02.u6zk77a338.js → 0wvv75.1gvloi.js} +12 -12
- package/.next/standalone/apps/web/.next/static/chunks/{0q_j4~6_etj_q.js → 10usg-2-r6y3f.js} +3 -3
- package/LICENSE +126 -0
- package/README.md +154 -0
- package/dist/auto-migrate.js +5 -1
- package/dist/cli.js +8 -3
- package/dist/server/lib/claude-command.d.ts +2 -0
- package/dist/server/lib/claude-command.js +47 -15
- package/dist/server/lib/llm-process.js +8 -7
- package/dist/server/lib/searxng.d.ts +2 -0
- package/dist/server/lib/searxng.js +280 -16
- package/dist/server/lib/tab-todos.d.ts +12 -0
- package/dist/server/lib/tab-todos.js +139 -0
- package/dist/server/lib/whisper-process.js +8 -7
- package/dist/server/routes/hooks.js +49 -63
- package/dist/server/routes/terminal.js +17 -6
- package/npm-shrinkwrap.json +8 -18
- package/package.json +1 -8
- package/tsunagi-marketplace/plugins/tsunagi-plugin/skills/tsunagi-task/SKILL.md +11 -9
- package/.next/standalone/apps/web/.next/static/chunks/09ortx3kdapgz.js +0 -5
- package/.next/standalone/apps/web/.next/static/chunks/0p9~lk406udl5.css +0 -4
- /package/.next/standalone/apps/web/.next/static/{odzSASj06wo3KbNbC2VNt → oMoJ6ksWSsDkoV7dPvxim}/_buildManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{odzSASj06wo3KbNbC2VNt → oMoJ6ksWSsDkoV7dPvxim}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{odzSASj06wo3KbNbC2VNt → oMoJ6ksWSsDkoV7dPvxim}/_ssgManifest.js +0 -0
- /package/{llm-server → dist/llm-server}/README.md +0 -0
- /package/{llm-server → dist/llm-server}/download_model.py +0 -0
- /package/{llm-server → dist/llm-server}/requirements.txt +0 -0
- /package/{llm-server → dist/llm-server}/run.sh +0 -0
- /package/{prisma → dist/prisma}/migrations/20260129030443_init/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260130140855_add_task_planning_fields_and_base_branch/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260130163529_add_base_branch_commit/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260131171847_remove_completed_at/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260328000000_remove_sdk_dead_code/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260329000000_add_todos_and_planner_tabs/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260410000000_clear_stale_tab_todos/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260413000000_make_task_order_non_nullable/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260629000000_add_tab_mode/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260915000000_drop_planner_tabs/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260916000000_add_repository_order/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260918000000_add_tab_unread/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/20260924000000_add_app_settings/migration.sql +0 -0
- /package/{prisma → dist/prisma}/migrations/migration_lock.toml +0 -0
- /package/{prisma → dist/prisma}/schema.prisma +0 -0
- /package/{prisma.config.ts → dist/prisma.config.ts} +0 -0
- /package/{scripts → dist/scripts}/monaco-editor.sh +0 -0
- /package/{whisper-server → dist/whisper-server}/README.md +0 -0
- /package/{whisper-server → dist/whisper-server}/download_model.py +0 -0
- /package/{whisper-server → dist/whisper-server}/requirements.txt +0 -0
- /package/{whisper-server → dist/whisper-server}/run.sh +0 -0
- /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) への同意をお願いします。
|
package/dist/auto-migrate.js
CHANGED
|
@@ -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(
|
|
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
|
@@ -21,8 +21,13 @@ import { acquireSingleInstanceLock } from './single-instance-lock.js';
|
|
|
21
21
|
* <pkg>/.next/standalone/apps/web/server.js ← Next.js standalone entry (bundled from apps/web/.next/standalone)
|
|
22
22
|
* <pkg>/.next/standalone/apps/web/.next/static/
|
|
23
23
|
* <pkg>/.next/standalone/node_modules/
|
|
24
|
-
* <pkg>/prisma/schema.prisma
|
|
25
|
-
* <pkg>/prisma
|
|
24
|
+
* <pkg>/dist/prisma/schema.prisma ← bundled from apps/server/prisma
|
|
25
|
+
* <pkg>/dist/prisma/migrations/**
|
|
26
|
+
* <pkg>/dist/prisma.config.ts ← passed via --config by dist/auto-migrate.js
|
|
27
|
+
* <pkg>/dist/scripts/monaco-editor.sh ← $EDITOR for Ctrl+G (resolved by dist/server/routes/terminal.js)
|
|
28
|
+
* <pkg>/dist/docs/ ← bundled from apps/docs/out (served on DOCS_PORT)
|
|
29
|
+
* <pkg>/dist/whisper-server/ ← bundled from apps/whisper-server
|
|
30
|
+
* <pkg>/dist/llm-server/ ← bundled from apps/llm-server
|
|
26
31
|
* <pkg>/tsunagi-marketplace/plugins/tsunagi-plugin/.claude-plugin/plugin.json
|
|
27
32
|
*/
|
|
28
33
|
// ---------------------------------------------------------------------------
|
|
@@ -58,7 +63,7 @@ const PACKAGE_ROOT = path.resolve(DIST_DIR, '..');
|
|
|
58
63
|
const AUTO_MIGRATE_JS = path.join(DIST_DIR, 'auto-migrate.js');
|
|
59
64
|
const FASTIFY_ENTRY_JS = path.join(DIST_DIR, 'server', 'index.js');
|
|
60
65
|
const NEXT_STANDALONE_ENTRY = path.join(PACKAGE_ROOT, '.next', 'standalone', 'apps', 'web', 'server.js');
|
|
61
|
-
const DOCS_DIR = path.join(
|
|
66
|
+
const DOCS_DIR = path.join(DIST_DIR, 'docs');
|
|
62
67
|
const DOCS_PORT = 2793;
|
|
63
68
|
const isDebug = !!process.env.TSUNAGI_DEBUG;
|
|
64
69
|
const isDocker = fs.existsSync('/.dockerenv');
|
|
@@ -2,5 +2,7 @@ import type { TabMode } from '@minimalcorp/tsunagi-shared';
|
|
|
2
2
|
/** ローカルLLMタブの Claude Code の接続先(tsunagi の中継口) */
|
|
3
3
|
export declare const LOCAL_LLM_PROXY_URL: string;
|
|
4
4
|
export declare function isLocalLlmMode(mode: TabMode | undefined): boolean;
|
|
5
|
+
/** 起動スクリプトの type 引数。original: Anthropic、ollama / lm-studio: ローカルLLM */
|
|
6
|
+
export type LaunchType = 'original' | 'ollama' | 'lm-studio';
|
|
5
7
|
/** タブの mode に応じた claude の起動コマンド(既存セッションがあれば resume) */
|
|
6
8
|
export declare function buildClaudeCommand(sessionId: string, mode: TabMode): Promise<string>;
|
|
@@ -19,6 +19,10 @@ export function isLocalLlmMode(mode) {
|
|
|
19
19
|
function shellQuote(value) {
|
|
20
20
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
21
21
|
}
|
|
22
|
+
const LAUNCH_TYPE_PROVIDER = {
|
|
23
|
+
ollama: 'ollama',
|
|
24
|
+
'lm-studio': 'lmstudio',
|
|
25
|
+
};
|
|
22
26
|
/**
|
|
23
27
|
* ローカルLLMタブの claude に付ける引数。
|
|
24
28
|
* - モデルは Settings でだけ切り替える: /model の一覧を中継口の名前1件にし、PreModelSwitch フックで
|
|
@@ -28,10 +32,9 @@ function shellQuote(value) {
|
|
|
28
32
|
* 毎回プロンプトに載る(prefill が遅くなり tool 選択の精度も落ちる)。そのため MCP を tsunagi の
|
|
29
33
|
* タスク管理と web_search だけに絞る
|
|
30
34
|
*/
|
|
31
|
-
|
|
32
|
-
const { active, webSearch } = await getLocalLlmSettings();
|
|
35
|
+
function localLlmArgs(provider, webSearch) {
|
|
33
36
|
// ollama.com による WebSearch の代行は、使用中のモデルが Ollama のときだけ使える
|
|
34
|
-
const localWebSearch = webSearch === 'local' ||
|
|
37
|
+
const localWebSearch = webSearch === 'local' || provider !== 'ollama';
|
|
35
38
|
const settings = {
|
|
36
39
|
modelPicker: {
|
|
37
40
|
options: [
|
|
@@ -80,27 +83,56 @@ async function localLlmArgs() {
|
|
|
80
83
|
return args;
|
|
81
84
|
}
|
|
82
85
|
/**
|
|
83
|
-
*
|
|
86
|
+
* タスク進捗(プログレスバー)の元になる Task 系ツール。
|
|
87
|
+
* Claude Code は旧モデル以外ではこれらを既定で無効にしており、--allowedTools で明示すると有効になる
|
|
88
|
+
*/
|
|
89
|
+
const TASK_TOOLS = 'TaskCreate,TaskGet,TaskUpdate,TaskList';
|
|
90
|
+
/**
|
|
91
|
+
* claude の起動スクリプトを書き出し、そのパスを返す。`sh <script> <type> <session-id>` で起動し、
|
|
92
|
+
* 既存セッションがあれば resume、なければ新規作成する。
|
|
84
93
|
* 起動コマンドは PTY に1行で書き込むため、macOS の端末入力の1行上限(MAX_CANON = 1024 バイト)を
|
|
85
94
|
* 超えると後ろが切り捨てられる。引数の JSON をコマンドに直接載せると上限を超え、
|
|
86
95
|
* `|| claude ... --session-id` 側が途中で切れてタブと別のセッションIDで起動してしまう
|
|
87
|
-
* (hooks がタブに紐づかず、--settings / --mcp-config
|
|
96
|
+
* (hooks がタブに紐づかず、--settings / --mcp-config も効かない)。そのため引数はスクリプトに閉じ込める。
|
|
97
|
+
* ローカルLLMの引数は Settings に依存するため起動のたびに書き直す
|
|
88
98
|
*/
|
|
89
|
-
async function
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
async function writeLauncher() {
|
|
100
|
+
const { webSearch } = await getLocalLlmSettings();
|
|
101
|
+
const branches = Object.keys(LAUNCH_TYPE_PROVIDER)
|
|
102
|
+
.map((type) => ` ${type}) set -- ${localLlmArgs(LAUNCH_TYPE_PROVIDER[type], webSearch).join(' ')} ;;`)
|
|
103
|
+
.join('\n');
|
|
104
|
+
const script = `#!/bin/sh
|
|
105
|
+
# usage: launch-claude.sh <original|ollama|lm-studio> <session-id>
|
|
106
|
+
type=$1
|
|
107
|
+
session_id=$2
|
|
108
|
+
case "$type" in
|
|
109
|
+
original) set -- ;;
|
|
110
|
+
${branches}
|
|
111
|
+
*) echo "launch-claude.sh: unknown type: $type" >&2; exit 2 ;;
|
|
112
|
+
esac
|
|
113
|
+
claude --dangerously-skip-permissions --allowedTools ${TASK_TOOLS} "$@" --resume "$session_id" 2>/dev/null ||
|
|
114
|
+
exec claude --dangerously-skip-permissions --allowedTools ${TASK_TOOLS} "$@" --session-id "$session_id"
|
|
115
|
+
`;
|
|
116
|
+
const file = path.join(getStateDir(), 'launch-claude.sh');
|
|
117
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
93
118
|
// 複数タブの同時起動で書きかけのファイルを読まないよう、書き終えてから置き換える
|
|
94
119
|
const tmp = `${file}.${randomUUID()}.tmp`;
|
|
95
|
-
await writeFile(tmp,
|
|
120
|
+
await writeFile(tmp, script);
|
|
96
121
|
await rename(tmp, file);
|
|
97
122
|
return file;
|
|
98
123
|
}
|
|
124
|
+
/** タブの mode から起動スクリプトの type を決める。ローカルLLMは Settings で選んだ使用中のモデルに従う */
|
|
125
|
+
async function resolveLaunchType(mode) {
|
|
126
|
+
if (!isLocalLlmMode(mode))
|
|
127
|
+
return 'original';
|
|
128
|
+
const { active } = await getLocalLlmSettings();
|
|
129
|
+
if (!active) {
|
|
130
|
+
throw new Error('ローカルLLMのモデルが未設定です。Settings で使用するモデルを選んでください');
|
|
131
|
+
}
|
|
132
|
+
return active.provider === 'ollama' ? 'ollama' : 'lm-studio';
|
|
133
|
+
}
|
|
99
134
|
/** タブの mode に応じた claude の起動コマンド(既存セッションがあれば resume) */
|
|
100
135
|
export async function buildClaudeCommand(sessionId, mode) {
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
? `sh ${shellQuote(await writeLocalLlmLauncher([...args, ...(await localLlmArgs())]))}`
|
|
104
|
-
: `claude ${args.join(' ')}`;
|
|
105
|
-
return `${claude} --resume ${sessionId} 2>/dev/null || ${claude} --session-id ${sessionId}`;
|
|
136
|
+
const type = await resolveLaunchType(mode);
|
|
137
|
+
return `sh ${shellQuote(await writeLauncher())} ${type} ${sessionId}`;
|
|
106
138
|
}
|
|
@@ -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
|
-
//
|
|
32
|
-
//
|
|
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
|
|
39
|
-
|
|
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');
|
|
@@ -9,6 +9,8 @@ export declare function parseSearxngSettings(body: unknown): {
|
|
|
9
9
|
};
|
|
10
10
|
/** searxng-run を探す(設定値 → PATH)。見つからなければ null */
|
|
11
11
|
export declare function findSearxngBin(settings: SearxngSettings): string | null;
|
|
12
|
+
/** docker コマンドを探す(PATH → Docker Desktop / Homebrew の既定の場所)。見つからなければ null */
|
|
13
|
+
export declare function findDockerBin(): string | null;
|
|
12
14
|
/** Ollama / LM Studio の有効状態に合わせて起動・停止する。失敗しても例外は投げない */
|
|
13
15
|
export declare function syncSearxng(): Promise<void>;
|
|
14
16
|
/** 手動での再起動(設定変更後やエラーからの復帰) */
|