@olares/lares-core 0.15.34 → 0.15.36

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/i18n/mobile.js CHANGED
@@ -42,8 +42,9 @@ export const ZH = {
42
42
  "goal.pause": "暂停目标",
43
43
  "goal.resume": "继续目标",
44
44
  "goal.clear": "清除目标",
45
- "approval.waiting": "等待确认",
46
- "approval.escalation": "{toolName} 请求执行权限",
45
+ "approval.waiting": "等待审批",
46
+ "approval.detail": "审批详情",
47
+ "approval.escalation": "工具 {toolName} 请求越权执行",
47
48
  "approval.reject": "拒绝",
48
49
  "approval.allowOnce": "允许一次",
49
50
  "question.waiting": "需要你的选择",
@@ -175,6 +176,7 @@ export const ZH = {
175
176
  "desktop.manual": "手动排序",
176
177
  "desktop.commands": "命令",
177
178
  "desktop.noCommands": "这个会话没有可用命令",
179
+ "permission.title": "权限",
178
180
  // Preset keys arrive from the host as kebab ids; the words live here.
179
181
  "permission.read-only": "只读",
180
182
  "permission.read-only.hint": "只读文件;写入和风险命令需要确认。",
@@ -262,7 +264,8 @@ export const EN = {
262
264
  "goal.resume": "Resume goal",
263
265
  "goal.clear": "Clear goal",
264
266
  "approval.waiting": "Waiting for approval",
265
- "approval.escalation": "{toolName} requests permission to run",
267
+ "approval.detail": "Approval details",
268
+ "approval.escalation": "Tool {toolName} requests privileged execution",
266
269
  "approval.reject": "Reject",
267
270
  "approval.allowOnce": "Allow once",
268
271
  "question.waiting": "Your input is needed",
@@ -393,6 +396,7 @@ export const EN = {
393
396
  "desktop.manual": "Manual",
394
397
  "desktop.commands": "Commands",
395
398
  "desktop.noCommands": "No commands for this session",
399
+ "permission.title": "Permission",
396
400
  "permission.read-only": "Read Only",
397
401
  "permission.read-only.hint": "Read files only; writes and risky commands require approval.",
398
402
  "permission.workspace-write": "Workspace Write",
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The approval card dsh shows in the composer: localized reason as the
3
+ * headline, and the correlated tool call's command underneath.
4
+ */
5
+
6
+ function commandFromArgs(argsRaw) {
7
+ try {
8
+ const args = JSON.parse(argsRaw ?? "");
9
+ return typeof args?.command === "string" ? args.command : "";
10
+ } catch {
11
+ return "";
12
+ }
13
+ }
14
+
15
+ export function approvalCommand(items, callId) {
16
+ if (!callId) return "";
17
+ const rows = Array.isArray(items) ? items : [];
18
+ for (let index = rows.length - 1; index >= 0; index -= 1) {
19
+ const row = rows[index];
20
+ if (row?.type === "tool" && row.callId === callId) return commandFromArgs(row.argsRaw);
21
+ }
22
+ return "";
23
+ }
24
+
25
+ function localizedReason(displayReason, locale) {
26
+ if (typeof displayReason === "string") return displayReason;
27
+ if (!displayReason || typeof displayReason !== "object") return "";
28
+ const lang = String(locale ?? "en").toLowerCase().startsWith("zh") ? "zh" : "en";
29
+ const text = displayReason[lang] ?? displayReason.en;
30
+ return typeof text === "string" ? text : "";
31
+ }
32
+
33
+ export function presentApproval(approval, items = [], locale = "en") {
34
+ if (!approval) return null;
35
+ const localized = localizedReason(approval.displayReason, locale);
36
+ const reason = localized || (typeof approval.reason === "string" ? approval.reason : "");
37
+ return {
38
+ toolName: typeof approval.toolName === "string" ? approval.toolName : "",
39
+ callId: approval.callId,
40
+ reason,
41
+ command: approvalCommand(items, approval.callId),
42
+ };
43
+ }
package/larepass/mux.js CHANGED
@@ -40,6 +40,24 @@ export function remoteEventsOpen(streamId) {
40
40
  return remoteStreamOpen(streamId, "$events");
41
41
  }
42
42
 
43
+ /** String audit reason plus the localized display copy, when the host sent one. */
44
+ function approvalFields(source) {
45
+ const displayReason = source?.displayReason && typeof source.displayReason === "object"
46
+ ? source.displayReason
47
+ : null;
48
+ const reason = typeof source?.reason === "string"
49
+ ? source.reason
50
+ : typeof source?.displayReason === "string"
51
+ ? source.displayReason
52
+ : "";
53
+ return {
54
+ toolName: source?.toolName,
55
+ callId: source?.callId,
56
+ reason,
57
+ ...(displayReason ? { displayReason } : {}),
58
+ };
59
+ }
60
+
43
61
  /**
44
62
  * One `$events` item. A waterfall this client does not answer passes as
45
63
  * `next` so the Host is not left waiting on it; `agentId` is the session.
@@ -69,9 +87,7 @@ export function classifyRemoteEvent(value) {
69
87
  kind: "approval",
70
88
  eventId: value.eventId,
71
89
  sessionId,
72
- toolName: request.toolName,
73
- callId: request.callId,
74
- reason: request.displayReason ?? request.reason,
90
+ ...approvalFields(request),
75
91
  };
76
92
  }
77
93
  return { kind: "pass", eventId: value.eventId };
@@ -305,9 +321,7 @@ export function classifyMuxEnvelope(envelope) {
305
321
  sessionId,
306
322
  rpcId,
307
323
  approvalId: frame.approvalId,
308
- toolName: frame.toolName,
309
- callId: frame.callId,
310
- reason: frame.reason,
324
+ ...approvalFields(frame),
311
325
  };
312
326
  }
313
327
  if (frame.type === "approval/resolved") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olares/lares-core",
3
- "version": "0.15.34",
3
+ "version": "0.15.36",
4
4
  "description": "Lares 共享业务核心:Router、workspace、文件/媒体、Olares 身份(无 UI、无平台壳)",
5
5
  "type": "module",
6
6
  "repository": {
@@ -174,6 +174,7 @@
174
174
  "./larepass/permissions": "./larepass/permissions.js",
175
175
  "./larepass/commands": "./larepass/commands.js",
176
176
  "./larepass/queue": "./larepass/queue.js",
177
+ "./larepass/approval": "./larepass/approval.js",
177
178
  "./larepass/references": "./larepass/references.js",
178
179
  "./larepass/submission-settings": "./larepass/submission-settings.js",
179
180
  "./larepass/turn-metrics": "./larepass/turn-metrics.js",