ltcai 8.5.0 → 8.7.0
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/README.md +35 -33
- package/desktop/electron/main.cjs +13 -1
- package/desktop/electron/preload.cjs +5 -0
- package/docs/CHANGELOG.md +46 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +5 -3
- package/docs/DEVELOPMENT.md +11 -9
- package/docs/LEGACY_COMPATIBILITY.md +3 -3
- package/docs/ONBOARDING.md +4 -4
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +2 -2
- package/docs/kg-schema.md +1 -1
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/app_factory.py +2 -2
- package/latticeai/core/config.py +14 -2
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/models/router.py +3 -2
- package/latticeai/runtime/router_registration.py +11 -5
- package/latticeai/services/architecture_readiness.py +2 -2
- package/latticeai/services/model_runtime.py +52 -28
- package/latticeai/services/product_readiness.py +11 -11
- package/package.json +3 -2
- package/scripts/bump_version.py +2 -0
- package/scripts/check_python.py +25 -12
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/capabilities/default.json +3 -0
- package/src-tauri/src/main.rs +32 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +11 -11
- package/static/app/assets/{Act-D5mo4tE4.js → Act-_U7mhXir.js} +1 -1
- package/static/app/assets/{Brain-BVWyQw8A.js → Brain-BxyTHZ21.js} +2 -2
- package/static/app/assets/Capture-DyDKWNh9.js +1 -0
- package/static/app/assets/Library-DJ8KioFM.js +1 -0
- package/static/app/assets/System-C0FIb3OO.js +1 -0
- package/static/app/assets/index-Bh7IIlyY.js +16 -0
- package/static/app/assets/index-_M5aCv21.css +2 -0
- package/static/app/assets/primitives-BywkNS3f.js +1 -0
- package/static/app/assets/{textarea-e7qaj6Hm.js → textarea-CQ61Rycp.js} +1 -1
- package/static/app/index.html +2 -2
- package/static/app/theme-boot.js +2 -2
- package/static/sw.js +1 -1
- package/static/app/assets/Capture-C1R6GT0t.js +0 -1
- package/static/app/assets/Library-C2wIxpTs.js +0 -1
- package/static/app/assets/System-DE5GRyQR.js +0 -1
- package/static/app/assets/index-CoiuIFFP.js +0 -16
- package/static/app/assets/index-ty1iGgZu.css +0 -2
- package/static/app/assets/primitives-BdsUNXa6.js +0 -1
|
@@ -16,6 +16,7 @@ import shutil
|
|
|
16
16
|
import time
|
|
17
17
|
import urllib.error
|
|
18
18
|
import urllib.request
|
|
19
|
+
import warnings
|
|
19
20
|
from pathlib import Path
|
|
20
21
|
from typing import AsyncIterator, Dict, List, Optional
|
|
21
22
|
|
|
@@ -100,6 +101,21 @@ class ModelRuntimeState:
|
|
|
100
101
|
self.get_user_api_key = _missing_user_api_key
|
|
101
102
|
|
|
102
103
|
def sync_to_module_globals(self):
|
|
104
|
+
"""Sync to bare module globals for legacy external importers.
|
|
105
|
+
|
|
106
|
+
This is a compatibility surface only. Internal code should use STATE.
|
|
107
|
+
Emits DeprecationWarning (future removal in major after 8.x).
|
|
108
|
+
"""
|
|
109
|
+
warnings.warn(
|
|
110
|
+
"sync_to_module_globals is a legacy compatibility shim and will be removed "
|
|
111
|
+
"after 8.x. Use latticeai.services.model_runtime.STATE or injected context instead.",
|
|
112
|
+
DeprecationWarning,
|
|
113
|
+
stacklevel=2,
|
|
114
|
+
)
|
|
115
|
+
self._sync_globals()
|
|
116
|
+
|
|
117
|
+
def _sync_globals(self) -> None:
|
|
118
|
+
"""Internal no-warning sync used at init."""
|
|
103
119
|
global router, APP_MODE, DEFAULT_HOST, DEFAULT_PORT, DATA_DIR, BASE_DIR
|
|
104
120
|
global ENABLE_TELEGRAM, ENABLE_GRAPH, AUTOLOAD_MODELS, MODEL_IDLE_UNLOAD_SECONDS
|
|
105
121
|
global ALLOW_LOCAL_MODELS, REQUIRE_AUTH, INVITE_GATE_ENABLED, ALLOW_PLAINTEXT_API_KEYS
|
|
@@ -128,7 +144,7 @@ class ModelRuntimeState:
|
|
|
128
144
|
get_user_api_key = self.get_user_api_key
|
|
129
145
|
|
|
130
146
|
STATE = ModelRuntimeState()
|
|
131
|
-
STATE.
|
|
147
|
+
STATE._sync_globals() # initial no-warning; public API warns on explicit legacy syncs
|
|
132
148
|
|
|
133
149
|
# Configured by server_app.configure_model_runtime during app assembly.
|
|
134
150
|
|
|
@@ -141,7 +157,9 @@ def _env_bool(key: str, default: bool = False) -> bool:
|
|
|
141
157
|
|
|
142
158
|
|
|
143
159
|
def _download_allowed(allow_download: bool = False) -> bool:
|
|
144
|
-
|
|
160
|
+
# Prefer STATE (the source of truth) over bare module global for internal logic.
|
|
161
|
+
autoload = getattr(STATE, "AUTOLOAD_MODELS", AUTOLOAD_MODELS)
|
|
162
|
+
return bool(allow_download) or _env_bool("LATTICEAI_ALLOW_MODEL_DOWNLOADS", default=False) or bool(autoload)
|
|
145
163
|
|
|
146
164
|
|
|
147
165
|
def _download_block(provider: str, model_name: str) -> None:
|
|
@@ -204,7 +222,7 @@ def configure_model_runtime(**deps) -> None:
|
|
|
204
222
|
elif key == "get_user_api_key":
|
|
205
223
|
STATE.get_user_api_key = value
|
|
206
224
|
|
|
207
|
-
STATE.
|
|
225
|
+
STATE._sync_globals() # wiring path uses internal (no spurious deprecation in normal startup)
|
|
208
226
|
|
|
209
227
|
|
|
210
228
|
# Catalog data + version-dedup helpers live in ``model_catalog``; re-exported
|
|
@@ -727,7 +745,8 @@ def engine_installed(engine: str) -> bool:
|
|
|
727
745
|
return False
|
|
728
746
|
|
|
729
747
|
def engine_status() -> List[Dict]:
|
|
730
|
-
|
|
748
|
+
r = getattr(STATE, "router", None) or router
|
|
749
|
+
cloud_models = r.detected_cloud_models() if r else []
|
|
731
750
|
cloud_by_provider = {}
|
|
732
751
|
for model in cloud_models:
|
|
733
752
|
cloud_by_provider.setdefault(model["provider"], []).append(model)
|
|
@@ -887,37 +906,41 @@ def engine_status() -> List[Dict]:
|
|
|
887
906
|
return engines
|
|
888
907
|
|
|
889
908
|
def runtime_features() -> Dict:
|
|
909
|
+
# Read from STATE object (central) for implementation; bare globals kept only
|
|
910
|
+
# for external legacy consumers who import names directly from this module.
|
|
911
|
+
s = STATE
|
|
912
|
+
r = getattr(s, "router", None) or router
|
|
890
913
|
return {
|
|
891
|
-
"mode": APP_MODE,
|
|
892
|
-
"public": IS_PUBLIC_MODE,
|
|
893
|
-
"host": DEFAULT_HOST,
|
|
894
|
-
"port": DEFAULT_PORT,
|
|
895
|
-
"data_dir": str(DATA_DIR),
|
|
896
|
-
"telegram_enabled": ENABLE_TELEGRAM,
|
|
897
|
-
"graph_enabled": ENABLE_GRAPH,
|
|
898
|
-
"autoload_models": AUTOLOAD_MODELS,
|
|
899
|
-
"model_idle_unload_seconds": MODEL_IDLE_UNLOAD_SECONDS,
|
|
900
|
-
"model_memory_policy":
|
|
901
|
-
"allow_local_models": ALLOW_LOCAL_MODELS,
|
|
914
|
+
"mode": s.APP_MODE,
|
|
915
|
+
"public": s.IS_PUBLIC_MODE,
|
|
916
|
+
"host": s.DEFAULT_HOST,
|
|
917
|
+
"port": s.DEFAULT_PORT,
|
|
918
|
+
"data_dir": str(s.DATA_DIR),
|
|
919
|
+
"telegram_enabled": s.ENABLE_TELEGRAM,
|
|
920
|
+
"graph_enabled": s.ENABLE_GRAPH,
|
|
921
|
+
"autoload_models": s.AUTOLOAD_MODELS,
|
|
922
|
+
"model_idle_unload_seconds": s.MODEL_IDLE_UNLOAD_SECONDS,
|
|
923
|
+
"model_memory_policy": r.model_memory_policy() if r else None,
|
|
924
|
+
"allow_local_models": s.ALLOW_LOCAL_MODELS,
|
|
902
925
|
"security": {
|
|
903
|
-
"host": DEFAULT_HOST,
|
|
904
|
-
"require_auth": REQUIRE_AUTH,
|
|
905
|
-
"invite_gate_enabled": INVITE_GATE_ENABLED,
|
|
906
|
-
"keyring_available": keyring is not None,
|
|
907
|
-
"plaintext_api_keys_allowed": ALLOW_PLAINTEXT_API_KEYS,
|
|
908
|
-
"cors_allow_network": CORS_ALLOW_NETWORK,
|
|
926
|
+
"host": s.DEFAULT_HOST,
|
|
927
|
+
"require_auth": s.REQUIRE_AUTH,
|
|
928
|
+
"invite_gate_enabled": s.INVITE_GATE_ENABLED,
|
|
929
|
+
"keyring_available": s.keyring is not None,
|
|
930
|
+
"plaintext_api_keys_allowed": s.ALLOW_PLAINTEXT_API_KEYS,
|
|
931
|
+
"cors_allow_network": s.CORS_ALLOW_NETWORK,
|
|
909
932
|
},
|
|
910
|
-
"default_model": PUBLIC_MODEL if IS_PUBLIC_MODE else LOCAL_MODEL,
|
|
933
|
+
"default_model": s.PUBLIC_MODEL if s.IS_PUBLIC_MODE else s.LOCAL_MODEL,
|
|
911
934
|
"local_only_features": {
|
|
912
|
-
"mlx": ALLOW_LOCAL_MODELS and not IS_PUBLIC_MODE,
|
|
913
|
-
"telegram_bridge": ENABLE_TELEGRAM,
|
|
914
|
-
"desktop_chrome_bridge": not IS_PUBLIC_MODE,
|
|
915
|
-
"computer_use_bridge": not IS_PUBLIC_MODE,
|
|
935
|
+
"mlx": s.ALLOW_LOCAL_MODELS and not s.IS_PUBLIC_MODE,
|
|
936
|
+
"telegram_bridge": s.ENABLE_TELEGRAM,
|
|
937
|
+
"desktop_chrome_bridge": not s.IS_PUBLIC_MODE,
|
|
938
|
+
"computer_use_bridge": not s.IS_PUBLIC_MODE,
|
|
916
939
|
},
|
|
917
940
|
"public_features": {
|
|
918
941
|
"web_ui": True,
|
|
919
942
|
"openai_compatible_models": True,
|
|
920
|
-
"persistent_data_dir": str(DATA_DIR),
|
|
943
|
+
"persistent_data_dir": str(s.DATA_DIR),
|
|
921
944
|
},
|
|
922
945
|
}
|
|
923
946
|
|
|
@@ -1099,7 +1122,8 @@ async def _probe_cloud_model(model_ref: str) -> Dict[str, object]:
|
|
|
1099
1122
|
|
|
1100
1123
|
async def verify_cloud_models(force: bool = False, provider_filter: Optional[str] = None) -> Dict[str, Dict]:
|
|
1101
1124
|
now = time.time()
|
|
1102
|
-
|
|
1125
|
+
r = getattr(STATE, "router", None) or router
|
|
1126
|
+
cloud_items = [item for item in (r.detected_cloud_models() if r else []) if item.get("tag") == "cloud"]
|
|
1103
1127
|
if provider_filter:
|
|
1104
1128
|
cloud_items = [item for item in cloud_items if item.get("provider") == provider_filter]
|
|
1105
1129
|
|
|
@@ -18,7 +18,7 @@ from typing import Any, Dict, List
|
|
|
18
18
|
|
|
19
19
|
from latticeai.services.architecture_readiness import architecture_readiness
|
|
20
20
|
|
|
21
|
-
PRODUCT_VERSION_TARGET = "8.
|
|
21
|
+
PRODUCT_VERSION_TARGET = "8.7.0"
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@dataclass(frozen=True)
|
|
@@ -76,10 +76,10 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
76
76
|
evidence=[
|
|
77
77
|
"package.json::release:artifacts",
|
|
78
78
|
"package.json::release:validate",
|
|
79
|
-
"README.md::dist/ltcai-8.
|
|
80
|
-
"README.md::dist/ltcai-8.
|
|
81
|
-
"README.md::dist/ltcai-8.
|
|
82
|
-
"README.md::ltcai-8.
|
|
79
|
+
"README.md::dist/ltcai-8.7.0-py3-none-any.whl",
|
|
80
|
+
"README.md::dist/ltcai-8.7.0.tar.gz",
|
|
81
|
+
"README.md::dist/ltcai-8.7.0.vsix",
|
|
82
|
+
"README.md::ltcai-8.7.0.tgz",
|
|
83
83
|
"scripts/validate_release_artifacts.py",
|
|
84
84
|
"scripts/release_smoke.py",
|
|
85
85
|
"Dockerfile",
|
|
@@ -95,12 +95,12 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
95
95
|
title="Release story is documented and honest",
|
|
96
96
|
evidence=[
|
|
97
97
|
"README.md",
|
|
98
|
-
"README.md::The current release is **8.
|
|
99
|
-
"SECURITY.md::8.
|
|
100
|
-
"vscode-extension/README.md::**8.
|
|
101
|
-
"docs/CHANGELOG.md::## [8.
|
|
98
|
+
"README.md::The current release is **8.7.0",
|
|
99
|
+
"SECURITY.md::8.7.x (latest)",
|
|
100
|
+
"vscode-extension/README.md::**8.7.0",
|
|
101
|
+
"docs/CHANGELOG.md::## [8.7.0]",
|
|
102
102
|
"FEATURE_STATUS.md",
|
|
103
|
-
"RELEASE_NOTES_v8.
|
|
103
|
+
"RELEASE_NOTES_v8.7.0.md",
|
|
104
104
|
"latticeai/core/agent.py::SingleAgentRuntime",
|
|
105
105
|
"latticeai/core/agent.py::AgentRuntime = SingleAgentRuntime",
|
|
106
106
|
"lattice_brain/runtime/contracts.py::runtime-boundary/v1",
|
|
@@ -115,7 +115,7 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
115
115
|
id="ecosystem-path",
|
|
116
116
|
title="Community and plugin growth path is explicit",
|
|
117
117
|
evidence=[
|
|
118
|
-
"docs/COMMUNITY_AND_PLUGINS.md::8.
|
|
118
|
+
"docs/COMMUNITY_AND_PLUGINS.md::8.7.0",
|
|
119
119
|
"docs/PLUGIN_SDK.md",
|
|
120
120
|
"plugins/README.md",
|
|
121
121
|
"plugins/hello-world/plugin.json",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ltcai",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.7.0",
|
|
4
4
|
"description": "Lattice AI — local-first Digital Brain that keeps your knowledge durable across any AI model.",
|
|
5
5
|
"homepage": "https://github.com/TaeSooPark-PTS/LatticeAI#readme",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"build:assets": "vite build && node scripts/build_frontend_assets.mjs",
|
|
24
24
|
"build:python": "node scripts/run_python.mjs -m build",
|
|
25
25
|
"check:python": "node scripts/run_python.mjs scripts/check_python.py",
|
|
26
|
-
"lint": "node --check tests/visual/mock_server.cjs && node --check tests/visual/v3.spec.js && npm run lint:frontend && node scripts/check_i18n_literals.mjs",
|
|
26
|
+
"lint": "npm run lint:python && node --check tests/visual/mock_server.cjs && node --check tests/visual/v3.spec.js && npm run lint:frontend && node scripts/check_i18n_literals.mjs",
|
|
27
|
+
"lint:python": "node scripts/run_python.mjs -m ruff check .",
|
|
27
28
|
"lint:frontend": "node scripts/lint_frontend.mjs",
|
|
28
29
|
"docs:check-links": "node scripts/check_markdown_links.mjs",
|
|
29
30
|
"typecheck": "npm run typecheck:frontend && cd vscode-extension && npm run build",
|
package/scripts/bump_version.py
CHANGED
|
@@ -27,6 +27,8 @@ TARGETS = [
|
|
|
27
27
|
("latticeai/core/workspace_os.py", "regex", r'(WORKSPACE_OS_VERSION = ")([^"]+)(")'),
|
|
28
28
|
("latticeai/core/marketplace.py", "regex", r'(MARKETPLACE_VERSION = ")([^"]+)(")'),
|
|
29
29
|
("lattice_brain/runtime/multi_agent.py", "regex", r'(MULTI_AGENT_VERSION = ")([^"]+)(")'),
|
|
30
|
+
("latticeai/services/architecture_readiness.py", "regex", r'(ARCHITECTURE_VERSION_TARGET = ")([^"]+)(")'),
|
|
31
|
+
("latticeai/services/product_readiness.py", "regex", r'(PRODUCT_VERSION_TARGET = ")([^"]+)(")'),
|
|
30
32
|
("pyproject.toml", "regex", r'(^version = ")([^"]+)(")'),
|
|
31
33
|
("package.json", "json", "version"),
|
|
32
34
|
("package-lock.json", "package-lock", None),
|
package/scripts/check_python.py
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Discover-and-
|
|
2
|
+
"""Discover-and-syntax-check every first-party Python module.
|
|
3
3
|
|
|
4
4
|
Replaces the hand-maintained ``py_compile`` enumeration in CI and
|
|
5
5
|
``package.json``: walks the repository, skips vendored / virtualenv / build /
|
|
6
|
-
cache / generated directories, and
|
|
6
|
+
cache / generated directories, and checks everything that remains. New
|
|
7
7
|
modules are picked up automatically — there is nothing to update when a file is
|
|
8
8
|
added, so the syntax gate can never silently fall behind the codebase.
|
|
9
9
|
|
|
10
|
+
Unlike ``py_compile``, this script does not write ``.pyc`` files or create
|
|
11
|
+
``__pycache__`` directories. Validation should not dirty a developer's working
|
|
12
|
+
tree or leave generated files for later lint passes to trip over.
|
|
13
|
+
|
|
10
14
|
Usage::
|
|
11
15
|
|
|
12
|
-
python scripts/check_python.py #
|
|
13
|
-
python scripts/check_python.py --list # just print what would be
|
|
16
|
+
python scripts/check_python.py # syntax-check all discovered modules
|
|
17
|
+
python scripts/check_python.py --list # just print what would be checked
|
|
14
18
|
|
|
15
|
-
Exit code is non-zero if any module fails to
|
|
19
|
+
Exit code is non-zero if any module fails to parse.
|
|
16
20
|
"""
|
|
17
21
|
|
|
18
22
|
from __future__ import annotations
|
|
19
23
|
|
|
20
|
-
import py_compile
|
|
21
24
|
import sys
|
|
22
25
|
from pathlib import Path
|
|
23
26
|
|
|
@@ -44,6 +47,7 @@ EXCLUDE_DIRS = {
|
|
|
44
47
|
"playwright-report",
|
|
45
48
|
"test-results",
|
|
46
49
|
"ltcai.egg-info",
|
|
50
|
+
"output",
|
|
47
51
|
".ltcai",
|
|
48
52
|
".ltcai-brain",
|
|
49
53
|
".ltcai-test",
|
|
@@ -60,6 +64,16 @@ def iter_modules():
|
|
|
60
64
|
yield path
|
|
61
65
|
|
|
62
66
|
|
|
67
|
+
def check_syntax(path: Path) -> str | None:
|
|
68
|
+
"""Return a human-readable failure string, or ``None`` when syntax is valid."""
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
compile(path.read_bytes(), str(path), "exec", dont_inherit=True)
|
|
72
|
+
except (OSError, SyntaxError, ValueError) as exc:
|
|
73
|
+
return f"{path.relative_to(ROOT)}: {exc}"
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
63
77
|
def main(argv: list[str]) -> int:
|
|
64
78
|
modules = sorted(iter_modules())
|
|
65
79
|
if "--list" in argv:
|
|
@@ -69,17 +83,16 @@ def main(argv: list[str]) -> int:
|
|
|
69
83
|
|
|
70
84
|
failures: list[str] = []
|
|
71
85
|
for path in modules:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
failures.append(str(exc))
|
|
86
|
+
failure = check_syntax(path)
|
|
87
|
+
if failure:
|
|
88
|
+
failures.append(failure)
|
|
76
89
|
|
|
77
90
|
if failures:
|
|
78
91
|
print("\n".join(failures))
|
|
79
|
-
print(f"check:python FAILED — {len(failures)} of {len(modules)} module(s) did not
|
|
92
|
+
print(f"check:python FAILED — {len(failures)} of {len(modules)} module(s) did not parse")
|
|
80
93
|
return 1
|
|
81
94
|
|
|
82
|
-
print(f"check:python OK —
|
|
95
|
+
print(f"check:python OK — syntax-checked {len(modules)} modules")
|
|
83
96
|
return 0
|
|
84
97
|
|
|
85
98
|
|
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
package/src-tauri/src/main.rs
CHANGED
|
@@ -66,6 +66,36 @@ fn shutdown_backend(state: State<'_, BackendState>) -> BackendStatus {
|
|
|
66
66
|
status_from_state(&state)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
#[tauri::command]
|
|
70
|
+
fn select_folder() -> Option<String> {
|
|
71
|
+
native_select_folder()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#[cfg(target_os = "macos")]
|
|
75
|
+
fn native_select_folder() -> Option<String> {
|
|
76
|
+
let output = Command::new("osascript")
|
|
77
|
+
.args([
|
|
78
|
+
"-e",
|
|
79
|
+
r#"POSIX path of (choose folder with prompt "Choose a folder for Lattice AI")"#,
|
|
80
|
+
])
|
|
81
|
+
.output()
|
|
82
|
+
.ok()?;
|
|
83
|
+
if !output.status.success() {
|
|
84
|
+
return None;
|
|
85
|
+
}
|
|
86
|
+
let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
87
|
+
if path.is_empty() {
|
|
88
|
+
None
|
|
89
|
+
} else {
|
|
90
|
+
Some(path)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#[cfg(not(target_os = "macos"))]
|
|
95
|
+
fn native_select_folder() -> Option<String> {
|
|
96
|
+
None
|
|
97
|
+
}
|
|
98
|
+
|
|
69
99
|
fn split_command(command: &str) -> Vec<String> {
|
|
70
100
|
command.split_whitespace().map(|part| part.to_string()).collect()
|
|
71
101
|
}
|
|
@@ -379,7 +409,8 @@ fn main() {
|
|
|
379
409
|
backend_origin,
|
|
380
410
|
backend_status,
|
|
381
411
|
restart_backend,
|
|
382
|
-
shutdown_backend
|
|
412
|
+
shutdown_backend,
|
|
413
|
+
select_folder
|
|
383
414
|
])
|
|
384
415
|
.setup(|app| {
|
|
385
416
|
if let Some(window) = app.get_webview_window("main") {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "8.
|
|
2
|
+
"version": "8.7.0",
|
|
3
3
|
"generated_at": "vite",
|
|
4
4
|
"entrypoints": {
|
|
5
|
-
"app": "/static/app/assets/index-
|
|
5
|
+
"app": "/static/app/assets/index-Bh7IIlyY.js"
|
|
6
6
|
},
|
|
7
7
|
"assets": {
|
|
8
8
|
"../node_modules/@tauri-apps/api/core.js": "/static/app/assets/core-CwxXejkd.js",
|
|
9
|
-
"_primitives-
|
|
10
|
-
"_textarea-
|
|
11
|
-
"index.html": "/static/app/assets/index-
|
|
12
|
-
"assets/index-
|
|
13
|
-
"src/pages/Act.tsx": "/static/app/assets/Act-
|
|
14
|
-
"src/pages/Brain.tsx": "/static/app/assets/Brain-
|
|
15
|
-
"src/pages/Capture.tsx": "/static/app/assets/Capture-
|
|
16
|
-
"src/pages/Library.tsx": "/static/app/assets/Library-
|
|
17
|
-
"src/pages/System.tsx": "/static/app/assets/System-
|
|
9
|
+
"_primitives-BywkNS3f.js": "/static/app/assets/primitives-BywkNS3f.js",
|
|
10
|
+
"_textarea-CQ61Rycp.js": "/static/app/assets/textarea-CQ61Rycp.js",
|
|
11
|
+
"index.html": "/static/app/assets/index-Bh7IIlyY.js",
|
|
12
|
+
"assets/index-_M5aCv21.css": "/static/app/assets/index-_M5aCv21.css",
|
|
13
|
+
"src/pages/Act.tsx": "/static/app/assets/Act-_U7mhXir.js",
|
|
14
|
+
"src/pages/Brain.tsx": "/static/app/assets/Brain-BxyTHZ21.js",
|
|
15
|
+
"src/pages/Capture.tsx": "/static/app/assets/Capture-DyDKWNh9.js",
|
|
16
|
+
"src/pages/Library.tsx": "/static/app/assets/Library-DJ8KioFM.js",
|
|
17
|
+
"src/pages/System.tsx": "/static/app/assets/System-C0FIb3OO.js"
|
|
18
18
|
}
|
|
19
19
|
}
|