@elizaos/app-core 2.0.0-beta.1 → 2.0.0-beta.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.
- package/package.json +2 -2
- package/platforms/electrobun/native/macos/window-effects.mm +103 -0
- package/platforms/electrobun/package.json +9 -0
- package/platforms/electrobun/src/__stubs__/bun-ffi.ts +16 -0
- package/platforms/electrobun/src/libMacWindowEffects.dylib +0 -0
- package/platforms/electrobun/src/native/agent.ts +74 -3
- package/platforms/electrobun/src/native/desktop.ts +39 -6
- package/platforms/electrobun/src/native/mac-window-effects.ts +61 -1
- package/platforms/electrobun/src/native/permissions-shared.ts +3 -2
- package/platforms/electrobun/src/native/permissions.ts +11 -6
- package/platforms/electrobun/src/rpc-handlers.ts +7 -0
- package/platforms/electrobun/src/rpc-schema.ts +39 -4
- package/platforms/electrobun/src/runtime-permissions.ts +7 -1
- package/runtime/ensure-local-inference-handler.d.ts +1 -0
- package/runtime/ensure-local-inference-handler.d.ts.map +1 -1
- package/runtime/ensure-local-inference-handler.js +9 -0
- package/runtime/mode/remote-forwarder.d.ts.map +1 -1
- package/runtime/mode/remote-forwarder.js +1 -1
- package/runtime/mode/runtime-mode.d.ts +20 -2
- package/runtime/mode/runtime-mode.d.ts.map +1 -1
- package/runtime/mode/runtime-mode.js +69 -1
- package/scripts/aosp/stage-default-models.mjs +2 -2
- package/scripts/build-llama-cpp-dflash.mjs +75 -40
- package/scripts/kernel-patches/metal-kernels.mjs +357 -337
- package/scripts/lib/read-app-identity.mjs +5 -1
- package/services/local-inference/catalog.d.ts +2 -1
- package/services/local-inference/catalog.d.ts.map +1 -1
- package/services/local-inference/catalog.js +131 -12
- package/services/local-inference/downloader.d.ts +2 -0
- package/services/local-inference/downloader.d.ts.map +1 -1
- package/services/local-inference/downloader.js +300 -1
- package/services/local-inference/manifest/validator.d.ts.map +1 -1
- package/services/local-inference/manifest/validator.js +48 -0
- package/services/local-inference/providers.d.ts +1 -1
- package/services/local-inference/providers.js +6 -6
- package/services/local-inference/registry.d.ts.map +1 -1
- package/services/local-inference/registry.js +10 -1
- package/services/local-inference/types.d.ts +6 -0
- package/services/local-inference/types.d.ts.map +1 -1
- package/test/helpers/real-runtime.ts +21 -20
- package/platforms/electrobun/src/native/permissions-darwin.ts +0 -342
- package/platforms/electrobun/src/native/permissions-linux.ts +0 -34
- package/platforms/electrobun/src/native/permissions-win32.ts +0 -56
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/app-core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.2",
|
|
4
4
|
"description": "Shared application core for elizaOS white-label agent apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@capacitor/preferences": "^8.0.1",
|
|
51
51
|
"@capacitor/push-notifications": "^8.0.0",
|
|
52
52
|
"@clack/prompts": "^1.0.0",
|
|
53
|
-
"@elizaos/agent": "2.0.0-beta.
|
|
53
|
+
"@elizaos/agent": "2.0.0-beta.2",
|
|
54
54
|
"@elizaos/capacitor-llama": "2.0.0-beta.1",
|
|
55
55
|
"@elizaos/core": "2.0.0-beta.1",
|
|
56
56
|
"@elizaos/plugin-anthropic": "2.0.0-beta.1",
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
#import <AVFoundation/AVFoundation.h>
|
|
4
4
|
#import <Availability.h>
|
|
5
5
|
#import <CoreGraphics/CoreGraphics.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <string.h>
|
|
6
8
|
|
|
7
9
|
static NSString *const kElectrobunVibrancyViewIdentifier =
|
|
8
10
|
@"ElectrobunVibrancyView";
|
|
@@ -17,6 +19,32 @@ static NSString *const kElectrobunNativeDragRightEdgeIdentifier =
|
|
|
17
19
|
static NSString *const kElizaInactiveTrafficLightsOverlayIdentifier =
|
|
18
20
|
@"ElizaInactiveTrafficLightsOverlay";
|
|
19
21
|
|
|
22
|
+
static NSMutableArray<NSURL *> *elizaSecurityScopedUrls(void) {
|
|
23
|
+
static NSMutableArray<NSURL *> *urls = nil;
|
|
24
|
+
static dispatch_once_t onceToken;
|
|
25
|
+
dispatch_once(&onceToken, ^{
|
|
26
|
+
urls = [[NSMutableArray alloc] init];
|
|
27
|
+
});
|
|
28
|
+
return urls;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static char *elizaCopyCString(NSString *value) {
|
|
32
|
+
if (value == nil) {
|
|
33
|
+
return nullptr;
|
|
34
|
+
}
|
|
35
|
+
const char *utf8 = [value UTF8String];
|
|
36
|
+
if (utf8 == nullptr) {
|
|
37
|
+
return nullptr;
|
|
38
|
+
}
|
|
39
|
+
size_t len = strlen(utf8);
|
|
40
|
+
char *out = (char *)malloc(len + 1);
|
|
41
|
+
if (out == nullptr) {
|
|
42
|
+
return nullptr;
|
|
43
|
+
}
|
|
44
|
+
memcpy(out, utf8, len + 1);
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
|
|
20
48
|
/** Transparent strip for moving the window. WKWebView does not honor
|
|
21
49
|
* -webkit-app-region reliably on system WebKit; this view is stacked
|
|
22
50
|
* NSWindowAbove the web view so safe empty/title zones hit AppKit first.
|
|
@@ -584,6 +612,81 @@ extern "C" void requestMicrophonePermission(void) {
|
|
|
584
612
|
}];
|
|
585
613
|
}
|
|
586
614
|
|
|
615
|
+
extern "C" void freeNativeCString(char *value) {
|
|
616
|
+
if (value != nullptr) {
|
|
617
|
+
free(value);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
extern "C" char *createSecurityScopedBookmark(const char *path) {
|
|
622
|
+
@autoreleasepool {
|
|
623
|
+
if (path == nullptr || path[0] == '\0') {
|
|
624
|
+
return nullptr;
|
|
625
|
+
}
|
|
626
|
+
NSString *pathString = [NSString stringWithUTF8String:path];
|
|
627
|
+
if (pathString == nil) {
|
|
628
|
+
return nullptr;
|
|
629
|
+
}
|
|
630
|
+
NSURL *url = [NSURL fileURLWithPath:pathString isDirectory:YES];
|
|
631
|
+
if (url == nil) {
|
|
632
|
+
return nullptr;
|
|
633
|
+
}
|
|
634
|
+
NSError *error = nil;
|
|
635
|
+
NSData *bookmark = [url
|
|
636
|
+
bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
|
|
637
|
+
includingResourceValuesForKeys:nil
|
|
638
|
+
relativeToURL:nil
|
|
639
|
+
error:&error];
|
|
640
|
+
if (bookmark == nil || error != nil) {
|
|
641
|
+
return nullptr;
|
|
642
|
+
}
|
|
643
|
+
return elizaCopyCString([bookmark base64EncodedStringWithOptions:0]);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
extern "C" char *startAccessingSecurityScopedBookmark(const char *base64) {
|
|
648
|
+
@autoreleasepool {
|
|
649
|
+
if (base64 == nullptr || base64[0] == '\0') {
|
|
650
|
+
return nullptr;
|
|
651
|
+
}
|
|
652
|
+
NSString *base64String = [NSString stringWithUTF8String:base64];
|
|
653
|
+
if (base64String == nil) {
|
|
654
|
+
return nullptr;
|
|
655
|
+
}
|
|
656
|
+
NSData *bookmark = [[NSData alloc]
|
|
657
|
+
initWithBase64EncodedString:base64String
|
|
658
|
+
options:NSDataBase64DecodingIgnoreUnknownCharacters];
|
|
659
|
+
if (bookmark == nil) {
|
|
660
|
+
return nullptr;
|
|
661
|
+
}
|
|
662
|
+
BOOL stale = NO;
|
|
663
|
+
NSError *error = nil;
|
|
664
|
+
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark
|
|
665
|
+
options:NSURLBookmarkResolutionWithSecurityScope
|
|
666
|
+
relativeToURL:nil
|
|
667
|
+
bookmarkDataIsStale:&stale
|
|
668
|
+
error:&error];
|
|
669
|
+
if (url == nil || error != nil) {
|
|
670
|
+
return nullptr;
|
|
671
|
+
}
|
|
672
|
+
if (![url startAccessingSecurityScopedResource]) {
|
|
673
|
+
return nullptr;
|
|
674
|
+
}
|
|
675
|
+
[elizaSecurityScopedUrls() addObject:url];
|
|
676
|
+
return elizaCopyCString([url path]);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
extern "C" void stopAccessingSecurityScopedBookmarks(void) {
|
|
681
|
+
@autoreleasepool {
|
|
682
|
+
NSMutableArray<NSURL *> *urls = elizaSecurityScopedUrls();
|
|
683
|
+
for (NSURL *url in urls) {
|
|
684
|
+
[url stopAccessingSecurityScopedResource];
|
|
685
|
+
}
|
|
686
|
+
[urls removeAllObjects];
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
587
690
|
extern "C" bool enableWindowVibrancy(void *windowPtr) {
|
|
588
691
|
if (windowPtr == nullptr) {
|
|
589
692
|
return false;
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
"name": "@elizaos/electrobun",
|
|
3
3
|
"version": "2.0.0-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"assets",
|
|
7
|
+
"entitlements",
|
|
8
|
+
"scripts",
|
|
9
|
+
"src",
|
|
10
|
+
"electrobun.config.ts",
|
|
11
|
+
"README.md",
|
|
12
|
+
"tsconfig.json"
|
|
13
|
+
],
|
|
5
14
|
"scripts": {
|
|
6
15
|
"dev": "bun run build:preload && PATH=\"$PWD/scripts/bin:$PATH\" bunx electrobun dev",
|
|
7
16
|
"build": "bun run build:preload && ELECTROBUN_SKIP_CODESIGN=1 PATH=\"$PWD/scripts/bin:$PATH\" bunx electrobun build",
|
|
@@ -10,10 +10,26 @@ export const FFIType = {
|
|
|
10
10
|
f64: 2,
|
|
11
11
|
i32: 3,
|
|
12
12
|
cstring: 4,
|
|
13
|
+
void: 5,
|
|
13
14
|
} as const;
|
|
14
15
|
|
|
15
16
|
export type Pointer = number;
|
|
16
17
|
|
|
18
|
+
export class CString {
|
|
19
|
+
private readonly value: unknown;
|
|
20
|
+
constructor(ptr: unknown) {
|
|
21
|
+
this.value = ptr;
|
|
22
|
+
}
|
|
23
|
+
toString(): string {
|
|
24
|
+
void this.value;
|
|
25
|
+
return "";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function ptr(_value: ArrayBufferView): Pointer {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
export function dlopen(
|
|
18
34
|
_path: string,
|
|
19
35
|
_symbols: Record<string, unknown>,
|
|
Binary file
|
|
@@ -28,13 +28,13 @@ import crypto from "node:crypto";
|
|
|
28
28
|
import fs from "node:fs";
|
|
29
29
|
import os from "node:os";
|
|
30
30
|
import path from "node:path";
|
|
31
|
-
import { Utils } from "electrobun/bun";
|
|
32
31
|
import {
|
|
33
32
|
resolveApiToken,
|
|
34
33
|
resolveDesktopApiPort,
|
|
35
34
|
resolveDisableAutoApiToken,
|
|
36
35
|
setApiToken,
|
|
37
36
|
} from "@elizaos/shared";
|
|
37
|
+
import { Utils } from "electrobun/bun";
|
|
38
38
|
import { resolveDesktopRuntimeMode } from "../api-base";
|
|
39
39
|
import { getBrandConfig } from "../brand-config";
|
|
40
40
|
import { DEFAULT_API_PORT } from "../constants";
|
|
@@ -159,7 +159,8 @@ function normalizeEnvPath(value: string | undefined): string | null {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
function isStoreBuildVariant(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
162
|
-
const raw =
|
|
162
|
+
const raw =
|
|
163
|
+
env.MILADY_BUILD_VARIANT?.trim() || env.ELIZA_BUILD_VARIANT?.trim();
|
|
163
164
|
return raw?.toLowerCase() === "store";
|
|
164
165
|
}
|
|
165
166
|
|
|
@@ -229,7 +230,10 @@ function buildExistingElizaInstallCandidates(opts?: {
|
|
|
229
230
|
normalizeEnvPath(env.MILADY_CONFIG_PATH) ??
|
|
230
231
|
normalizeEnvPath(env.ELIZA_CONFIG_PATH);
|
|
231
232
|
const stateDirFromEnv = resolveExplicitStateDir(env);
|
|
232
|
-
const defaultStateDir = joinPortable(
|
|
233
|
+
const defaultStateDir = joinPortable(
|
|
234
|
+
homedir,
|
|
235
|
+
`.${resolveStateNamespace(env)}`,
|
|
236
|
+
);
|
|
233
237
|
|
|
234
238
|
const candidates = [
|
|
235
239
|
configPathFromEnv
|
|
@@ -316,6 +320,69 @@ export function inspectExistingElizaInstall(opts?: {
|
|
|
316
320
|
};
|
|
317
321
|
}
|
|
318
322
|
|
|
323
|
+
export function migrateDesktopStateDirFromPath(
|
|
324
|
+
fromPath: string,
|
|
325
|
+
opts?: { env?: NodeJS.ProcessEnv },
|
|
326
|
+
): StateDirMigrationResult {
|
|
327
|
+
const source = resolvePortablePath(fromPath);
|
|
328
|
+
const target = resolveDesktopChildStateDir({ env: opts?.env ?? process.env });
|
|
329
|
+
|
|
330
|
+
if (source === target) {
|
|
331
|
+
return {
|
|
332
|
+
ok: true,
|
|
333
|
+
migrated: false,
|
|
334
|
+
fromPath: source,
|
|
335
|
+
toPath: target,
|
|
336
|
+
skippedReason: "same-path",
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
try {
|
|
341
|
+
const stat = fs.statSync(source);
|
|
342
|
+
if (!stat.isDirectory()) {
|
|
343
|
+
return {
|
|
344
|
+
ok: true,
|
|
345
|
+
migrated: false,
|
|
346
|
+
fromPath: source,
|
|
347
|
+
toPath: target,
|
|
348
|
+
skippedReason: "source-not-directory",
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
} catch {
|
|
352
|
+
return {
|
|
353
|
+
ok: true,
|
|
354
|
+
migrated: false,
|
|
355
|
+
fromPath: source,
|
|
356
|
+
toPath: target,
|
|
357
|
+
skippedReason: "source-missing",
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
try {
|
|
362
|
+
fs.mkdirSync(target, { recursive: true });
|
|
363
|
+
fs.cpSync(source, target, {
|
|
364
|
+
recursive: true,
|
|
365
|
+
force: false,
|
|
366
|
+
errorOnExist: false,
|
|
367
|
+
dereference: false,
|
|
368
|
+
});
|
|
369
|
+
return {
|
|
370
|
+
ok: true,
|
|
371
|
+
migrated: true,
|
|
372
|
+
fromPath: source,
|
|
373
|
+
toPath: target,
|
|
374
|
+
};
|
|
375
|
+
} catch (err) {
|
|
376
|
+
return {
|
|
377
|
+
ok: false,
|
|
378
|
+
migrated: false,
|
|
379
|
+
fromPath: source,
|
|
380
|
+
toPath: target,
|
|
381
|
+
error: err instanceof Error ? err.message : String(err),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
319
386
|
// ---------------------------------------------------------------------------
|
|
320
387
|
// Diagnostic logging
|
|
321
388
|
// ---------------------------------------------------------------------------
|
|
@@ -1630,6 +1697,10 @@ export class AgentManager {
|
|
|
1630
1697
|
return inspectExistingElizaInstall();
|
|
1631
1698
|
}
|
|
1632
1699
|
|
|
1700
|
+
migrateStateDir(params: { fromPath: string }): StateDirMigrationResult {
|
|
1701
|
+
return migrateDesktopStateDirFromPath(params.fromPath);
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1633
1704
|
getPort(): number | null {
|
|
1634
1705
|
return this.status.port;
|
|
1635
1706
|
}
|
|
@@ -71,10 +71,13 @@ import {
|
|
|
71
71
|
getStartupDiagnosticsSnapshot,
|
|
72
72
|
} from "./agent";
|
|
73
73
|
import {
|
|
74
|
+
createSecurityScopedBookmark,
|
|
74
75
|
isAppActive,
|
|
75
76
|
isKeyWindow,
|
|
76
77
|
makeKeyAndOrderFront,
|
|
77
78
|
orderOut,
|
|
79
|
+
startAccessingSecurityScopedBookmark,
|
|
80
|
+
stopAccessingSecurityScopedBookmarks,
|
|
78
81
|
} from "./mac-window-effects";
|
|
79
82
|
import {
|
|
80
83
|
linuxSysfsOnBattery,
|
|
@@ -2018,11 +2021,8 @@ X-GNOME-Autostart-enabled=true
|
|
|
2018
2021
|
*
|
|
2019
2022
|
* The `bookmark` field is the OS-specific persistence handle: on macOS, a
|
|
2020
2023
|
* base64 NSURLBookmarkCreationOptions.WithSecurityScope blob the caller
|
|
2021
|
-
* stores and re-resolves on next launch.
|
|
2022
|
-
*
|
|
2023
|
-
* `bookmark: null` and rely on the picker re-prompt at next launch when
|
|
2024
|
-
* the path no longer resolves under the sandbox. TODO: wire into the
|
|
2025
|
-
* `native/` module's NSURL bookmark API to make grants persistent.
|
|
2024
|
+
* stores and re-resolves on next launch. Non-macOS platforms return null
|
|
2025
|
+
* because portals / AppContainer do not use NSURL bookmarks.
|
|
2026
2026
|
*/
|
|
2027
2027
|
async pickWorkspaceFolder(options: {
|
|
2028
2028
|
defaultPath?: string;
|
|
@@ -2038,7 +2038,40 @@ X-GNOME-Autostart-enabled=true
|
|
|
2038
2038
|
if (canceled) {
|
|
2039
2039
|
return { canceled: true, path: "", bookmark: null };
|
|
2040
2040
|
}
|
|
2041
|
-
|
|
2041
|
+
const selectedPath = filePaths[0] ?? "";
|
|
2042
|
+
if (!selectedPath) {
|
|
2043
|
+
return { canceled: true, path: "", bookmark: null };
|
|
2044
|
+
}
|
|
2045
|
+
const bookmark =
|
|
2046
|
+
process.platform === "darwin"
|
|
2047
|
+
? createSecurityScopedBookmark(selectedPath)
|
|
2048
|
+
: null;
|
|
2049
|
+
return { canceled: false, path: selectedPath, bookmark };
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
resolveWorkspaceFolderBookmark(options: { bookmark: string }): {
|
|
2053
|
+
ok: boolean;
|
|
2054
|
+
path: string;
|
|
2055
|
+
stale?: boolean;
|
|
2056
|
+
error?: string;
|
|
2057
|
+
} {
|
|
2058
|
+
if (process.platform !== "darwin") {
|
|
2059
|
+
return { ok: true, path: "" };
|
|
2060
|
+
}
|
|
2061
|
+
const path = startAccessingSecurityScopedBookmark(options.bookmark);
|
|
2062
|
+
if (!path) {
|
|
2063
|
+
return {
|
|
2064
|
+
ok: false,
|
|
2065
|
+
path: "",
|
|
2066
|
+
error: "Unable to resolve security-scoped bookmark.",
|
|
2067
|
+
};
|
|
2068
|
+
}
|
|
2069
|
+
return { ok: true, path };
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
releaseWorkspaceFolderBookmarks(): { ok: true } {
|
|
2073
|
+
stopAccessingSecurityScopedBookmarks();
|
|
2074
|
+
return { ok: true };
|
|
2042
2075
|
}
|
|
2043
2076
|
|
|
2044
2077
|
// MARK: - Helpers
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dlopen, FFIType, type Pointer } from "bun:ffi";
|
|
1
|
+
import { CString, dlopen, FFIType, type Pointer, ptr } from "bun:ffi";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
|
|
@@ -16,6 +16,10 @@ type MacEffectsSymbols = {
|
|
|
16
16
|
makeKeyAndOrderFrontWindow(ptr: Pointer): boolean;
|
|
17
17
|
isAppActive(): boolean;
|
|
18
18
|
isWindowKey(ptr: Pointer): boolean;
|
|
19
|
+
createSecurityScopedBookmark(path: Pointer): Pointer | null;
|
|
20
|
+
startAccessingSecurityScopedBookmark(bookmark: Pointer): Pointer | null;
|
|
21
|
+
stopAccessingSecurityScopedBookmarks(): void;
|
|
22
|
+
freeNativeCString(value: Pointer): void;
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
type LoadedMacEffectsLib = { symbols: MacEffectsSymbols; close(): void };
|
|
@@ -52,6 +56,19 @@ function loadLib(): MacEffectsLib {
|
|
|
52
56
|
},
|
|
53
57
|
isAppActive: { args: [], returns: FFIType.bool },
|
|
54
58
|
isWindowKey: { args: [FFIType.ptr], returns: FFIType.bool },
|
|
59
|
+
createSecurityScopedBookmark: {
|
|
60
|
+
args: [FFIType.ptr],
|
|
61
|
+
returns: FFIType.ptr,
|
|
62
|
+
},
|
|
63
|
+
startAccessingSecurityScopedBookmark: {
|
|
64
|
+
args: [FFIType.ptr],
|
|
65
|
+
returns: FFIType.ptr,
|
|
66
|
+
},
|
|
67
|
+
stopAccessingSecurityScopedBookmarks: {
|
|
68
|
+
args: [],
|
|
69
|
+
returns: FFIType.void,
|
|
70
|
+
},
|
|
71
|
+
freeNativeCString: { args: [FFIType.ptr], returns: FFIType.void },
|
|
55
72
|
}) as MacEffectsLib;
|
|
56
73
|
} catch (err) {
|
|
57
74
|
console.warn("[MacEffects] Failed to load dylib:", err);
|
|
@@ -59,6 +76,25 @@ function loadLib(): MacEffectsLib {
|
|
|
59
76
|
}
|
|
60
77
|
}
|
|
61
78
|
|
|
79
|
+
function cStringBuffer(value: string): Buffer {
|
|
80
|
+
const bytes = Buffer.from(value, "utf8");
|
|
81
|
+
const buffer = Buffer.alloc(bytes.byteLength + 1);
|
|
82
|
+
bytes.copy(buffer);
|
|
83
|
+
return buffer;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function takeNativeString(
|
|
87
|
+
lib: LoadedMacEffectsLib,
|
|
88
|
+
value: Pointer | null,
|
|
89
|
+
): string | null {
|
|
90
|
+
if (!value) return null;
|
|
91
|
+
try {
|
|
92
|
+
return new CString(value).toString();
|
|
93
|
+
} finally {
|
|
94
|
+
lib.symbols.freeNativeCString(value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
62
98
|
function getLib(): LoadedMacEffectsLib | null {
|
|
63
99
|
if (process.platform !== "darwin") return null;
|
|
64
100
|
if (_lib === undefined) {
|
|
@@ -116,3 +152,27 @@ export function isAppActive(): boolean {
|
|
|
116
152
|
export function isKeyWindow(ptr: Pointer): boolean {
|
|
117
153
|
return getLib()?.symbols.isWindowKey(ptr) ?? false;
|
|
118
154
|
}
|
|
155
|
+
|
|
156
|
+
export function createSecurityScopedBookmark(path: string): string | null {
|
|
157
|
+
const lib = getLib();
|
|
158
|
+
if (!lib || !path.trim()) return null;
|
|
159
|
+
const pathBuffer = cStringBuffer(path);
|
|
160
|
+
const result = lib.symbols.createSecurityScopedBookmark(ptr(pathBuffer));
|
|
161
|
+
return takeNativeString(lib, result);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function startAccessingSecurityScopedBookmark(
|
|
165
|
+
bookmark: string,
|
|
166
|
+
): string | null {
|
|
167
|
+
const lib = getLib();
|
|
168
|
+
if (!lib || !bookmark.trim()) return null;
|
|
169
|
+
const bookmarkBuffer = cStringBuffer(bookmark);
|
|
170
|
+
const result = lib.symbols.startAccessingSecurityScopedBookmark(
|
|
171
|
+
ptr(bookmarkBuffer),
|
|
172
|
+
);
|
|
173
|
+
return takeNativeString(lib, result);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function stopAccessingSecurityScopedBookmarks(): void {
|
|
177
|
+
getLib()?.symbols.stopAccessingSecurityScopedBookmarks();
|
|
178
|
+
}
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
|
|
17
17
|
export type SystemPermissionId = PermissionId;
|
|
18
18
|
|
|
19
|
-
/** Local variant
|
|
19
|
+
/** Local variant keeps a loose index signature for legacy Electrobun RPC code. */
|
|
20
20
|
export interface AllPermissionsState {
|
|
21
21
|
[key: string]: PermissionState;
|
|
22
22
|
}
|
|
@@ -133,7 +133,8 @@ export const SYSTEM_PERMISSIONS: SystemPermissionDefinition[] = [
|
|
|
133
133
|
{
|
|
134
134
|
id: "notifications",
|
|
135
135
|
name: "Notifications",
|
|
136
|
-
description:
|
|
136
|
+
description:
|
|
137
|
+
"Show system notifications for reminders and background results",
|
|
137
138
|
icon: "bell",
|
|
138
139
|
platforms: ["darwin", "win32", "linux"],
|
|
139
140
|
requiredForFeatures: ["notifications", "lifeops"],
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* Shared implementation ported forward to Electrobun; no runtime-specific APIs required.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { SendToWebview } from "../types.js";
|
|
9
8
|
import { ALL_PROBERS } from "@elizaos/agent/services/permissions/probers/index";
|
|
10
9
|
import { getMacPermissionDeepLink } from "@elizaos/shared";
|
|
10
|
+
import type { SendToWebview } from "../types.js";
|
|
11
11
|
import type {
|
|
12
12
|
AllPermissionsState,
|
|
13
13
|
PermissionState,
|
|
@@ -82,7 +82,8 @@ async function openPermissionSettings(id: SystemPermissionId): Promise<void> {
|
|
|
82
82
|
notifications: "notifications",
|
|
83
83
|
};
|
|
84
84
|
const panel = settingsMap[id];
|
|
85
|
-
if (panel)
|
|
85
|
+
if (panel)
|
|
86
|
+
await spawnDetached(["sh", "-lc", `gnome-control-center ${panel}`]);
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -177,10 +178,14 @@ export class PermissionManager {
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
if (id === "shell") {
|
|
180
|
-
const state = buildPermissionState(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
const state = buildPermissionState(
|
|
182
|
+
id,
|
|
183
|
+
this.shellEnabled ? "granted" : "denied",
|
|
184
|
+
{
|
|
185
|
+
canRequest: false,
|
|
186
|
+
lastRequested: Date.now(),
|
|
187
|
+
},
|
|
188
|
+
);
|
|
184
189
|
this.cache.set(id, state);
|
|
185
190
|
return state;
|
|
186
191
|
}
|
|
@@ -244,6 +244,8 @@ export function buildBunRpcHandlers({
|
|
|
244
244
|
},
|
|
245
245
|
agentStatus: async () => agent.getStatus(),
|
|
246
246
|
agentInspectExistingInstall: async () => agent.inspectExistingInstall(),
|
|
247
|
+
agentMigrateStateDir: async (params: { fromPath: string }) =>
|
|
248
|
+
agent.migrateStateDir(params),
|
|
247
249
|
/** Renderer `fetch` after native dialogs can stall; main POST matches menu reset pattern. */
|
|
248
250
|
agentPostReset: async (
|
|
249
251
|
params?: { apiBase?: string; bearerToken?: string } | null,
|
|
@@ -640,6 +642,11 @@ export function buildBunRpcHandlers({
|
|
|
640
642
|
desktopPickWorkspaceFolder: async (
|
|
641
643
|
params: Parameters<typeof desktop.pickWorkspaceFolder>[0],
|
|
642
644
|
) => desktop.pickWorkspaceFolder(params),
|
|
645
|
+
desktopResolveWorkspaceFolderBookmark: async (
|
|
646
|
+
params: Parameters<typeof desktop.resolveWorkspaceFolderBookmark>[0],
|
|
647
|
+
) => desktop.resolveWorkspaceFolderBookmark(params),
|
|
648
|
+
desktopReleaseWorkspaceFolderBookmarks: async () =>
|
|
649
|
+
desktop.releaseWorkspaceFolderBookmarks(),
|
|
643
650
|
|
|
644
651
|
// ---- Gateway ----
|
|
645
652
|
gatewayStartDiscovery: async (
|
|
@@ -40,6 +40,15 @@ export interface ExistingElizaInstallInfo {
|
|
|
40
40
|
source: ExistingElizaInstallSource;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export interface StateDirMigrationResult {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
migrated: boolean;
|
|
46
|
+
fromPath: string;
|
|
47
|
+
toPath: string;
|
|
48
|
+
error?: string;
|
|
49
|
+
skippedReason?: "same-path" | "source-missing" | "source-not-directory";
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
export interface TrayMenuItem {
|
|
44
53
|
id: string;
|
|
45
54
|
label?: string;
|
|
@@ -242,12 +251,14 @@ export interface DiscoveryResult {
|
|
|
242
251
|
|
|
243
252
|
// -- Permissions --
|
|
244
253
|
export type {
|
|
254
|
+
PermissionId,
|
|
245
255
|
PermissionState,
|
|
246
256
|
PermissionStatus,
|
|
247
|
-
SystemPermissionId,
|
|
248
257
|
} from "@elizaos/shared";
|
|
249
258
|
|
|
250
|
-
import type {
|
|
259
|
+
import type { PermissionId, PermissionState } from "@elizaos/shared";
|
|
260
|
+
|
|
261
|
+
export type SystemPermissionId = PermissionId;
|
|
251
262
|
|
|
252
263
|
/** Local variant uses an index signature (the canonical contract uses explicit keys). */
|
|
253
264
|
export interface AllPermissionsState {
|
|
@@ -432,8 +443,8 @@ export interface FileDialogResult {
|
|
|
432
443
|
* `path` — resolved absolute path (empty string when canceled).
|
|
433
444
|
* `canceled` — user dismissed the dialog without choosing.
|
|
434
445
|
* `bookmark` — opaque, OS-specific persistence handle (macOS security-scoped
|
|
435
|
-
* bookmark base64; null on platforms that do not require it
|
|
436
|
-
*
|
|
446
|
+
* bookmark base64; null on platforms that do not require it). Callers must
|
|
447
|
+
* persist it verbatim.
|
|
437
448
|
*/
|
|
438
449
|
export interface WorkspaceFolderPickResult {
|
|
439
450
|
canceled: boolean;
|
|
@@ -441,6 +452,13 @@ export interface WorkspaceFolderPickResult {
|
|
|
441
452
|
bookmark: string | null;
|
|
442
453
|
}
|
|
443
454
|
|
|
455
|
+
export interface WorkspaceFolderBookmarkResolveResult {
|
|
456
|
+
ok: boolean;
|
|
457
|
+
path: string;
|
|
458
|
+
stale?: boolean;
|
|
459
|
+
error?: string;
|
|
460
|
+
}
|
|
461
|
+
|
|
444
462
|
// -- Screen / Display --
|
|
445
463
|
export interface DisplayBounds {
|
|
446
464
|
x: number;
|
|
@@ -533,6 +551,10 @@ export type ElizaDesktopRPCSchema = {
|
|
|
533
551
|
params: undefined;
|
|
534
552
|
response: ExistingElizaInstallInfo;
|
|
535
553
|
};
|
|
554
|
+
agentMigrateStateDir: {
|
|
555
|
+
params: { fromPath: string };
|
|
556
|
+
response: StateDirMigrationResult;
|
|
557
|
+
};
|
|
536
558
|
agentPostReset: {
|
|
537
559
|
params: { apiBase?: string; bearerToken?: string } | undefined | null;
|
|
538
560
|
response: { ok: boolean; error?: string };
|
|
@@ -843,6 +865,14 @@ export type ElizaDesktopRPCSchema = {
|
|
|
843
865
|
params: { defaultPath?: string; promptTitle?: string };
|
|
844
866
|
response: WorkspaceFolderPickResult;
|
|
845
867
|
};
|
|
868
|
+
desktopResolveWorkspaceFolderBookmark: {
|
|
869
|
+
params: { bookmark: string };
|
|
870
|
+
response: WorkspaceFolderBookmarkResolveResult;
|
|
871
|
+
};
|
|
872
|
+
desktopReleaseWorkspaceFolderBookmarks: {
|
|
873
|
+
params: undefined;
|
|
874
|
+
response: { ok: true };
|
|
875
|
+
};
|
|
846
876
|
|
|
847
877
|
// ---- Gateway ----
|
|
848
878
|
gatewayStartDiscovery: {
|
|
@@ -1507,6 +1537,7 @@ export const CHANNEL_TO_RPC_METHOD: Record<string, string> = {
|
|
|
1507
1537
|
"agent:restartClearLocalDb": "agentRestartClearLocalDb",
|
|
1508
1538
|
"agent:status": "agentStatus",
|
|
1509
1539
|
"agent:inspectExistingInstall": "agentInspectExistingInstall",
|
|
1540
|
+
"agent:migrateStateDir": "agentMigrateStateDir",
|
|
1510
1541
|
"agent:postReset": "agentPostReset",
|
|
1511
1542
|
"agent:postCloudDisconnect": "agentPostCloudDisconnect",
|
|
1512
1543
|
"agent:cloudDisconnectWithConfirm": "agentCloudDisconnectWithConfirm",
|
|
@@ -1614,6 +1645,10 @@ export const CHANNEL_TO_RPC_METHOD: Record<string, string> = {
|
|
|
1614
1645
|
"desktop:showOpenDialog": "desktopShowOpenDialog",
|
|
1615
1646
|
"desktop:showSaveDialog": "desktopShowSaveDialog",
|
|
1616
1647
|
"desktop:pickWorkspaceFolder": "desktopPickWorkspaceFolder",
|
|
1648
|
+
"desktop:resolveWorkspaceFolderBookmark":
|
|
1649
|
+
"desktopResolveWorkspaceFolderBookmark",
|
|
1650
|
+
"desktop:releaseWorkspaceFolderBookmarks":
|
|
1651
|
+
"desktopReleaseWorkspaceFolderBookmarks",
|
|
1617
1652
|
|
|
1618
1653
|
// Gateway
|
|
1619
1654
|
"gateway:startDiscovery": "gatewayStartDiscovery",
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
SystemPermissionId,
|
|
7
7
|
} from "./native/permissions-shared";
|
|
8
8
|
|
|
9
|
-
export const RUNTIME_PERMISSION_IDS = ["website-blocking"
|
|
9
|
+
export const RUNTIME_PERMISSION_IDS = ["website-blocking"] as const;
|
|
10
10
|
|
|
11
11
|
type RuntimePermissionId = (typeof RUNTIME_PERMISSION_IDS)[number];
|
|
12
12
|
type RuntimePermissionOperation = "check" | "request" | "open-settings";
|
|
@@ -39,6 +39,12 @@ export function buildRuntimePermissionUnavailableState(
|
|
|
39
39
|
status: "denied",
|
|
40
40
|
lastChecked: Date.now(),
|
|
41
41
|
canRequest: false,
|
|
42
|
+
platform:
|
|
43
|
+
process.platform === "darwin" ||
|
|
44
|
+
process.platform === "win32" ||
|
|
45
|
+
process.platform === "linux"
|
|
46
|
+
? process.platform
|
|
47
|
+
: "linux",
|
|
42
48
|
reason,
|
|
43
49
|
};
|
|
44
50
|
}
|
|
@@ -20,5 +20,6 @@
|
|
|
20
20
|
* Parallels `ensure-text-to-speech-handler.ts` — same shape, same guards.
|
|
21
21
|
*/
|
|
22
22
|
import { type AgentRuntime } from "@elizaos/core";
|
|
23
|
+
export declare function shouldRegisterLocalInferenceHandlers(mode: string): boolean;
|
|
23
24
|
export declare function ensureLocalInferenceHandler(runtime: AgentRuntime): Promise<void>;
|
|
24
25
|
//# sourceMappingURL=ensure-local-inference-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-local-inference-handler.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/ensure-local-inference-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,KAAK,YAAY,EAMlB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ensure-local-inference-handler.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/ensure-local-inference-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,KAAK,YAAY,EAMlB,MAAM,eAAe,CAAC;AAoEvB,wBAAgB,oCAAoC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1E;AAiSD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CA+Jf"}
|