ltcai 8.7.0 → 8.9.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 +38 -26
- package/auto_setup.py +73 -8
- package/docs/CHANGELOG.md +63 -0
- package/docs/CODE_REVIEW_2026-07-06.md +764 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +4 -3
- package/docs/DEVELOPMENT.md +10 -10
- package/docs/LEGACY_COMPATIBILITY.md +33 -14
- package/docs/ONBOARDING.md +2 -2
- package/docs/PRODUCT_DIRECTION_REVIEW.md +3 -2
- package/docs/TRUST_MODEL.md +5 -1
- package/docs/WHY_LATTICE.md +4 -3
- package/docs/architecture.md +4 -0
- package/docs/kg-schema.md +1 -1
- package/kg_schema.py +1 -1
- package/knowledge_graph.py +2 -2
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/conversations.py +156 -21
- package/lattice_brain/core.py +1 -1
- package/lattice_brain/graph/_kg_common.py +12 -34
- package/lattice_brain/graph/json_utils.py +25 -0
- package/lattice_brain/graph/retrieval.py +66 -27
- package/lattice_brain/graph/runtime.py +16 -0
- package/lattice_brain/ingestion.py +35 -20
- package/lattice_brain/runtime/agent_runtime.py +37 -3
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/chat.py +31 -14
- package/latticeai/api/mcp.py +3 -2
- package/latticeai/api/models.py +4 -1
- package/latticeai/api/permissions.py +69 -30
- package/latticeai/api/setup.py +17 -2
- package/latticeai/api/tools.py +104 -62
- package/latticeai/app_factory.py +93 -10
- package/latticeai/core/agent.py +25 -7
- package/latticeai/core/legacy_compatibility.py +36 -25
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/sessions.py +11 -3
- package/latticeai/core/tool_registry.py +15 -4
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/runtime/bootstrap.py +1 -1
- package/latticeai/runtime/persistence_runtime.py +1 -1
- package/latticeai/runtime/platform_services_runtime.py +1 -1
- package/latticeai/services/app_context.py +1 -0
- package/latticeai/services/architecture_readiness.py +2 -2
- package/latticeai/services/memory_service.py +38 -7
- package/latticeai/services/model_engines.py +79 -12
- package/latticeai/services/model_runtime.py +24 -4
- package/latticeai/services/process_audit.py +208 -0
- package/latticeai/services/product_readiness.py +11 -11
- package/latticeai/services/search_service.py +106 -30
- package/latticeai/services/tool_dispatch.py +66 -0
- package/latticeai/services/workspace_service.py +15 -0
- package/package.json +1 -1
- package/scripts/check_i18n_literals.mjs +20 -8
- package/scripts/i18n_literal_allowlist.json +34 -0
- package/scripts/lint_frontend.mjs +6 -2
- package/setup_wizard.py +185 -19
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +11 -11
- package/static/app/assets/{Act-_U7mhXir.js → Act-fZokUnC0.js} +1 -1
- package/static/app/assets/{Brain-BxyTHZ21.js → Brain-DtyuWubr.js} +2 -2
- package/static/app/assets/{Capture-DyDKWNh9.js → Capture-D5KV3Cu7.js} +1 -1
- package/static/app/assets/{Library-DJ8KioFM.js → Library-C9kyFkSt.js} +1 -1
- package/static/app/assets/{System-C0FIb3OO.js → System-VbChmX7r.js} +1 -1
- package/static/app/assets/index-DCh5AoXt.css +2 -0
- package/static/app/assets/index-DPdcPoF0.js +17 -0
- package/static/app/assets/{primitives-BywkNS3f.js → primitives-DFeanEV6.js} +1 -1
- package/static/app/assets/{textarea-CQ61Rycp.js → textarea-CD8UNKIy.js} +1 -1
- package/static/app/index.html +2 -2
- package/static/sw.js +1 -1
- package/lattice_brain/_kg_common.py +0 -11
- package/lattice_brain/discovery.py +0 -11
- package/lattice_brain/documents.py +0 -11
- package/lattice_brain/identity.py +0 -11
- package/lattice_brain/ingest.py +0 -11
- package/lattice_brain/network.py +0 -11
- package/lattice_brain/projection.py +0 -11
- package/lattice_brain/provenance.py +0 -11
- package/lattice_brain/retrieval.py +0 -11
- package/lattice_brain/schema.py +0 -11
- package/lattice_brain/store.py +0 -11
- package/lattice_brain/write_master.py +0 -11
- package/latticeai/brain/__init__.py +0 -36
- package/latticeai/brain/_kg_common.py +0 -17
- package/latticeai/brain/context.py +0 -17
- package/latticeai/brain/conversations.py +0 -17
- package/latticeai/brain/discovery.py +0 -17
- package/latticeai/brain/documents.py +0 -17
- package/latticeai/brain/identity.py +0 -17
- package/latticeai/brain/ingest.py +0 -17
- package/latticeai/brain/memory.py +0 -17
- package/latticeai/brain/network.py +0 -17
- package/latticeai/brain/projection.py +0 -17
- package/latticeai/brain/provenance.py +0 -17
- package/latticeai/brain/retrieval.py +0 -17
- package/latticeai/brain/schema.py +0 -17
- package/latticeai/brain/store.py +0 -17
- package/latticeai/brain/write_master.py +0 -17
- package/latticeai/services/agent_runtime.py +0 -11
- package/static/app/assets/index-Bh7IIlyY.js +0 -16
- package/static/app/assets/index-_M5aCv21.css +0 -2
package/setup_wizard.py
CHANGED
|
@@ -21,6 +21,14 @@ import time
|
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
from typing import Any, AsyncIterator, Dict, List, Tuple
|
|
23
23
|
|
|
24
|
+
from latticeai.services.process_audit import (
|
|
25
|
+
CommandConfirmationError,
|
|
26
|
+
append_process_audit_event,
|
|
27
|
+
command_plan,
|
|
28
|
+
command_plan_for_commands,
|
|
29
|
+
require_command_confirmation,
|
|
30
|
+
)
|
|
31
|
+
|
|
24
32
|
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
25
33
|
|
|
26
34
|
def _cmd(args: List[str], timeout: int = 10) -> str:
|
|
@@ -33,6 +41,61 @@ def _cmd(args: List[str], timeout: int = 10) -> str:
|
|
|
33
41
|
def _sse(data: Dict) -> str:
|
|
34
42
|
return f"data: {_json.dumps(data, ensure_ascii=False)}\n\n"
|
|
35
43
|
|
|
44
|
+
|
|
45
|
+
def _action_commands(action: Dict[str, Any]) -> List[List[str]]:
|
|
46
|
+
atype = action.get("type")
|
|
47
|
+
if atype == "pip":
|
|
48
|
+
return [[sys.executable, "-m", "pip", "install", "--upgrade", str(pkg)] for pkg in action.get("packages", [])]
|
|
49
|
+
if atype == "brew":
|
|
50
|
+
package = str(action.get("package") or "")
|
|
51
|
+
return [["brew", "install", package]] if package else []
|
|
52
|
+
return []
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _action_command_plan(action: Dict[str, Any], *, name: str) -> Dict[str, Any] | None:
|
|
56
|
+
commands = _action_commands(action)
|
|
57
|
+
if not commands:
|
|
58
|
+
return None
|
|
59
|
+
return command_plan_for_commands(
|
|
60
|
+
commands,
|
|
61
|
+
name=name,
|
|
62
|
+
purpose="setup_wizard_install",
|
|
63
|
+
metadata={"action_type": action.get("type")},
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _attach_action_plan(action: Dict[str, Any] | None, *, name: str) -> Dict[str, Any] | None:
|
|
68
|
+
if not isinstance(action, dict):
|
|
69
|
+
return action
|
|
70
|
+
plan = _action_command_plan(action, name=name)
|
|
71
|
+
if not plan:
|
|
72
|
+
return action
|
|
73
|
+
hydrated = dict(action)
|
|
74
|
+
hydrated["command_plan"] = plan
|
|
75
|
+
hydrated["confirmation_token"] = plan["confirmation_token"]
|
|
76
|
+
return hydrated
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _hydrate_install_actions(groups: Dict[str, Any]) -> Dict[str, Any]:
|
|
80
|
+
for group_name in ("components", "engines", "models", "mcps"):
|
|
81
|
+
items = groups.get(group_name)
|
|
82
|
+
if not isinstance(items, list):
|
|
83
|
+
continue
|
|
84
|
+
for item in items:
|
|
85
|
+
if isinstance(item, dict):
|
|
86
|
+
item["action"] = _attach_action_plan(
|
|
87
|
+
item.get("action"),
|
|
88
|
+
name=str(item.get("id") or item.get("name") or group_name),
|
|
89
|
+
)
|
|
90
|
+
return groups
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _verify_action_confirmation(action: Dict[str, Any], token: str | None, *, name: str) -> bool:
|
|
94
|
+
plan = _action_command_plan(action, name=name)
|
|
95
|
+
if not plan:
|
|
96
|
+
return True
|
|
97
|
+
return str(token or "").strip() == plan["confirmation_token"]
|
|
98
|
+
|
|
36
99
|
OFFICIAL_DOWNLOADS: Dict[str, str] = {
|
|
37
100
|
"homebrew": "https://brew.sh",
|
|
38
101
|
"python": "https://www.python.org/downloads/",
|
|
@@ -933,7 +996,7 @@ def get_recommendations(env: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
933
996
|
},
|
|
934
997
|
]
|
|
935
998
|
|
|
936
|
-
return {
|
|
999
|
+
return _hydrate_install_actions({
|
|
937
1000
|
"components": components,
|
|
938
1001
|
"engines": engines,
|
|
939
1002
|
"models": models,
|
|
@@ -954,7 +1017,7 @@ def get_recommendations(env: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
954
1017
|
"is_apple_silicon": is_apple,
|
|
955
1018
|
"max_model_gb": round(max_model_gb, 1),
|
|
956
1019
|
},
|
|
957
|
-
}
|
|
1020
|
+
})
|
|
958
1021
|
|
|
959
1022
|
# ── Installation Stream ───────────────────────────────────────────────────────
|
|
960
1023
|
|
|
@@ -972,7 +1035,12 @@ def _verify_action(action: Dict[str, Any]) -> Tuple[bool, str]:
|
|
|
972
1035
|
return True, "검증 항목 없음"
|
|
973
1036
|
|
|
974
1037
|
|
|
975
|
-
async def _repair_action(
|
|
1038
|
+
async def _repair_action(
|
|
1039
|
+
action: Dict[str, Any],
|
|
1040
|
+
*,
|
|
1041
|
+
confirmation_token: str | None = None,
|
|
1042
|
+
actor: str | None = None,
|
|
1043
|
+
) -> Tuple[bool, str]:
|
|
976
1044
|
binary = action.get("binary")
|
|
977
1045
|
if binary:
|
|
978
1046
|
repair_path_for(binary)
|
|
@@ -982,15 +1050,23 @@ async def _repair_action(action: Dict[str, Any]) -> Tuple[bool, str]:
|
|
|
982
1050
|
if action.get("type") == "pip":
|
|
983
1051
|
packages = action.get("packages", [])
|
|
984
1052
|
if packages:
|
|
1053
|
+
if not _verify_action_confirmation(action, confirmation_token, name="repair_action"):
|
|
1054
|
+
return False, "설치 명령 확인 토큰이 일치하지 않습니다."
|
|
985
1055
|
for pkg in packages:
|
|
986
|
-
success, err = await _pip_install(pkg)
|
|
1056
|
+
success, err = await _pip_install(pkg, confirmed=True, actor=actor)
|
|
987
1057
|
if not success:
|
|
988
1058
|
return False, err
|
|
989
1059
|
return _verify_action(action)
|
|
990
1060
|
return False, "자동 복구 방법을 찾지 못했습니다."
|
|
991
1061
|
|
|
992
1062
|
|
|
993
|
-
async def install_stream(
|
|
1063
|
+
async def install_stream(
|
|
1064
|
+
items: List[Dict],
|
|
1065
|
+
router: Any,
|
|
1066
|
+
*,
|
|
1067
|
+
confirmation_token: str | None = None,
|
|
1068
|
+
user_email: str | None = None,
|
|
1069
|
+
) -> AsyncIterator[str]:
|
|
994
1070
|
for item in items:
|
|
995
1071
|
item_id = item.get("id", "unknown")
|
|
996
1072
|
name = item.get("name", item_id)
|
|
@@ -1006,10 +1082,14 @@ async def install_stream(items: List[Dict], router: Any) -> AsyncIterator[str]:
|
|
|
1006
1082
|
|
|
1007
1083
|
if atype == "pip":
|
|
1008
1084
|
packages = action.get("packages", [])
|
|
1085
|
+
token = confirmation_token or action.get("confirmation_token") or (action.get("command_plan") or {}).get("confirmation_token")
|
|
1086
|
+
if not _verify_action_confirmation(action, token, name=str(item_id)):
|
|
1087
|
+
yield _sse({"id": item_id, "status": "error", "msg": "설치 명령 확인 토큰이 일치하지 않습니다."})
|
|
1088
|
+
continue
|
|
1009
1089
|
ok = True
|
|
1010
1090
|
for pkg in packages:
|
|
1011
1091
|
yield _sse({"id": item_id, "status": "running", "msg": f"pip install {pkg} ..."})
|
|
1012
|
-
success, err = await _pip_install(pkg)
|
|
1092
|
+
success, err = await _pip_install(pkg, confirmed=True, actor=user_email)
|
|
1013
1093
|
if success:
|
|
1014
1094
|
yield _sse({"id": item_id, "status": "progress", "msg": f"{pkg} 설치 완료"})
|
|
1015
1095
|
else:
|
|
@@ -1023,13 +1103,17 @@ async def install_stream(items: List[Dict], router: Any) -> AsyncIterator[str]:
|
|
|
1023
1103
|
yield _sse({"id": item_id, "status": "done", "msg": f"{name} 설치 · 검증 완료 ✅\n{detail}"})
|
|
1024
1104
|
else:
|
|
1025
1105
|
yield _sse({"id": item_id, "status": "running", "msg": f"검증 실패 — 자동 복구 중...\n{detail}"})
|
|
1026
|
-
repaired, repair_msg = await _repair_action(action)
|
|
1106
|
+
repaired, repair_msg = await _repair_action(action, confirmation_token=token, actor=user_email)
|
|
1027
1107
|
yield _sse({"id": item_id, "status": "done" if repaired else "error", "msg": repair_msg[:500]})
|
|
1028
1108
|
|
|
1029
1109
|
elif atype == "brew":
|
|
1030
1110
|
pkg = action.get("package", "")
|
|
1111
|
+
token = confirmation_token or action.get("confirmation_token") or (action.get("command_plan") or {}).get("confirmation_token")
|
|
1112
|
+
if not _verify_action_confirmation(action, token, name=str(item_id)):
|
|
1113
|
+
yield _sse({"id": item_id, "status": "error", "msg": "설치 명령 확인 토큰이 일치하지 않습니다."})
|
|
1114
|
+
continue
|
|
1031
1115
|
yield _sse({"id": item_id, "status": "running", "msg": f"brew install {pkg} ..."})
|
|
1032
|
-
success, err = await _brew_install(pkg)
|
|
1116
|
+
success, err = await _brew_install(pkg, confirmed=True, actor=user_email)
|
|
1033
1117
|
if success:
|
|
1034
1118
|
yield _sse({"id": item_id, "status": "running", "msg": "설치 완료 감지 · PATH 보정 중..."})
|
|
1035
1119
|
binary = action.get("binary")
|
|
@@ -1040,7 +1124,7 @@ async def install_stream(items: List[Dict], router: Any) -> AsyncIterator[str]:
|
|
|
1040
1124
|
yield _sse({"id": item_id, "status": "done", "msg": f"{name} 설치 · 연결 · 검증 완료 ✅\n{detail}"})
|
|
1041
1125
|
else:
|
|
1042
1126
|
yield _sse({"id": item_id, "status": "running", "msg": f"검증 실패 — 자동 복구 중...\n{detail}"})
|
|
1043
|
-
repaired, repair_msg = await _repair_action(action)
|
|
1127
|
+
repaired, repair_msg = await _repair_action(action, confirmation_token=token, actor=user_email)
|
|
1044
1128
|
yield _sse({"id": item_id, "status": "done" if repaired else "error", "msg": repair_msg[:500]})
|
|
1045
1129
|
else:
|
|
1046
1130
|
url = action.get("official_url") or action.get("url")
|
|
@@ -1094,49 +1178,131 @@ async def install_stream(items: List[Dict], router: Any) -> AsyncIterator[str]:
|
|
|
1094
1178
|
yield _sse({"status": "complete", "msg": "모든 항목 처리 완료!"})
|
|
1095
1179
|
|
|
1096
1180
|
|
|
1097
|
-
async def _pip_install(
|
|
1181
|
+
async def _pip_install(
|
|
1182
|
+
package: str,
|
|
1183
|
+
*,
|
|
1184
|
+
confirmation_token: str | None = None,
|
|
1185
|
+
confirmed: bool = False,
|
|
1186
|
+
actor: str | None = None,
|
|
1187
|
+
) -> Tuple[bool, str]:
|
|
1188
|
+
command = [sys.executable, "-m", "pip", "install", "--upgrade", package]
|
|
1189
|
+
plan = command_plan(
|
|
1190
|
+
command,
|
|
1191
|
+
name=f"pip:{package}",
|
|
1192
|
+
purpose="setup_wizard_install",
|
|
1193
|
+
metadata={"package": package},
|
|
1194
|
+
)
|
|
1098
1195
|
try:
|
|
1196
|
+
if not confirmed:
|
|
1197
|
+
require_command_confirmation(command, confirmation_token, purpose="setup_wizard_install")
|
|
1198
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="started", user_email=actor)
|
|
1099
1199
|
proc = await asyncio.create_subprocess_exec(
|
|
1100
|
-
|
|
1200
|
+
*command,
|
|
1101
1201
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
|
1102
1202
|
)
|
|
1103
1203
|
_, stderr = await asyncio.wait_for(proc.communicate(), timeout=600)
|
|
1204
|
+
stderr_text = stderr.decode(errors="replace")
|
|
1205
|
+
append_process_audit_event(
|
|
1206
|
+
"setup_wizard_install",
|
|
1207
|
+
plan=plan,
|
|
1208
|
+
status="finished",
|
|
1209
|
+
user_email=actor,
|
|
1210
|
+
returncode=proc.returncode,
|
|
1211
|
+
stderr=stderr_text,
|
|
1212
|
+
)
|
|
1104
1213
|
if proc.returncode == 0:
|
|
1105
1214
|
return True, ""
|
|
1106
|
-
return False,
|
|
1215
|
+
return False, stderr_text
|
|
1216
|
+
except CommandConfirmationError as e:
|
|
1217
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="denied", user_email=actor, error=str(e))
|
|
1218
|
+
return False, str(e)
|
|
1107
1219
|
except asyncio.TimeoutError:
|
|
1220
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="timeout", user_email=actor)
|
|
1108
1221
|
return False, "설치 시간 초과 (10분)"
|
|
1109
1222
|
except Exception as e:
|
|
1223
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="error", user_email=actor, error=str(e))
|
|
1110
1224
|
return False, str(e)
|
|
1111
1225
|
|
|
1112
1226
|
|
|
1113
|
-
async def _brew_install(
|
|
1227
|
+
async def _brew_install(
|
|
1228
|
+
package: str,
|
|
1229
|
+
*,
|
|
1230
|
+
confirmation_token: str | None = None,
|
|
1231
|
+
confirmed: bool = False,
|
|
1232
|
+
actor: str | None = None,
|
|
1233
|
+
) -> Tuple[bool, str]:
|
|
1114
1234
|
brew = shutil.which("brew")
|
|
1115
1235
|
if not brew:
|
|
1116
1236
|
return False, "Homebrew 미설치 — https://brew.sh 에서 설치하세요"
|
|
1237
|
+
command = [brew, "install", package]
|
|
1238
|
+
plan = command_plan(
|
|
1239
|
+
command,
|
|
1240
|
+
name=f"brew:{package}",
|
|
1241
|
+
purpose="setup_wizard_install",
|
|
1242
|
+
metadata={"package": package},
|
|
1243
|
+
)
|
|
1117
1244
|
try:
|
|
1245
|
+
if not confirmed:
|
|
1246
|
+
require_command_confirmation(command, confirmation_token, purpose="setup_wizard_install")
|
|
1247
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="started", user_email=actor)
|
|
1118
1248
|
proc = await asyncio.create_subprocess_exec(
|
|
1119
|
-
|
|
1249
|
+
*command,
|
|
1120
1250
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
|
1121
1251
|
)
|
|
1122
1252
|
_, stderr = await asyncio.wait_for(proc.communicate(), timeout=300)
|
|
1253
|
+
stderr_text = stderr.decode(errors="replace")
|
|
1254
|
+
append_process_audit_event(
|
|
1255
|
+
"setup_wizard_install",
|
|
1256
|
+
plan=plan,
|
|
1257
|
+
status="finished",
|
|
1258
|
+
user_email=actor,
|
|
1259
|
+
returncode=proc.returncode,
|
|
1260
|
+
stderr=stderr_text,
|
|
1261
|
+
)
|
|
1123
1262
|
if proc.returncode == 0:
|
|
1124
1263
|
return True, ""
|
|
1125
|
-
return False,
|
|
1264
|
+
return False, stderr_text
|
|
1265
|
+
except CommandConfirmationError as e:
|
|
1266
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="denied", user_email=actor, error=str(e))
|
|
1267
|
+
return False, str(e)
|
|
1126
1268
|
except asyncio.TimeoutError:
|
|
1269
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="timeout", user_email=actor)
|
|
1127
1270
|
return False, "설치 시간 초과 (5분)"
|
|
1128
1271
|
except Exception as e:
|
|
1272
|
+
append_process_audit_event("setup_wizard_install", plan=plan, status="error", user_email=actor, error=str(e))
|
|
1129
1273
|
return False, str(e)
|
|
1130
1274
|
|
|
1131
1275
|
|
|
1132
1276
|
def open_url(url: str) -> None:
|
|
1277
|
+
command: List[str]
|
|
1133
1278
|
try:
|
|
1134
1279
|
system = platform.system()
|
|
1135
1280
|
if system == "Darwin":
|
|
1136
|
-
|
|
1281
|
+
command = ["open", url]
|
|
1282
|
+
plan = command_plan(command, name="open_url", purpose="setup_wizard_open_url")
|
|
1283
|
+
append_process_audit_event("setup_wizard_open_url", plan=plan, status="started")
|
|
1284
|
+
subprocess.Popen(command)
|
|
1285
|
+
append_process_audit_event("setup_wizard_open_url", plan=plan, status="spawned")
|
|
1137
1286
|
elif system == "Windows":
|
|
1138
|
-
|
|
1287
|
+
command = ["start", "", url]
|
|
1288
|
+
plan = command_plan(command, name="open_url", purpose="setup_wizard_open_url")
|
|
1289
|
+
append_process_audit_event("setup_wizard_open_url", plan=plan, status="started")
|
|
1290
|
+
subprocess.Popen(command, shell=True)
|
|
1291
|
+
append_process_audit_event("setup_wizard_open_url", plan=plan, status="spawned")
|
|
1139
1292
|
else:
|
|
1140
|
-
|
|
1141
|
-
|
|
1293
|
+
command = ["xdg-open", url]
|
|
1294
|
+
plan = command_plan(command, name="open_url", purpose="setup_wizard_open_url")
|
|
1295
|
+
append_process_audit_event("setup_wizard_open_url", plan=plan, status="started")
|
|
1296
|
+
subprocess.Popen(command)
|
|
1297
|
+
append_process_audit_event("setup_wizard_open_url", plan=plan, status="spawned")
|
|
1298
|
+
except Exception as exc:
|
|
1299
|
+
try:
|
|
1300
|
+
append_process_audit_event(
|
|
1301
|
+
"setup_wizard_open_url",
|
|
1302
|
+
plan=command_plan(["open_url", url], name="open_url", purpose="setup_wizard_open_url"),
|
|
1303
|
+
status="error",
|
|
1304
|
+
error=str(exc),
|
|
1305
|
+
)
|
|
1306
|
+
except Exception:
|
|
1307
|
+
pass
|
|
1142
1308
|
pass
|
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "8.
|
|
2
|
+
"version": "8.9.0",
|
|
3
3
|
"generated_at": "vite",
|
|
4
4
|
"entrypoints": {
|
|
5
|
-
"app": "/static/app/assets/index-
|
|
5
|
+
"app": "/static/app/assets/index-DPdcPoF0.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-DFeanEV6.js": "/static/app/assets/primitives-DFeanEV6.js",
|
|
10
|
+
"_textarea-CD8UNKIy.js": "/static/app/assets/textarea-CD8UNKIy.js",
|
|
11
|
+
"index.html": "/static/app/assets/index-DPdcPoF0.js",
|
|
12
|
+
"assets/index-DCh5AoXt.css": "/static/app/assets/index-DCh5AoXt.css",
|
|
13
|
+
"src/pages/Act.tsx": "/static/app/assets/Act-fZokUnC0.js",
|
|
14
|
+
"src/pages/Brain.tsx": "/static/app/assets/Brain-DtyuWubr.js",
|
|
15
|
+
"src/pages/Capture.tsx": "/static/app/assets/Capture-D5KV3Cu7.js",
|
|
16
|
+
"src/pages/Library.tsx": "/static/app/assets/Library-C9kyFkSt.js",
|
|
17
|
+
"src/pages/System.tsx": "/static/app/assets/System-VbChmX7r.js"
|
|
18
18
|
}
|
|
19
19
|
}
|