a2acalling 0.6.50 → 0.6.51
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/bin/cli.js +172 -0
- package/native/macos/index.html +5 -10
- package/native/macos/src-tauri/Cargo.lock +5875 -0
- package/native/macos/src-tauri/Cargo.toml +3 -2
- package/native/macos/src-tauri/icons/128x128.png +0 -0
- package/native/macos/src-tauri/icons/128x128@2x.png +0 -0
- package/native/macos/src-tauri/icons/32x32.png +0 -0
- package/native/macos/src-tauri/icons/tray-connected.png +0 -0
- package/native/macos/src-tauri/icons/tray-disconnected.png +0 -0
- package/native/macos/src-tauri/src/lib.rs +2 -2
- package/native/macos/src-tauri/src/notifications.rs +147 -68
- package/native/macos/src-tauri/tauri.conf.json +2 -9
- package/package.json +1 -1
- package/scripts/postinstall.js +0 -49
- package/src/dashboard/public/app.js +147 -1
- package/src/lib/conversations.js +55 -1
- package/src/lib/dashboard-events.js +205 -0
- package/src/routes/a2a.js +25 -4
- package/src/routes/dashboard.js +114 -1
- package/src/server.js +4 -0
package/bin/cli.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* a2a call <url> <msg> Call a contact (or invite URL)
|
|
12
12
|
* a2a ping <url> Ping an invite URL
|
|
13
13
|
* a2a gui Open the local dashboard GUI in a browser
|
|
14
|
+
* a2a app <action> Manage native macOS app (status/install/uninstall)
|
|
14
15
|
* a2a setup Auto setup (gateway-aware dashboard install)
|
|
15
16
|
* a2a uninstall Stop server and remove local A2A config
|
|
16
17
|
*/
|
|
@@ -37,6 +38,7 @@ const ONBOARDING_EXEMPT = new Set([
|
|
|
37
38
|
'dashboard',
|
|
38
39
|
'server',
|
|
39
40
|
'setup',
|
|
41
|
+
'app',
|
|
40
42
|
'install',
|
|
41
43
|
'skills'
|
|
42
44
|
]);
|
|
@@ -168,6 +170,100 @@ function findNativeApp() {
|
|
|
168
170
|
return null;
|
|
169
171
|
}
|
|
170
172
|
|
|
173
|
+
function getNativeAppPaths() {
|
|
174
|
+
return {
|
|
175
|
+
appDir: path.join(os.homedir(), 'Applications'),
|
|
176
|
+
appPath: path.join(os.homedir(), 'Applications', 'A2A Callbook.app')
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function parseInstalledNativeAppVersion(appPath) {
|
|
181
|
+
if (!appPath) return null;
|
|
182
|
+
const plistPath = path.join(appPath, 'Contents', 'Info.plist');
|
|
183
|
+
if (!fs.existsSync(plistPath)) return null;
|
|
184
|
+
try {
|
|
185
|
+
const plist = fs.readFileSync(plistPath, 'utf8');
|
|
186
|
+
const m = plist.match(/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/);
|
|
187
|
+
return m && m[1] ? m[1].trim() : null;
|
|
188
|
+
} catch (_) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function installNativeMacApp(options = {}) {
|
|
194
|
+
if (os.platform() !== 'darwin') {
|
|
195
|
+
return { success: false, skipped: 'not_macos' };
|
|
196
|
+
}
|
|
197
|
+
const quiet = Boolean(options.quiet);
|
|
198
|
+
const force = Boolean(options.force);
|
|
199
|
+
const version = require('../package.json').version;
|
|
200
|
+
const { appDir, appPath } = getNativeAppPaths();
|
|
201
|
+
const installedVersion = parseInstalledNativeAppVersion(appPath);
|
|
202
|
+
if (!force && installedVersion === version) {
|
|
203
|
+
return { success: true, installed: false, version, appPath, reason: 'already_current' };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const tarUrl = `https://github.com/onthegonow/a2a_calling/releases/download/v${version}/A2A-Callbook-${version}.app.tar.gz`;
|
|
207
|
+
const tmpFile = path.join(os.tmpdir(), `a2a-callbook-${version}.app.tar.gz`);
|
|
208
|
+
const { execFileSync } = require('child_process');
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
fs.mkdirSync(appDir, { recursive: true });
|
|
212
|
+
execFileSync('curl', ['-fL', '-o', tmpFile, tarUrl], { timeout: 120000, stdio: quiet ? 'ignore' : 'inherit' });
|
|
213
|
+
if (!fs.existsSync(tmpFile) || fs.statSync(tmpFile).size < 1000) {
|
|
214
|
+
return { success: false, error: 'download_failed' };
|
|
215
|
+
}
|
|
216
|
+
if (fs.existsSync(appPath)) {
|
|
217
|
+
fs.rmSync(appPath, { recursive: true, force: true });
|
|
218
|
+
}
|
|
219
|
+
execFileSync('tar', ['-xzf', tmpFile, '-C', appDir], { timeout: 60000, stdio: quiet ? 'ignore' : 'inherit' });
|
|
220
|
+
try { fs.unlinkSync(tmpFile); } catch (_) {}
|
|
221
|
+
return { success: true, installed: true, version, appPath };
|
|
222
|
+
} catch (err) {
|
|
223
|
+
try { fs.unlinkSync(tmpFile); } catch (_) {}
|
|
224
|
+
return { success: false, error: err.message || 'install_failed' };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function uninstallNativeMacApp() {
|
|
229
|
+
if (os.platform() !== 'darwin') {
|
|
230
|
+
return { success: false, skipped: 'not_macos' };
|
|
231
|
+
}
|
|
232
|
+
const candidates = [
|
|
233
|
+
path.join(os.homedir(), 'Applications', 'A2A Callbook.app'),
|
|
234
|
+
'/Applications/A2A Callbook.app'
|
|
235
|
+
];
|
|
236
|
+
const existing = candidates.filter((candidate) => {
|
|
237
|
+
try {
|
|
238
|
+
return fs.existsSync(candidate);
|
|
239
|
+
} catch (_) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
if (existing.length === 0) {
|
|
244
|
+
return { success: true, removed: false, appPath: candidates[0] };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const removed = [];
|
|
248
|
+
const failed = [];
|
|
249
|
+
for (const appPath of existing) {
|
|
250
|
+
try {
|
|
251
|
+
fs.rmSync(appPath, { recursive: true, force: true });
|
|
252
|
+
removed.push(appPath);
|
|
253
|
+
} catch (err) {
|
|
254
|
+
failed.push({ appPath, error: err && err.message ? err.message : 'uninstall_failed' });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (failed.length > 0) {
|
|
258
|
+
return {
|
|
259
|
+
success: false,
|
|
260
|
+
error: failed.map((f) => `${f.appPath}: ${f.error}`).join('; '),
|
|
261
|
+
appPath: removed[0] || existing[0]
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
return { success: true, removed: true, appPath: removed[0] || existing[0] };
|
|
265
|
+
}
|
|
266
|
+
|
|
171
267
|
async function findLocalServerPort(preferredPorts = []) {
|
|
172
268
|
const http = require('http');
|
|
173
269
|
|
|
@@ -2159,6 +2255,74 @@ a2a add "${inviteUrl}" "${ownerText || 'friend'}" && a2a call "${ownerText || 'f
|
|
|
2159
2255
|
require('../scripts/install-openclaw.js');
|
|
2160
2256
|
},
|
|
2161
2257
|
|
|
2258
|
+
app: (args) => {
|
|
2259
|
+
const action = String(args._[1] || 'status').trim().toLowerCase();
|
|
2260
|
+
const force = Boolean(args.flags.force || args.flags.f);
|
|
2261
|
+
const quiet = Boolean(args.flags.quiet || args.flags.q);
|
|
2262
|
+
const pkgVersion = require('../package.json').version;
|
|
2263
|
+
|
|
2264
|
+
if (action === 'status') {
|
|
2265
|
+
const installedAppPath = findNativeApp();
|
|
2266
|
+
const preferredPath = getNativeAppPaths().appPath;
|
|
2267
|
+
const version = installedAppPath ? parseInstalledNativeAppVersion(installedAppPath) : null;
|
|
2268
|
+
console.log('A2A Native App Status\n');
|
|
2269
|
+
console.log(` Platform: ${os.platform()}`);
|
|
2270
|
+
console.log(` CLI version: ${pkgVersion}`);
|
|
2271
|
+
if (os.platform() !== 'darwin') {
|
|
2272
|
+
console.log(' Native app: Not supported on this platform');
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
2275
|
+
console.log(` Installed: ${installedAppPath ? 'yes' : 'no'}`);
|
|
2276
|
+
console.log(` App path: ${installedAppPath || preferredPath}`);
|
|
2277
|
+
console.log(` App version: ${version || '(unknown)'}`);
|
|
2278
|
+
if (!installedAppPath) {
|
|
2279
|
+
console.log('\nInstall with: a2a app install');
|
|
2280
|
+
}
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
if (action === 'install') {
|
|
2285
|
+
const result = installNativeMacApp({ force, quiet });
|
|
2286
|
+
if (result.skipped === 'not_macos') {
|
|
2287
|
+
console.error('Native app install is only available on macOS.');
|
|
2288
|
+
process.exit(1);
|
|
2289
|
+
}
|
|
2290
|
+
if (!result.success) {
|
|
2291
|
+
console.error(`Native app install failed: ${result.error || 'unknown error'}`);
|
|
2292
|
+
process.exit(1);
|
|
2293
|
+
}
|
|
2294
|
+
if (result.reason === 'already_current') {
|
|
2295
|
+
console.log(`Native app already installed at current version (${result.version}).`);
|
|
2296
|
+
console.log(`Path: ${result.appPath}`);
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
console.log(`Native app installed (v${result.version}).`);
|
|
2300
|
+
console.log(`Path: ${result.appPath}`);
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
if (action === 'uninstall') {
|
|
2305
|
+
const result = uninstallNativeMacApp();
|
|
2306
|
+
if (result.skipped === 'not_macos') {
|
|
2307
|
+
console.error('Native app uninstall is only available on macOS.');
|
|
2308
|
+
process.exit(1);
|
|
2309
|
+
}
|
|
2310
|
+
if (!result.success) {
|
|
2311
|
+
console.error(`Native app uninstall failed: ${result.error || 'unknown error'}`);
|
|
2312
|
+
process.exit(1);
|
|
2313
|
+
}
|
|
2314
|
+
if (!result.removed) {
|
|
2315
|
+
console.log('Native app is not installed.');
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
console.log(`Native app removed: ${result.appPath}`);
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
console.error('Usage: a2a app <status|install|uninstall> [--force] [--quiet]');
|
|
2323
|
+
process.exit(1);
|
|
2324
|
+
},
|
|
2325
|
+
|
|
2162
2326
|
uninstall: async (args) => {
|
|
2163
2327
|
const fs = require('fs');
|
|
2164
2328
|
const path = require('path');
|
|
@@ -2737,6 +2901,12 @@ Calling:
|
|
|
2737
2901
|
status <url> Get A2A status
|
|
2738
2902
|
gui Open the local dashboard GUI in a browser
|
|
2739
2903
|
--tab, -t Optional: contacts|calls|logs|settings|invites
|
|
2904
|
+
app Manage native macOS app
|
|
2905
|
+
status Show native app installation status (default)
|
|
2906
|
+
install Install/update native app from GitHub release
|
|
2907
|
+
--force, -f Reinstall even when current version is present
|
|
2908
|
+
--quiet, -q Suppress download/extract output
|
|
2909
|
+
uninstall Remove native app from ~/Applications
|
|
2740
2910
|
|
|
2741
2911
|
Server:
|
|
2742
2912
|
server Start the A2A server
|
|
@@ -2773,6 +2943,8 @@ Examples:
|
|
|
2773
2943
|
a2a contacts link Alice tok_abc123
|
|
2774
2944
|
a2a call Alice "Hello!"
|
|
2775
2945
|
a2a conversations show conv_abc123
|
|
2946
|
+
a2a app status
|
|
2947
|
+
a2a app install --force
|
|
2776
2948
|
a2a server --port 3001
|
|
2777
2949
|
`);
|
|
2778
2950
|
}
|
package/native/macos/index.html
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
Server not running
|
|
72
72
|
</p>
|
|
73
73
|
<p class="port-info" id="last-port">No a2a server found on common ports</p>
|
|
74
|
-
<button id="btn-start">
|
|
74
|
+
<button id="btn-start">How to start server</button>
|
|
75
75
|
<button id="btn-retry" class="secondary">Retry</button>
|
|
76
76
|
<p id="error-detail"></p>
|
|
77
77
|
</div>
|
|
@@ -120,15 +120,10 @@
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
document.getElementById('btn-start')?.addEventListener('click', async () => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
} catch (err) {
|
|
128
|
-
const detail = document.getElementById('error-detail');
|
|
129
|
-
detail.textContent = `Failed to start: ${err}`;
|
|
130
|
-
detail.style.display = 'block';
|
|
131
|
-
}
|
|
123
|
+
const detail = document.getElementById('error-detail');
|
|
124
|
+
// v1 design decision: app links/status only; no app-owned server lifecycle management yet.
|
|
125
|
+
detail.textContent = 'Run `a2a server` (or `a2a quickstart`) in Terminal, then click Retry.';
|
|
126
|
+
detail.style.display = 'block';
|
|
132
127
|
});
|
|
133
128
|
|
|
134
129
|
document.getElementById('btn-retry')?.addEventListener('click', checkServer);
|