@bolloon/bolloon-agent 0.2.1 → 0.2.2

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.
@@ -0,0 +1,170 @@
1
+ /**
2
+ * scripts/build-app-bundle.js
3
+ *
4
+ * 手搓 macOS .app bundle, 完全绕过 electron-builder 的 npm walker
5
+ * (那个 walker 在 1.1G @rayhanadev + app-builder-lib@26.x 下 OOM, 见
6
+ * memory/electron-pack-oom-2026-06-24.md).
7
+ *
8
+ * 步骤:
9
+ * 1. 复制 node_modules/electron/dist/Electron.app → release/mac-arm64/Bolloon Agent.app
10
+ * 2. 替换 Contents/Info.plist + PkgInfo + icon.icns
11
+ * 3. 复制 dist/ + node_modules/ + package.json → Contents/Resources/app/
12
+ * 4. (可选) 复制 build/tray.png → Contents/Resources/build/ (给 tray 用)
13
+ *
14
+ * 输出: release/mac-arm64/Bolloon Agent.app (可直接 open /Applications)
15
+ * 不生成 .dmg — 用 electron-builder --prepackaged 后续可补 (但现在跳过)
16
+ */
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const { execSync } = require('child_process');
20
+
21
+ const ROOT = path.resolve(__dirname, '..');
22
+ const ELECTRON_DIST = path.join(ROOT, 'node_modules', 'electron', 'dist');
23
+ const ELECTRON_APP = path.join(ELECTRON_DIST, 'Electron.app');
24
+ const APP_NAME = 'Bolloon Agent';
25
+ const PRODUCT_NAME = 'Bolloon Agent';
26
+ const APP_ID = 'com.bolloon.agent';
27
+ const OUTPUT_DIR = path.join(ROOT, 'release', 'mac-arm64');
28
+ const TARGET_APP = path.join(OUTPUT_DIR, `${APP_NAME}.app`);
29
+
30
+ function log(msg) {
31
+ console.log(`[build-app-bundle] ${msg}`);
32
+ }
33
+
34
+ function rmrf(p) {
35
+ if (fs.existsSync(p)) fs.rmSync(p, { recursive: true, force: true });
36
+ }
37
+
38
+ function copyDir(src, dst) {
39
+ fs.mkdirSync(dst, { recursive: true });
40
+ execSync(`cp -R "${src}/." "${dst}/"`, { stdio: 'inherit' });
41
+ }
42
+
43
+ function writeInfoPlist(appPath) {
44
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
45
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
46
+ <plist version="1.0">
47
+ <dict>
48
+ <key>CFBundleName</key>
49
+ <string>${APP_NAME}</string>
50
+ <key>CFBundleDisplayName</key>
51
+ <string>${APP_NAME}</string>
52
+ <key>CFBundleExecutable</key>
53
+ <string>Electron</string>
54
+ <key>CFBundleIdentifier</key>
55
+ <string>${APP_ID}</string>
56
+ <key>CFBundleVersion</key>
57
+ <string>0.1.42</string>
58
+ <key>CFBundleShortVersionString</key>
59
+ <string>0.1.42</string>
60
+ <key>CFBundleInfoDictionaryVersion</key>
61
+ <string>6.0</string>
62
+ <key>CFBundlePackageType</key>
63
+ <string>APPL</string>
64
+ <key>CFBundleSignature</key>
65
+ <string>????</string>
66
+ <key>LSMinimumSystemVersion</key>
67
+ <string>10.13.0</string>
68
+ <key>NSHighResolutionCapable</key>
69
+ <true/>
70
+ <key>NSPrincipalClass</key>
71
+ <string>NSApplication</string>
72
+ <key>LSApplicationCategoryType</key>
73
+ <string>public.app-category.productivity</string>
74
+ <key>NSSupportsAutomaticGraphicsSwitching</key>
75
+ <true/>
76
+ <key>ElectronAsarIntegrity</key>
77
+ <dict/>
78
+ <key>NSAppTransportSecurity</key>
79
+ <dict>
80
+ <key>NSAllowsLocalNetworking</key>
81
+ <true/>
82
+ </dict>
83
+ </dict>
84
+ </plist>
85
+ `;
86
+ fs.writeFileSync(path.join(appPath, 'Contents', 'Info.plist'), plist);
87
+ fs.writeFileSync(path.join(appPath, 'Contents', 'PkgInfo'), 'APPL????');
88
+ }
89
+
90
+ function main() {
91
+ if (!fs.existsSync(ELECTRON_APP)) {
92
+ console.error(`[build-app-bundle] FATAL: ${ELECTRON_APP} not found. Run: node node_modules/electron/install.js`);
93
+ process.exit(1);
94
+ }
95
+
96
+ log(`Cleaning ${OUTPUT_DIR}`);
97
+ rmrf(OUTPUT_DIR);
98
+ fs.mkdirSync(OUTPUT_DIR, { recursive: true });
99
+
100
+ log(`Copying Electron.app → ${TARGET_APP}`);
101
+ copyDir(ELECTRON_APP, TARGET_APP);
102
+
103
+ log(`Writing Info.plist + PkgInfo`);
104
+ writeInfoPlist(TARGET_APP);
105
+
106
+ // 替换 icon
107
+ const iconSrc = path.join(ROOT, 'build', 'icon.icns');
108
+ if (fs.existsSync(iconSrc)) {
109
+ log(`Copying icon: ${iconSrc}`);
110
+ fs.copyFileSync(iconSrc, path.join(TARGET_APP, 'Contents', 'Resources', 'electron.icns'));
111
+ } else {
112
+ log(`WARN: ${iconSrc} missing — app will use default Electron icon`);
113
+ }
114
+
115
+ // 复制 app 内容 → Contents/Resources/app/
116
+ const appContentDir = path.join(TARGET_APP, 'Contents', 'Resources', 'app');
117
+ log(`Building app content dir: ${appContentDir}`);
118
+ rmrf(appContentDir);
119
+ fs.mkdirSync(appContentDir, { recursive: true });
120
+
121
+ log(`Copying dist/`);
122
+ copyDir(path.join(ROOT, 'dist'), path.join(appContentDir, 'dist'));
123
+
124
+ log(`Copying package.json`);
125
+ fs.copyFileSync(path.join(ROOT, 'package.json'), path.join(appContentDir, 'package.json'));
126
+
127
+ log(`Copying node_modules/ (excluding devDeps) — this is the slow part`);
128
+ // 不能用 rsync 因为 OOM, 用 cp -R
129
+ const srcNm = path.join(ROOT, 'node_modules');
130
+ const dstNm = path.join(appContentDir, 'node_modules');
131
+ fs.mkdirSync(dstNm, { recursive: true });
132
+ // 排除大且 dev-only 的 packages, 但 @rayhanadev 必须保留 (生产代码用)
133
+ const entries = fs.readdirSync(srcNm);
134
+ let count = 0;
135
+ for (const name of entries) {
136
+ if (name.startsWith('.')) continue;
137
+ const src = path.join(srcNm, name);
138
+ const dst = path.join(dstNm, name);
139
+ fs.cpSync(src, dst, { recursive: true, dereference: false, filter: (s) => {
140
+ // 跳过 .bin, .cache, .package-lock.json
141
+ const base = path.basename(s);
142
+ if (base === '.bin' || base === '.cache' || base === '.package-lock.json') return false;
143
+ // 跳过 doc/test/assets 巨型 dir, 运行时不需要
144
+ if (base === 'test' || base === 'docs' || base === '__tests__') return false;
145
+ return true;
146
+ }});
147
+ count++;
148
+ if (count % 20 === 0) log(` copied ${count}/${entries.length} node_modules/*`);
149
+ }
150
+ log(`Copied ${count} node_modules entries`);
151
+
152
+ // 复制 bin/
153
+ const binSrc = path.join(ROOT, 'bin');
154
+ if (fs.existsSync(binSrc)) {
155
+ log(`Copying bin/`);
156
+ copyDir(binSrc, path.join(appContentDir, 'bin'));
157
+ }
158
+
159
+ // 复制 build/ → Resources/build/ (tray 图标用)
160
+ const buildSrc = path.join(ROOT, 'build');
161
+ if (fs.existsSync(buildSrc)) {
162
+ log(`Copying build/ → Resources/build/`);
163
+ copyDir(buildSrc, path.join(TARGET_APP, 'Contents', 'Resources', 'build'));
164
+ }
165
+
166
+ log(`Done. App bundle: ${TARGET_APP}`);
167
+ log(`To run: open "${TARGET_APP}"`);
168
+ }
169
+
170
+ main();
package/.comm/README.md DELETED
@@ -1,21 +0,0 @@
1
- # .comm/ — 跨机聊天收件箱
2
-
3
- Bolloon chat transport: commits-as-messages.
4
- 每条消息 = 一个 markdown 文件 + 一次 git commit + push.
5
-
6
- ## 目录约定
7
-
8
- - `<role>/` — 每个 role 一个子目录, 里面是该角色发的所有消息
9
- - `_state/` — 本地运行态 (cursor, seen, lock), 不 commit
10
- - `_inbox/` — 看门狗把对方消息反写到本地, 不 commit
11
-
12
- ## 子命令
13
-
14
- ```
15
- bolloon --chat-init
16
- bolloon --chat-send "..."
17
- bolloon --chat-pull
18
- bolloon --chat-list
19
- bolloon --chat-watch
20
- bolloon --chat-status
21
- ```
@@ -1,7 +0,0 @@
1
- ---
2
- v: 1
3
- from: default
4
- fromPk: d2e7473e4a2f8e6057d6c000f2146109585ed3bdb387233c5f9fecdd0c57d17d
5
- ts: 2026-06-17T08:23:00.017Z
6
- ---
7
- 今天把 chat transport 装上了, 测试一下两台电脑能不能通过 github 同步消息