soulnet-dsh 0.1.8 → 0.1.10
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/lib/client.js +2484 -658
- package/lib/client.js.map +1 -1
- package/lib/events-CLARJLU9.js +1126 -0
- package/lib/events-CLARJLU9.js.map +1 -0
- package/lib/group-contract-N1I1OV1e.js +409 -0
- package/lib/group-contract-N1I1OV1e.js.map +1 -0
- package/lib/index.js +820 -805
- package/lib/index.js.map +1 -1
- package/lib/sessions.js +712 -26
- package/lib/sessions.js.map +1 -1
- package/lib/tools.js +398 -4
- package/lib/tools.js.map +1 -1
- package/lib/types/api/index.d.ts +3 -0
- package/lib/types/client/AgentPane.d.ts +1 -3
- package/lib/types/client/AlterPane.d.ts +3 -3
- package/lib/types/client/DraftCard.d.ts +3 -1
- package/lib/types/client/FriendList.d.ts +3 -1
- package/lib/types/client/GroupCreateDialog.d.ts +3 -1
- package/lib/types/client/MemoryNotification.d.ts +4 -0
- package/lib/types/client/MemoryPane.d.ts +25 -0
- package/lib/types/client/SettingsSection.d.ts +11 -3
- package/lib/types/client/SoulmirrorPage.d.ts +1 -3
- package/lib/types/client/UpdateAction.d.ts +5 -0
- package/lib/types/client/UpdateTrigger.d.ts +5 -0
- package/lib/types/client/alter-card.d.ts +3 -5
- package/lib/types/client/alter-ui.d.ts +2 -1
- package/lib/types/client/api.d.ts +134 -3
- package/lib/types/client/dir-picker.d.ts +3 -0
- package/lib/types/client/inbox-state.d.ts +4 -2
- package/lib/types/client/locales.d.ts +101 -14
- package/lib/types/client/page-state.d.ts +4 -5
- package/lib/types/client/page-store.d.ts +2 -2
- package/lib/types/friend-settings.d.ts +3 -0
- package/lib/types/group-contract.d.ts +37 -0
- package/lib/types/group-settings.d.ts +4 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/memory/extract.d.ts +39 -0
- package/lib/types/memory/store.d.ts +67 -0
- package/lib/types/network/paygate.d.ts +61 -0
- package/lib/types/network/soulnet.d.ts +14 -0
- package/lib/types/network/types.d.ts +85 -4
- package/lib/types/persona.d.ts +2 -0
- package/lib/types/sessions/index.d.ts +42 -0
- package/lib/types/settings.d.ts +29 -0
- package/lib/types-zwvjR1n5.js.map +1 -1
- package/package.json +11 -6
package/lib/client.js
CHANGED
|
@@ -237,7 +237,7 @@ window.__ModuleLoader__.load({
|
|
|
237
237
|
},
|
|
238
238
|
"--dsw-alias-label-primary-inverted": {
|
|
239
239
|
light: "#ffffff",
|
|
240
|
-
dark: "#
|
|
240
|
+
dark: "#0f1115"
|
|
241
241
|
},
|
|
242
242
|
"--dsw-alias-brand-primary": {
|
|
243
243
|
light: "#0f1115",
|
|
@@ -488,6 +488,7 @@ window.__ModuleLoader__.load({
|
|
|
488
488
|
notice: {
|
|
489
489
|
id: message.id,
|
|
490
490
|
fp: message.from,
|
|
491
|
+
gid: frame.gid,
|
|
491
492
|
name: `${message.name} · ${group.name}`,
|
|
492
493
|
body: message.body,
|
|
493
494
|
ts: message.ts,
|
|
@@ -639,6 +640,8 @@ window.__ModuleLoader__.load({
|
|
|
639
640
|
}
|
|
640
641
|
const api = {
|
|
641
642
|
state: () => call("state"),
|
|
643
|
+
/** Wallet status for the create-group UI (paid join needs a wallet). */
|
|
644
|
+
payWallet: () => call("pay.wallet"),
|
|
642
645
|
/** Self-upgrade: is a newer soulnet-dsh published? */
|
|
643
646
|
upgradeCheck: () => call("upgrade.check", {}),
|
|
644
647
|
/** Self-upgrade: install `soulnet-dsh@version` (pnpm may take minutes — long timeout). */
|
|
@@ -679,6 +682,18 @@ window.__ModuleLoader__.load({
|
|
|
679
682
|
presence: (fps) => call("presence", { fps: [...fps] }),
|
|
680
683
|
/** The owner instructs their alter (an owner user/message + a woken turn in the alter session). */
|
|
681
684
|
instruct: (text) => call("alter.instruct", { text }),
|
|
685
|
+
/** Cancel (delete) extracted pre-memories by uid. */
|
|
686
|
+
cancelMemory: (ids) => call("memory.cancel", { ids: [...ids] }),
|
|
687
|
+
memoryList: (allow) => call("memory.list", { ...allow }),
|
|
688
|
+
memoryAdd: (input) => call("memory.add", { ...input }),
|
|
689
|
+
memoryUpdate: (uid, content, scope) => call("memory.update", {
|
|
690
|
+
uid,
|
|
691
|
+
content,
|
|
692
|
+
...scope === void 0 ? {} : { scope }
|
|
693
|
+
}),
|
|
694
|
+
memoryRemove: (uid) => call("memory.remove", { uid }),
|
|
695
|
+
/** 埋点:进群(未读多)时总结该群最近一段消息并提炼记忆。 */
|
|
696
|
+
memorySummarize: (gid) => call("memory.summarize", { gid }),
|
|
682
697
|
/** The alter's latest state (null = no session yet). */
|
|
683
698
|
sessionLatest: () => call("session.latest", {}),
|
|
684
699
|
/** The alter transcript (last `limit` items). */
|
|
@@ -750,10 +765,15 @@ window.__ModuleLoader__.load({
|
|
|
750
765
|
id
|
|
751
766
|
}),
|
|
752
767
|
/** Apply to join a group from its public URI (`soulmirror://group?gid=…&relay=…`). */
|
|
753
|
-
|
|
768
|
+
/** Fetch a group's public card (join policy, paid price/address). */
|
|
769
|
+
groupLookup: (uri) => call("group.lookup", { uri }),
|
|
770
|
+
groupApply: (uri, note, payment) => call("group.apply", {
|
|
754
771
|
uri,
|
|
755
|
-
...note === void 0 ? {} : { note }
|
|
772
|
+
...note === void 0 ? {} : { note },
|
|
773
|
+
...payment === void 0 ? {} : { payment }
|
|
756
774
|
}),
|
|
775
|
+
/** Pay the group's join price from THIS user's local CDP wallet and apply with the proof (one click). */
|
|
776
|
+
groupPaidJoin: (uri) => call("group.paidJoin", { uri }),
|
|
757
777
|
groupApplications: (gid) => call("group.applications", { gid }),
|
|
758
778
|
groupApprove: (gid, fp) => call("group.approve", {
|
|
759
779
|
gid,
|
|
@@ -806,6 +826,7 @@ window.__ModuleLoader__.load({
|
|
|
806
826
|
};
|
|
807
827
|
listeners = /* @__PURE__ */ new Set();
|
|
808
828
|
mailListeners = /* @__PURE__ */ new Set();
|
|
829
|
+
memoryListeners = /* @__PURE__ */ new Set();
|
|
809
830
|
frameListeners = /* @__PURE__ */ new Set();
|
|
810
831
|
source;
|
|
811
832
|
everConnected = false;
|
|
@@ -876,6 +897,13 @@ window.__ModuleLoader__.load({
|
|
|
876
897
|
this.frameListeners.delete(listener);
|
|
877
898
|
};
|
|
878
899
|
};
|
|
900
|
+
/** Subscribe to memory-extraction frames (the owner's popup). Does not open the SSE stream by itself. */
|
|
901
|
+
onMemory = (listener) => {
|
|
902
|
+
this.memoryListeners.add(listener);
|
|
903
|
+
return () => {
|
|
904
|
+
this.memoryListeners.delete(listener);
|
|
905
|
+
};
|
|
906
|
+
};
|
|
879
907
|
/** Fold a `presence` answer (fp -> online) into the friend rows. */
|
|
880
908
|
applyPresence = (online) => {
|
|
881
909
|
let inbox = this.snapshot.inbox;
|
|
@@ -987,6 +1015,14 @@ window.__ModuleLoader__.load({
|
|
|
987
1015
|
inbox: folded.state
|
|
988
1016
|
});
|
|
989
1017
|
return;
|
|
1018
|
+
case "memory":
|
|
1019
|
+
for (const l of this.memoryListeners) l({
|
|
1020
|
+
phase: frame.phase,
|
|
1021
|
+
count: frame.count,
|
|
1022
|
+
...frame.memories === void 0 ? {} : { memories: frame.memories },
|
|
1023
|
+
...frame.clue === void 0 ? {} : { clue: frame.clue }
|
|
1024
|
+
});
|
|
1025
|
+
return;
|
|
990
1026
|
case "alter":
|
|
991
1027
|
this.set({ revision });
|
|
992
1028
|
return;
|
|
@@ -1023,6 +1059,7 @@ window.__ModuleLoader__.load({
|
|
|
1023
1059
|
"alter",
|
|
1024
1060
|
"agent",
|
|
1025
1061
|
"draft",
|
|
1062
|
+
"memory",
|
|
1026
1063
|
"group_message",
|
|
1027
1064
|
"group_typing",
|
|
1028
1065
|
"group_update",
|
|
@@ -1093,7 +1130,7 @@ window.__ModuleLoader__.load({
|
|
|
1093
1130
|
});
|
|
1094
1131
|
}
|
|
1095
1132
|
/** Per-friend alter settings: reply tier + protocol override (friend pane, above the action bar). */
|
|
1096
|
-
function FriendSettingsPanel({ fp, name, tier, tierExplicit, protocol, defaultTier, perHour, t, onClose }) {
|
|
1133
|
+
function FriendSettingsPanel({ fp, name, tier, tierExplicit, protocol, muted, defaultTier, perHour, t, onClose }) {
|
|
1097
1134
|
const [draft, setDraft] = (0, react.useState)(protocol ?? "");
|
|
1098
1135
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1099
1136
|
const [note, setNote] = (0, react.useState)(void 0);
|
|
@@ -1156,6 +1193,23 @@ window.__ModuleLoader__.load({
|
|
|
1156
1193
|
}),
|
|
1157
1194
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("friend.tier.hint", { n: perHour }) })
|
|
1158
1195
|
] }),
|
|
1196
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1197
|
+
style: {
|
|
1198
|
+
display: "flex",
|
|
1199
|
+
alignItems: "center",
|
|
1200
|
+
gap: 8,
|
|
1201
|
+
flexDirection: "row"
|
|
1202
|
+
},
|
|
1203
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1204
|
+
type: "checkbox",
|
|
1205
|
+
checked: muted,
|
|
1206
|
+
disabled: busy,
|
|
1207
|
+
onChange: (e) => {
|
|
1208
|
+
save({ muted: e.target.checked });
|
|
1209
|
+
},
|
|
1210
|
+
"data-soulmirror-friend-mute": true
|
|
1211
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("friend.mute") })]
|
|
1212
|
+
}),
|
|
1159
1213
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("friend.protocol") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
1160
1214
|
className: "sm-textarea-box",
|
|
1161
1215
|
value: draft,
|
|
@@ -1396,6 +1450,28 @@ window.__ModuleLoader__.load({
|
|
|
1396
1450
|
});
|
|
1397
1451
|
}
|
|
1398
1452
|
//#endregion
|
|
1453
|
+
//#region src/client/dir-picker.ts
|
|
1454
|
+
/**
|
|
1455
|
+
* Module-level access to the host's directory picker (`ctx.workspaces`).
|
|
1456
|
+
* Set once in the client `apply` (bundle purity keeps `ctx` out of React
|
|
1457
|
+
* components); the AgentSettingsSheet reads it for its "browse" button next to
|
|
1458
|
+
* the working-directory field. Falls back to null when the host has no picker
|
|
1459
|
+
* or the user cancels, so the field stays editable by hand either way.
|
|
1460
|
+
*/
|
|
1461
|
+
let pick;
|
|
1462
|
+
function setDirectoryPicker(fn) {
|
|
1463
|
+
pick = fn;
|
|
1464
|
+
}
|
|
1465
|
+
/** Open the host's native directory picker; resolves null when unavailable or cancelled. */
|
|
1466
|
+
async function pickDirectory() {
|
|
1467
|
+
if (pick === void 0) return null;
|
|
1468
|
+
try {
|
|
1469
|
+
return await pick();
|
|
1470
|
+
} catch {
|
|
1471
|
+
return null;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
//#endregion
|
|
1399
1475
|
//#region src/client/page-state.ts
|
|
1400
1476
|
const EMPTY_THREAD = {
|
|
1401
1477
|
entries: [],
|
|
@@ -1561,6 +1637,12 @@ window.__ModuleLoader__.load({
|
|
|
1561
1637
|
entries: state.entries.filter((e) => e.clientId !== clientId)
|
|
1562
1638
|
};
|
|
1563
1639
|
}
|
|
1640
|
+
/** Case-insensitive filter over name / remark / card name / fingerprint prefix. */
|
|
1641
|
+
function filterFriends(friends, query) {
|
|
1642
|
+
const q = query.trim().toLowerCase();
|
|
1643
|
+
if (q === "") return [...friends];
|
|
1644
|
+
return friends.filter((f) => f.name.toLowerCase().includes(q) || (f.remark?.toLowerCase().includes(q) ?? false) || (f.cardName?.toLowerCase().includes(q) ?? false) || f.fp.toLowerCase().startsWith(q));
|
|
1645
|
+
}
|
|
1564
1646
|
/** Selection key of the pinned first item "My alter" (never a fingerprint). */
|
|
1565
1647
|
const ALTER_KEY = "alter";
|
|
1566
1648
|
/** Selection key of one group. */
|
|
@@ -1603,30 +1685,40 @@ window.__ModuleLoader__.load({
|
|
|
1603
1685
|
* The tab set the third column offers for a selection. `admin` (group
|
|
1604
1686
|
* management) is group-owner/admin only; the rest follow the product's rows:
|
|
1605
1687
|
* a friend has chat + home, a group has chat / announce / home / members
|
|
1606
|
-
* (+ admin)
|
|
1607
|
-
* memory, per-agent memory) slot in here later.
|
|
1688
|
+
* (+ admin), the alter and every agent have a memory page.
|
|
1608
1689
|
*/
|
|
1609
1690
|
function tabsFor(kind, canAdmin) {
|
|
1610
1691
|
switch (kind) {
|
|
1611
1692
|
case "alter": return [
|
|
1612
1693
|
"chat",
|
|
1613
1694
|
"home",
|
|
1695
|
+
"memory",
|
|
1614
1696
|
"settings"
|
|
1615
1697
|
];
|
|
1616
|
-
case "friend": return [
|
|
1698
|
+
case "friend": return [
|
|
1699
|
+
"chat",
|
|
1700
|
+
"home",
|
|
1701
|
+
"memory"
|
|
1702
|
+
];
|
|
1617
1703
|
case "group": return canAdmin ? [
|
|
1618
1704
|
"chat",
|
|
1619
1705
|
"announce",
|
|
1620
1706
|
"home",
|
|
1707
|
+
"memory",
|
|
1621
1708
|
"members",
|
|
1622
1709
|
"admin"
|
|
1623
1710
|
] : [
|
|
1624
1711
|
"chat",
|
|
1625
1712
|
"announce",
|
|
1626
1713
|
"home",
|
|
1714
|
+
"memory",
|
|
1627
1715
|
"members"
|
|
1628
1716
|
];
|
|
1629
|
-
case "agent": return [
|
|
1717
|
+
case "agent": return [
|
|
1718
|
+
"chat",
|
|
1719
|
+
"memory",
|
|
1720
|
+
"info"
|
|
1721
|
+
];
|
|
1630
1722
|
}
|
|
1631
1723
|
}
|
|
1632
1724
|
/** The default tab when a selection is entered. */
|
|
@@ -1715,13 +1807,10 @@ window.__ModuleLoader__.load({
|
|
|
1715
1807
|
"members",
|
|
1716
1808
|
"admin",
|
|
1717
1809
|
"info",
|
|
1810
|
+
"memory",
|
|
1718
1811
|
"settings"
|
|
1719
1812
|
];
|
|
1720
|
-
const COL2_TABS = [
|
|
1721
|
-
"contacts",
|
|
1722
|
-
"agents",
|
|
1723
|
-
"groups"
|
|
1724
|
-
];
|
|
1813
|
+
const COL2_TABS = ["messages", "contacts"];
|
|
1725
1814
|
/**
|
|
1726
1815
|
* A persisted `paneTab` only makes sense for the selection it was saved under:
|
|
1727
1816
|
* the friend it belonged to may be gone (the page then falls back to the alter,
|
|
@@ -1739,7 +1828,7 @@ window.__ModuleLoader__.load({
|
|
|
1739
1828
|
const fallback = {
|
|
1740
1829
|
open: false,
|
|
1741
1830
|
selected: void 0,
|
|
1742
|
-
col2Tab: "
|
|
1831
|
+
col2Tab: "messages",
|
|
1743
1832
|
paneTab: DEFAULT_PANE_TAB
|
|
1744
1833
|
};
|
|
1745
1834
|
try {
|
|
@@ -1751,7 +1840,7 @@ window.__ModuleLoader__.load({
|
|
|
1751
1840
|
return {
|
|
1752
1841
|
open: p.open === true,
|
|
1753
1842
|
selected,
|
|
1754
|
-
col2Tab: COL2_TABS.includes(p.col2Tab) ? p.col2Tab : "
|
|
1843
|
+
col2Tab: COL2_TABS.includes(p.col2Tab) ? p.col2Tab : "messages",
|
|
1755
1844
|
paneTab: clampPaneTab(p.paneTab, selected)
|
|
1756
1845
|
};
|
|
1757
1846
|
} catch {
|
|
@@ -1951,7 +2040,7 @@ window.__ModuleLoader__.load({
|
|
|
1951
2040
|
});
|
|
1952
2041
|
this.prime(selection);
|
|
1953
2042
|
};
|
|
1954
|
-
/** Switch the second-column section (
|
|
2043
|
+
/** Switch the second-column section (messages / contacts). */
|
|
1955
2044
|
setCol2Tab = (tab) => {
|
|
1956
2045
|
if (tab !== this.snapshot.col2Tab) this.set({ col2Tab: tab });
|
|
1957
2046
|
};
|
|
@@ -2179,6 +2268,333 @@ window.__ModuleLoader__.load({
|
|
|
2179
2268
|
};
|
|
2180
2269
|
const pageStore = new PageStore();
|
|
2181
2270
|
//#endregion
|
|
2271
|
+
//#region src/client/MemoryNotification.tsx
|
|
2272
|
+
/**
|
|
2273
|
+
* Memory-extraction popup (product parity with the lingshu reference):
|
|
2274
|
+
* every turn ends with a "distilling" notice that steps through a simulated
|
|
2275
|
+
* progress, then shows the extracted memories with a countdown that KEEPS them
|
|
2276
|
+
* by default, or a short "nothing to save" notice when extraction came back
|
|
2277
|
+
* empty. Keeping shows a transient guide bubble.
|
|
2278
|
+
*/
|
|
2279
|
+
const KEEP_SECONDS = 5;
|
|
2280
|
+
const EMPTY_SECONDS = 3;
|
|
2281
|
+
const GUIDE_MS = 5e3;
|
|
2282
|
+
const STEP_DELAY_MS = 1100;
|
|
2283
|
+
const box = {
|
|
2284
|
+
position: "fixed",
|
|
2285
|
+
top: 84,
|
|
2286
|
+
right: 24,
|
|
2287
|
+
width: 320,
|
|
2288
|
+
maxWidth: "calc(100vw - 48px)",
|
|
2289
|
+
zIndex: 2e3,
|
|
2290
|
+
background: "var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-base))",
|
|
2291
|
+
border: "1px solid var(--dsw-alias-border, rgba(128,128,128,0.3))",
|
|
2292
|
+
borderRadius: 12,
|
|
2293
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.28)",
|
|
2294
|
+
padding: 16,
|
|
2295
|
+
color: "var(--dsw-alias-label-primary, #e6e6e6)",
|
|
2296
|
+
fontFamily: "inherit"
|
|
2297
|
+
};
|
|
2298
|
+
const title = {
|
|
2299
|
+
margin: 0,
|
|
2300
|
+
fontSize: 14,
|
|
2301
|
+
fontWeight: 600
|
|
2302
|
+
};
|
|
2303
|
+
const hint = {
|
|
2304
|
+
marginTop: 6,
|
|
2305
|
+
fontSize: 12.5,
|
|
2306
|
+
lineHeight: 1.55,
|
|
2307
|
+
opacity: .82
|
|
2308
|
+
};
|
|
2309
|
+
const list = {
|
|
2310
|
+
marginTop: 10,
|
|
2311
|
+
display: "flex",
|
|
2312
|
+
flexDirection: "column",
|
|
2313
|
+
gap: 6
|
|
2314
|
+
};
|
|
2315
|
+
const stepRow = {
|
|
2316
|
+
display: "flex",
|
|
2317
|
+
alignItems: "center",
|
|
2318
|
+
gap: 8,
|
|
2319
|
+
fontSize: 12.5,
|
|
2320
|
+
lineHeight: 1.4
|
|
2321
|
+
};
|
|
2322
|
+
const dot = {
|
|
2323
|
+
width: 6,
|
|
2324
|
+
height: 6,
|
|
2325
|
+
borderRadius: 3,
|
|
2326
|
+
flexShrink: 0
|
|
2327
|
+
};
|
|
2328
|
+
const dotLoading = {
|
|
2329
|
+
...dot,
|
|
2330
|
+
background: "var(--dsw-alias-accent, #4c8dff)",
|
|
2331
|
+
animation: "soulnet-pulse 1.2s ease-in-out infinite"
|
|
2332
|
+
};
|
|
2333
|
+
const dotDone = {
|
|
2334
|
+
...dot,
|
|
2335
|
+
background: "var(--dsw-alias-state-success-primary, #4ade80)"
|
|
2336
|
+
};
|
|
2337
|
+
const points = {
|
|
2338
|
+
marginTop: 8,
|
|
2339
|
+
display: "flex",
|
|
2340
|
+
flexDirection: "column",
|
|
2341
|
+
gap: 6,
|
|
2342
|
+
maxHeight: 200,
|
|
2343
|
+
overflowY: "auto"
|
|
2344
|
+
};
|
|
2345
|
+
const point = {
|
|
2346
|
+
fontSize: 12.5,
|
|
2347
|
+
lineHeight: 1.5,
|
|
2348
|
+
padding: "7px 10px",
|
|
2349
|
+
borderRadius: 8,
|
|
2350
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(255,255,255,0.04))"
|
|
2351
|
+
};
|
|
2352
|
+
const actions = {
|
|
2353
|
+
marginTop: 12,
|
|
2354
|
+
display: "flex",
|
|
2355
|
+
gap: 8,
|
|
2356
|
+
justifyContent: "flex-end"
|
|
2357
|
+
};
|
|
2358
|
+
const ghostBtn = {
|
|
2359
|
+
padding: "6px 12px",
|
|
2360
|
+
fontSize: 12.5,
|
|
2361
|
+
borderRadius: 8,
|
|
2362
|
+
cursor: "pointer",
|
|
2363
|
+
border: "1px solid var(--dsw-alias-border, rgba(128,128,128,0.4))",
|
|
2364
|
+
background: "transparent",
|
|
2365
|
+
color: "inherit"
|
|
2366
|
+
};
|
|
2367
|
+
const primaryBtn = {
|
|
2368
|
+
padding: "6px 12px",
|
|
2369
|
+
fontSize: 12.5,
|
|
2370
|
+
borderRadius: 8,
|
|
2371
|
+
cursor: "pointer",
|
|
2372
|
+
border: "none",
|
|
2373
|
+
background: "var(--dsw-alias-accent, #4c8dff)",
|
|
2374
|
+
color: "#fff"
|
|
2375
|
+
};
|
|
2376
|
+
const guideBox = {
|
|
2377
|
+
...box,
|
|
2378
|
+
width: 300,
|
|
2379
|
+
top: 84,
|
|
2380
|
+
right: 24
|
|
2381
|
+
};
|
|
2382
|
+
const guideCopy = {
|
|
2383
|
+
fontSize: 13,
|
|
2384
|
+
fontWeight: 600
|
|
2385
|
+
};
|
|
2386
|
+
const guideSub = {
|
|
2387
|
+
marginTop: 6,
|
|
2388
|
+
fontSize: 12,
|
|
2389
|
+
lineHeight: 1.5,
|
|
2390
|
+
opacity: .8
|
|
2391
|
+
};
|
|
2392
|
+
function MemoryNotification({ t }) {
|
|
2393
|
+
const [task, setTask] = (0, react.useState)(null);
|
|
2394
|
+
const timersRef = (0, react.useRef)([]);
|
|
2395
|
+
const intervalRef = (0, react.useRef)(null);
|
|
2396
|
+
const clearAll = (0, react.useCallback)(() => {
|
|
2397
|
+
timersRef.current.forEach(clearTimeout);
|
|
2398
|
+
timersRef.current = [];
|
|
2399
|
+
if (intervalRef.current !== null) {
|
|
2400
|
+
clearInterval(intervalRef.current);
|
|
2401
|
+
intervalRef.current = null;
|
|
2402
|
+
}
|
|
2403
|
+
}, []);
|
|
2404
|
+
const startCountdown = (0, react.useCallback)((seconds, onZero) => {
|
|
2405
|
+
intervalRef.current = setInterval(() => {
|
|
2406
|
+
setTask((prev) => {
|
|
2407
|
+
if (prev === null) return prev;
|
|
2408
|
+
const next = prev.remaining - 1;
|
|
2409
|
+
if (next > 0) return {
|
|
2410
|
+
...prev,
|
|
2411
|
+
remaining: next
|
|
2412
|
+
};
|
|
2413
|
+
if (intervalRef.current !== null) clearInterval(intervalRef.current);
|
|
2414
|
+
intervalRef.current = null;
|
|
2415
|
+
onZero();
|
|
2416
|
+
return prev;
|
|
2417
|
+
});
|
|
2418
|
+
}, 1e3);
|
|
2419
|
+
}, []);
|
|
2420
|
+
(0, react.useEffect)(() => networkStore.onMemory((frame) => {
|
|
2421
|
+
clearAll();
|
|
2422
|
+
if (frame.phase === "extracting") {
|
|
2423
|
+
setTask({
|
|
2424
|
+
phase: "processing",
|
|
2425
|
+
memories: [],
|
|
2426
|
+
remaining: KEEP_SECONDS,
|
|
2427
|
+
step: 0,
|
|
2428
|
+
count: 0,
|
|
2429
|
+
clue: frame.clue ?? ""
|
|
2430
|
+
});
|
|
2431
|
+
const stepTimer = setTimeout(() => {
|
|
2432
|
+
setTask((prev) => prev !== null && prev.phase === "processing" ? {
|
|
2433
|
+
...prev,
|
|
2434
|
+
step: 1
|
|
2435
|
+
} : prev);
|
|
2436
|
+
}, STEP_DELAY_MS);
|
|
2437
|
+
timersRef.current.push(stepTimer);
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2440
|
+
const memories = frame.memories ?? [];
|
|
2441
|
+
const count = frame.count;
|
|
2442
|
+
if (memories.length > 0) {
|
|
2443
|
+
setTask({
|
|
2444
|
+
phase: "result",
|
|
2445
|
+
memories,
|
|
2446
|
+
remaining: KEEP_SECONDS,
|
|
2447
|
+
step: 2,
|
|
2448
|
+
count,
|
|
2449
|
+
clue: frame.clue ?? ""
|
|
2450
|
+
});
|
|
2451
|
+
startCountdown(KEEP_SECONDS, () => {
|
|
2452
|
+
setTask((prev) => prev === null ? prev : {
|
|
2453
|
+
...prev,
|
|
2454
|
+
phase: "guide"
|
|
2455
|
+
});
|
|
2456
|
+
const guideTimer = setTimeout(() => setTask(null), GUIDE_MS);
|
|
2457
|
+
timersRef.current.push(guideTimer);
|
|
2458
|
+
});
|
|
2459
|
+
} else {
|
|
2460
|
+
setTask({
|
|
2461
|
+
phase: "empty",
|
|
2462
|
+
memories: [],
|
|
2463
|
+
remaining: EMPTY_SECONDS,
|
|
2464
|
+
step: 2,
|
|
2465
|
+
count,
|
|
2466
|
+
clue: frame.clue ?? ""
|
|
2467
|
+
});
|
|
2468
|
+
startCountdown(EMPTY_SECONDS, () => setTask(null));
|
|
2469
|
+
}
|
|
2470
|
+
}), [clearAll, startCountdown]);
|
|
2471
|
+
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
2472
|
+
(0, react.useEffect)(() => {
|
|
2473
|
+
clearAll();
|
|
2474
|
+
setTask(null);
|
|
2475
|
+
}, [
|
|
2476
|
+
page.selected,
|
|
2477
|
+
page.open,
|
|
2478
|
+
clearAll
|
|
2479
|
+
]);
|
|
2480
|
+
const onCancel = (0, react.useCallback)(() => {
|
|
2481
|
+
const ids = task?.memories.map((m) => m.id).filter(Boolean) ?? [];
|
|
2482
|
+
api.cancelMemory(ids).catch(() => {});
|
|
2483
|
+
clearAll();
|
|
2484
|
+
setTask(null);
|
|
2485
|
+
}, [task, clearAll]);
|
|
2486
|
+
const onClose = (0, react.useCallback)(() => {
|
|
2487
|
+
clearAll();
|
|
2488
|
+
setTask(null);
|
|
2489
|
+
}, [clearAll]);
|
|
2490
|
+
if (task === null) return null;
|
|
2491
|
+
if (task.phase === "guide") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2492
|
+
style: guideBox,
|
|
2493
|
+
"aria-live": "polite",
|
|
2494
|
+
"data-soulmirror-float": true,
|
|
2495
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2496
|
+
style: guideCopy,
|
|
2497
|
+
children: t("memory.guide", {
|
|
2498
|
+
count: task.count,
|
|
2499
|
+
plural: task.count === 1 ? "y" : "ies"
|
|
2500
|
+
})
|
|
2501
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2502
|
+
style: guideSub,
|
|
2503
|
+
children: t("memory.guide.sub")
|
|
2504
|
+
})]
|
|
2505
|
+
});
|
|
2506
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2507
|
+
style: box,
|
|
2508
|
+
"aria-live": "polite",
|
|
2509
|
+
"data-soulmirror-float": true,
|
|
2510
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2511
|
+
style: title,
|
|
2512
|
+
children: t("memory.title")
|
|
2513
|
+
}), task.phase === "processing" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2514
|
+
style: hint,
|
|
2515
|
+
children: t("memory.processing.hint")
|
|
2516
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2517
|
+
style: list,
|
|
2518
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2519
|
+
style: stepRow,
|
|
2520
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: task.step >= 0 ? dotDone : dotLoading }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("memory.step.clue", { summary: task.clue === "" ? "…" : task.clue }) })]
|
|
2521
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2522
|
+
style: stepRow,
|
|
2523
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: task.step >= 1 ? dotLoading : dot }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("memory.step.semantic") })]
|
|
2524
|
+
})]
|
|
2525
|
+
})] }) : task.phase === "result" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2526
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2527
|
+
style: hint,
|
|
2528
|
+
children: t("memory.result.hint")
|
|
2529
|
+
}),
|
|
2530
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2531
|
+
style: {
|
|
2532
|
+
marginTop: 10,
|
|
2533
|
+
fontSize: 12.5,
|
|
2534
|
+
fontWeight: 600
|
|
2535
|
+
},
|
|
2536
|
+
children: t("memory.result.title")
|
|
2537
|
+
}),
|
|
2538
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2539
|
+
style: points,
|
|
2540
|
+
children: task.memories.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2541
|
+
style: point,
|
|
2542
|
+
children: m.content
|
|
2543
|
+
}, m.id))
|
|
2544
|
+
}),
|
|
2545
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2546
|
+
style: actions,
|
|
2547
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2548
|
+
type: "button",
|
|
2549
|
+
style: ghostBtn,
|
|
2550
|
+
onClick: onCancel,
|
|
2551
|
+
children: t("memory.cancel")
|
|
2552
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2553
|
+
type: "button",
|
|
2554
|
+
style: primaryBtn,
|
|
2555
|
+
onClick: () => {
|
|
2556
|
+
clearAll();
|
|
2557
|
+
setTask((prev) => prev === null ? prev : {
|
|
2558
|
+
...prev,
|
|
2559
|
+
phase: "guide"
|
|
2560
|
+
});
|
|
2561
|
+
const guideTimer = setTimeout(() => setTask(null), GUIDE_MS);
|
|
2562
|
+
timersRef.current.push(guideTimer);
|
|
2563
|
+
},
|
|
2564
|
+
children: t("memory.keep", { n: task.remaining })
|
|
2565
|
+
})]
|
|
2566
|
+
})
|
|
2567
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2568
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2569
|
+
style: hint,
|
|
2570
|
+
children: t("memory.empty.hint")
|
|
2571
|
+
}),
|
|
2572
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2573
|
+
style: {
|
|
2574
|
+
marginTop: 10,
|
|
2575
|
+
fontSize: 12.5,
|
|
2576
|
+
fontWeight: 600
|
|
2577
|
+
},
|
|
2578
|
+
children: t("memory.empty.title")
|
|
2579
|
+
}),
|
|
2580
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2581
|
+
style: actions,
|
|
2582
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2583
|
+
type: "button",
|
|
2584
|
+
style: ghostBtn,
|
|
2585
|
+
onClick: onClose,
|
|
2586
|
+
children: t("memory.empty.gotIt", { n: task.remaining })
|
|
2587
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2588
|
+
type: "button",
|
|
2589
|
+
style: primaryBtn,
|
|
2590
|
+
onClick: onClose,
|
|
2591
|
+
children: t("memory.empty.continue")
|
|
2592
|
+
})]
|
|
2593
|
+
})
|
|
2594
|
+
] })]
|
|
2595
|
+
});
|
|
2596
|
+
}
|
|
2597
|
+
//#endregion
|
|
2182
2598
|
//#region src/client/nav-seat.ts
|
|
2183
2599
|
/**
|
|
2184
2600
|
* Whether a sidebar that declares `sidebar.nav.primary` (soulnet-dsh-sidebar)
|
|
@@ -2268,11 +2684,10 @@ window.__ModuleLoader__.load({
|
|
|
2268
2684
|
/**
|
|
2269
2685
|
* `shell.overlay` entry `soulmirror-inbox`: the new-mail cue — a ui-primitives
|
|
2270
2686
|
* Toast "New message from <name>" for mail whose session is not the one on
|
|
2271
|
-
* screen and whose thread is not open on the SoulMirror page.
|
|
2272
|
-
*
|
|
2273
|
-
*
|
|
2274
|
-
*
|
|
2275
|
-
* that used to live here was replaced by the full page (./SoulmirrorPage.tsx).
|
|
2687
|
+
* screen and whose thread is not open on the SoulMirror page. The memory
|
|
2688
|
+
* extraction popup lives in ./MemoryNotification.tsx (mounted here so the SSE
|
|
2689
|
+
* stream stays open for its own subscription too). Always mounted (the overlay
|
|
2690
|
+
* layer is click-through until an entry renders something).
|
|
2276
2691
|
*/
|
|
2277
2692
|
function InboxOverlay({ currentSessionId, t }) {
|
|
2278
2693
|
(0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
@@ -2280,7 +2695,10 @@ window.__ModuleLoader__.load({
|
|
|
2280
2695
|
const seq = (0, react.useRef)(0);
|
|
2281
2696
|
(0, react.useEffect)(() => networkStore.onMail((notice) => {
|
|
2282
2697
|
const page = pageStore.getSnapshot();
|
|
2283
|
-
|
|
2698
|
+
const threadKey = notice.gid !== void 0 ? groupKey(notice.gid) : notice.fp;
|
|
2699
|
+
if (page.open && page.selected === threadKey) return;
|
|
2700
|
+
const inbox = networkStore.getSnapshot().inbox;
|
|
2701
|
+
if (notice.gid !== void 0 ? inbox.groups.find((g) => g.gid === notice.gid)?.muted === true : inbox.friends.find((f) => f.fp === notice.fp)?.muted === true) return;
|
|
2284
2702
|
if (!shouldNotify(notice, currentSessionId())) return;
|
|
2285
2703
|
seq.current += 1;
|
|
2286
2704
|
const entry = {
|
|
@@ -2292,19 +2710,34 @@ window.__ModuleLoader__.load({
|
|
|
2292
2710
|
const dismiss = (0, react.useCallback)((key) => {
|
|
2293
2711
|
setToasts((prev) => prev.filter((x) => x.key !== key));
|
|
2294
2712
|
}, []);
|
|
2295
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2713
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryNotification, { t }), toasts.map((toast) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MailToast, {
|
|
2296
2714
|
entry: toast,
|
|
2297
2715
|
t,
|
|
2298
2716
|
onDone: () => {
|
|
2299
2717
|
dismiss(toast.key);
|
|
2300
2718
|
}
|
|
2301
|
-
}, toast.key)) });
|
|
2719
|
+
}, toast.key))] });
|
|
2302
2720
|
}
|
|
2303
2721
|
function MailToast({ entry, t, onDone }) {
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2722
|
+
(0, react.useEffect)(() => {
|
|
2723
|
+
const timer = setTimeout(onDone, 4500);
|
|
2724
|
+
return () => {
|
|
2725
|
+
clearTimeout(timer);
|
|
2726
|
+
};
|
|
2727
|
+
}, []);
|
|
2728
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2729
|
+
type: "button",
|
|
2730
|
+
className: "sm-mail-toast",
|
|
2731
|
+
onClick: onDone,
|
|
2732
|
+
"data-soulmirror-mail-toast": true,
|
|
2733
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SoulMirrorIcon, { size: 16 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2734
|
+
style: {
|
|
2735
|
+
overflow: "hidden",
|
|
2736
|
+
textOverflow: "ellipsis",
|
|
2737
|
+
whiteSpace: "nowrap"
|
|
2738
|
+
},
|
|
2739
|
+
children: t("toast.newMail", { name: entry.name })
|
|
2740
|
+
})]
|
|
2308
2741
|
});
|
|
2309
2742
|
}
|
|
2310
2743
|
//#endregion
|
|
@@ -2320,7 +2753,7 @@ window.__ModuleLoader__.load({
|
|
|
2320
2753
|
"inbox.pending.noGreeting": "(no greeting)",
|
|
2321
2754
|
"inbox.pending.accepted": "Accepted {name}.",
|
|
2322
2755
|
"inbox.empty": "No friends yet — paste a card URI below, or /add.",
|
|
2323
|
-
"inbox.empty.noIdentity": "No identity yet — create one in Settings →
|
|
2756
|
+
"inbox.empty.noIdentity": "No identity yet — create one in Settings → Soulnet.",
|
|
2324
2757
|
"inbox.noIdentity": "No identity yet",
|
|
2325
2758
|
"inbox.noMessages": "No messages yet",
|
|
2326
2759
|
"inbox.typing": "typing…",
|
|
@@ -2333,17 +2766,53 @@ window.__ModuleLoader__.load({
|
|
|
2333
2766
|
"inbox.add": "Add",
|
|
2334
2767
|
"inbox.add.placeholder": "Add a friend: paste a card URI (soulmirror://card?…)",
|
|
2335
2768
|
"toast.newMail": "New message from {name}",
|
|
2769
|
+
"memory.title": "Saving your key memories",
|
|
2770
|
+
"memory.processing.hint": "I'm listening — I'll distill the important bits into long-term memory that understands you better.",
|
|
2771
|
+
"memory.step.clue": "Spotted a new cue: \"{summary}\"",
|
|
2772
|
+
"memory.step.semantic": "Extracting key meaning: checking for long-term value",
|
|
2773
|
+
"memory.result.hint": "These are saved as pre-memories; you can review them in your knowledge space later.",
|
|
2774
|
+
"memory.result.title": "Extracted memories",
|
|
2775
|
+
"memory.cancel": "Discard",
|
|
2776
|
+
"memory.keep": "Keep {n}s",
|
|
2777
|
+
"memory.empty.hint": "Nothing worth remembering this time — I won't write anything down.",
|
|
2778
|
+
"memory.empty.title": "No memories found",
|
|
2779
|
+
"memory.empty.gotIt": "Got it {n}s",
|
|
2780
|
+
"memory.empty.continue": "Keep chatting",
|
|
2781
|
+
"memory.guide": "{count} key memor{plural} remembered!",
|
|
2782
|
+
"memory.guide.sub": "Keep chatting and I'll slowly remember your preferences and ideas.",
|
|
2783
|
+
"memory.tab": "Memory",
|
|
2784
|
+
"memory.add": "Add",
|
|
2785
|
+
"memory.add.placeholder": "Add a memory by hand…",
|
|
2786
|
+
"memory.save": "Save",
|
|
2787
|
+
"memory.edit": "Edit",
|
|
2788
|
+
"memory.delete": "Delete",
|
|
2789
|
+
"memory.empty.page": "No memories yet.",
|
|
2790
|
+
"memory.origin.auto": "auto",
|
|
2791
|
+
"memory.origin.manual": "manual",
|
|
2792
|
+
"memory.scope.global": "global",
|
|
2793
|
+
"memory.scope.agent": "agent {name}",
|
|
2794
|
+
"memory.scope.group": "group",
|
|
2795
|
+
"memory.scope.friend": "shared",
|
|
2796
|
+
"memory.scope.label": "Scope",
|
|
2797
|
+
"memory.scope.onlyAgent": "this agent only",
|
|
2798
|
+
"memory.scope.onlyGroup": "this group only",
|
|
2799
|
+
"memory.scope.onlyFriend": "this friend only",
|
|
2800
|
+
"memory.filter.label": "Filter",
|
|
2801
|
+
"memory.filter.all": "All",
|
|
2802
|
+
"memory.empty.filter": "No memories in this scope.",
|
|
2336
2803
|
"bubble.in": "from {name}",
|
|
2337
2804
|
"bubble.out": "to {name}",
|
|
2338
2805
|
"bubble.mine": "my alter",
|
|
2339
2806
|
"bubble.auto": "auto-reply",
|
|
2340
2807
|
"bubble.note": "SoulMirror",
|
|
2341
|
-
"settings.nav": "
|
|
2342
|
-
"
|
|
2343
|
-
"
|
|
2344
|
-
"page.update.
|
|
2345
|
-
"
|
|
2346
|
-
"
|
|
2808
|
+
"settings.nav": "Soulnet",
|
|
2809
|
+
"sidebar.update": "Upgrade v{v}",
|
|
2810
|
+
"sidebar.update.busy": "Upgrading…",
|
|
2811
|
+
"page.update.installing": "Installing v{v}…",
|
|
2812
|
+
"page.update.restarting": "Restarting the service…",
|
|
2813
|
+
"page.update.reloading": "Back — reloading…",
|
|
2814
|
+
"settings.title": "Soulnet",
|
|
2815
|
+
"settings.intro": "This dsh is a node on Soulnet: an end-to-end encrypted A2A identity, friends, and your alter — one dsh session (\"My alter\") that speaks to every friend on your behalf.",
|
|
2347
2816
|
"settings.status": "Backend",
|
|
2348
2817
|
"settings.status.soulnet": "soulnet light peer",
|
|
2349
2818
|
"settings.status.fake": "in-memory fake",
|
|
@@ -2408,14 +2877,14 @@ window.__ModuleLoader__.load({
|
|
|
2408
2877
|
"settings.add.sent": "Request sent to {name}. The thread appears once they accept.",
|
|
2409
2878
|
"settings.error": "Error: {message}",
|
|
2410
2879
|
"settings.refresh": "Refresh",
|
|
2411
|
-
"onboard.title": "Welcome to
|
|
2880
|
+
"onboard.title": "Welcome to Soulnet",
|
|
2412
2881
|
"onboard.body": "Create your A2A identity: a key pair generated on this machine. Others add you by pasting your card URI.",
|
|
2413
2882
|
"onboard.name": "Display name",
|
|
2414
2883
|
"onboard.create": "Create identity",
|
|
2415
2884
|
"onboard.done": "Done",
|
|
2416
2885
|
"onboard.later": "Later",
|
|
2417
2886
|
"onboard.created": "Identity created. Copy your card URI and back up identity.json.",
|
|
2418
|
-
"onboard.waiting": "The soulnet peer is not running yet ({state}). Check Settings →
|
|
2887
|
+
"onboard.waiting": "The soulnet peer is not running yet ({state}). Check Settings → Soulnet.",
|
|
2419
2888
|
"cmd.friends.open": "Open the thread with {name}",
|
|
2420
2889
|
"cmd.friends.none": "No friends yet",
|
|
2421
2890
|
"cmd.soulmirror.page": "Open SoulMirror — My alter",
|
|
@@ -2433,7 +2902,7 @@ window.__ModuleLoader__.load({
|
|
|
2433
2902
|
"page.add.note": "Note (optional, also the greeting)",
|
|
2434
2903
|
"page.add.send": "Send request",
|
|
2435
2904
|
"page.empty.noFriends": "No friends yet. Paste a card URI under \"Add friend\" at the bottom of the list, or send yours to a friend.",
|
|
2436
|
-
"page.empty.noFriends.noIdentity": "No identity yet — create one in Settings →
|
|
2905
|
+
"page.empty.noFriends.noIdentity": "No identity yet — create one in Settings → Soulnet.",
|
|
2437
2906
|
"page.empty.noMatch": "No friend matches \"{query}\".",
|
|
2438
2907
|
"page.header.online": "online",
|
|
2439
2908
|
"page.header.offline": "offline",
|
|
@@ -2462,13 +2931,12 @@ window.__ModuleLoader__.load({
|
|
|
2462
2931
|
"page.composer.instructing": "Sending…",
|
|
2463
2932
|
"page.composer.direct": "Debug: direct to {name} · end-to-end encrypted · your alter does not see it",
|
|
2464
2933
|
"alter.me": "My alter",
|
|
2934
|
+
"alter.wallet": "Wallet",
|
|
2465
2935
|
"alter.row.hint": "Talk to your alter directly",
|
|
2466
2936
|
"alter.row.drafts": "{n} draft(s) waiting for you",
|
|
2467
2937
|
"alter.status.running": "Your alter is working…",
|
|
2468
2938
|
"alter.status.idle": "Ready · one memory shared across every friend",
|
|
2469
2939
|
"alter.status.noSession": "Starting the alter session…",
|
|
2470
|
-
"alter.openDsh": "Open in dsh",
|
|
2471
|
-
"alter.openDsh.hint": "The same conversation as a native dsh session (trajectory, tools, approvals).",
|
|
2472
2940
|
"alter.pendbar": "{n} draft(s) of your alter wait for your decision",
|
|
2473
2941
|
"alter.pendbar.go": "Review in {name}'s thread →",
|
|
2474
2942
|
"alter.empty.title": "Tell your alter what to do",
|
|
@@ -2479,6 +2947,8 @@ window.__ModuleLoader__.load({
|
|
|
2479
2947
|
"alter.thinking": "Your alter is working…",
|
|
2480
2948
|
"alter.item.inbound": "Mail from {name}",
|
|
2481
2949
|
"alter.item.view": "open thread",
|
|
2950
|
+
"alter.item.groupInbound": "Group message · {name}",
|
|
2951
|
+
"alter.item.viewGroup": "view in {name}",
|
|
2482
2952
|
"alter.item.send": "To {name}",
|
|
2483
2953
|
"alter.item.send.pending": "sending…",
|
|
2484
2954
|
"alter.item.send.sent": "sent",
|
|
@@ -2496,6 +2966,7 @@ window.__ModuleLoader__.load({
|
|
|
2496
2966
|
"draft.title": "Your alter wants to send this",
|
|
2497
2967
|
"draft.title.to": "Your alter wants to send this to {name}",
|
|
2498
2968
|
"draft.openThread": "open thread",
|
|
2969
|
+
"draft.openGroup": "view in group",
|
|
2499
2970
|
"draft.reason.draft-tier": "Held because this friend's reply tier is \"draft\" (you review before anything goes out).",
|
|
2500
2971
|
"draft.reason.notify-tier": "Held because this friend's reply tier is \"notify\".",
|
|
2501
2972
|
"draft.reason.rate-limited": "Held because the hourly auto-reply cap for this friend is reached.",
|
|
@@ -2534,6 +3005,7 @@ window.__ModuleLoader__.load({
|
|
|
2534
3005
|
"tier.short.auto": "auto",
|
|
2535
3006
|
"friend.settings.title": "How your alter handles {name}",
|
|
2536
3007
|
"friend.tier": "Reply tier",
|
|
3008
|
+
"friend.mute": "Mute (do not disturb)",
|
|
2537
3009
|
"friend.tier.hint": "notify: mail is only shown; draft: your alter drafts a reply and you review it on this page; auto: it sends by itself (max {n}/hour).",
|
|
2538
3010
|
"friend.protocol": "Protocol override for this friend",
|
|
2539
3011
|
"friend.protocol.placeholder": "Rules for this friend only (they win over the global protocol on conflict). Empty = none.",
|
|
@@ -2556,8 +3028,24 @@ window.__ModuleLoader__.load({
|
|
|
2556
3028
|
"settings.alter.alterMode.full": "Full dsh (shell + files, like a normal session)",
|
|
2557
3029
|
"settings.alter.alterMode.hint": "Applies to the next alter session — restart dsh (or reopen the alter session) to switch.",
|
|
2558
3030
|
"settings.alter.openPage": "Open SoulMirror",
|
|
2559
|
-
"settings.alter.openSession": "Open the alter session in dsh",
|
|
2560
3031
|
"settings.alter.legacy": "{n} old per-friend session(s) from before 0.1.0-p4 are kept in dsh but receive no mail; you can delete them.",
|
|
3032
|
+
"settings.wallet": "My USDC wallet",
|
|
3033
|
+
"settings.wallet.loading": "Loading…",
|
|
3034
|
+
"settings.wallet.none": "No wallet yet — ask your alter to create one, or bind an existing address.",
|
|
3035
|
+
"settings.wallet.refresh": "Refresh",
|
|
3036
|
+
"settings.wallet.address": "Address",
|
|
3037
|
+
"settings.wallet.balanceUsdc": "USDC",
|
|
3038
|
+
"settings.wallet.balanceEth": "ETH",
|
|
3039
|
+
"settings.pay": "USDC payments (CDP)",
|
|
3040
|
+
"settings.pay.intro": "Your alter can hold a USDC wallet on Base through Coinbase CDP. Fill the three CDP secrets from portal.cdp.coinbase.com (API Keys → Secret API Key; Wallet Secret is shown once) to let the alter create wallets and send automatically. Without CDP you can still receive payments and verify paid group-join transfers.",
|
|
3041
|
+
"settings.pay.cdpKeyId": "CDP API Key ID",
|
|
3042
|
+
"settings.pay.cdpKeySecret": "CDP API Key Secret",
|
|
3043
|
+
"settings.pay.cdpWalletSecret": "CDP Wallet Secret",
|
|
3044
|
+
"settings.pay.cdpNetwork": "CDP Network",
|
|
3045
|
+
"settings.pay.paygateProxy": "Proxy for CDP calls (e.g. http://127.0.0.1:10808)",
|
|
3046
|
+
"settings.pay.paygateBinary": "paygate binary path (empty = bundled/PATH)",
|
|
3047
|
+
"settings.pay.paygatePort": "paygate port (loopback)",
|
|
3048
|
+
"settings.pay.hint": "Saving any of these fields restarts the local payment gateway automatically — no dsh restart needed.",
|
|
2561
3049
|
"group.section": "Groups",
|
|
2562
3050
|
"group.create": "New group",
|
|
2563
3051
|
"group.create.name": "Group name",
|
|
@@ -2574,6 +3062,8 @@ window.__ModuleLoader__.load({
|
|
|
2574
3062
|
"group.leave.owner": "You are the owner — a group lives and dies with its owner for now.",
|
|
2575
3063
|
"group.left": "Left the group.",
|
|
2576
3064
|
"group.empty": "No messages yet — say something below.",
|
|
3065
|
+
"group.draftReminder": "Your alter drafted a reply — awaiting your review.",
|
|
3066
|
+
"group.draftReminder.go": "Review",
|
|
2577
3067
|
"group.sender.me": "me",
|
|
2578
3068
|
"group.composer.placeholder": "Message {name}…",
|
|
2579
3069
|
"group.composer.hint": "Sent as yourself, end-to-end encrypted (sender key).",
|
|
@@ -2600,6 +3090,14 @@ window.__ModuleLoader__.load({
|
|
|
2600
3090
|
"group.form.join.invite": "invite only",
|
|
2601
3091
|
"group.form.join.apply": "strangers may apply",
|
|
2602
3092
|
"group.form.join.open": "open (applications auto-approved)",
|
|
3093
|
+
"group.form.join.paid": "paid (USDC to join)",
|
|
3094
|
+
"group.form.join.paid.noWallet": "needs a wallet",
|
|
3095
|
+
"group.form.join.paid.noWalletHint": "Create a USDC wallet first (Settings → SoulMirror network → USDC payments), then you can charge for joining.",
|
|
3096
|
+
"group.form.joinPrice": "Join price (USDC)",
|
|
3097
|
+
"group.form.joinAddr": "Receive at: {address}",
|
|
3098
|
+
"group.form.join.paid.membersFree": "Members you select now join free; only later applicants pay the join price.",
|
|
3099
|
+
"group.form.join.paid.priceRequired": "Enter the join price (USDC) to create a paid group.",
|
|
3100
|
+
"group.form.join.paid.autoPublic": "Paid groups are public automatically (strangers need the group link to find and pay).",
|
|
2603
3101
|
"group.form.wake": "Alter wake-up",
|
|
2604
3102
|
"group.form.wake.mention": "on mention",
|
|
2605
3103
|
"group.form.wake.always": "always",
|
|
@@ -2647,6 +3145,7 @@ window.__ModuleLoader__.load({
|
|
|
2647
3145
|
"group.speak.whoOwner": "Only the owner posts in this group.",
|
|
2648
3146
|
"group.speak.whoAdmins": "Only the owner and admins post in this group.",
|
|
2649
3147
|
"group.alter.toggle": "My alter participates",
|
|
3148
|
+
"group.mute": "Mute (do not disturb)",
|
|
2650
3149
|
"group.mode.mention": "replies when @mentioned",
|
|
2651
3150
|
"group.mode.always": "active — may reply to anything",
|
|
2652
3151
|
"group.by.alter": "alter",
|
|
@@ -2663,6 +3162,7 @@ window.__ModuleLoader__.load({
|
|
|
2663
3162
|
"settings.agents.none": "No agents yet — add one below.",
|
|
2664
3163
|
"settings.agents.name": "Name (used as @mention)",
|
|
2665
3164
|
"settings.agents.cwd": "Working directory - the folder it reads, writes and runs commands in (optional)",
|
|
3165
|
+
"settings.agents.cwd.browse": "Browse",
|
|
2666
3166
|
"settings.agents.cwdHint": "Leave empty for its own default folder",
|
|
2667
3167
|
"settings.agents.preset": "Capability preset",
|
|
2668
3168
|
"settings.agents.preset.default": "standard coding agent (default)",
|
|
@@ -2679,7 +3179,6 @@ window.__ModuleLoader__.load({
|
|
|
2679
3179
|
"settings.agents.remove": "Remove",
|
|
2680
3180
|
"settings.agents.saved": "Agent \"{name}\" saved.",
|
|
2681
3181
|
"settings.agents.removed": "Removed \"{name}\".",
|
|
2682
|
-
"settings.agents.open": "Open session",
|
|
2683
3182
|
"settings.agents.status.running": "working…",
|
|
2684
3183
|
"settings.agents.status.idle": "idle",
|
|
2685
3184
|
"agents.section": "My agents",
|
|
@@ -2700,15 +3199,34 @@ window.__ModuleLoader__.load({
|
|
|
2700
3199
|
"agent.thinking.done": "Thought",
|
|
2701
3200
|
"group.join.section": "Join a group",
|
|
2702
3201
|
"group.join.uri": "Group link (soulmirror://group?…)",
|
|
3202
|
+
"group.join.paid.info": "This group is PAID to join: pay {price} USDC to {addr} from any wallet, then paste the transaction hash below.",
|
|
3203
|
+
"group.join.paid.amountLabel": "Join fee",
|
|
3204
|
+
"group.join.paid.confirm": "You are about to pay {price} USDC from your wallet — continue?",
|
|
3205
|
+
"group.join.paid.confirmPay": "Confirm Payment",
|
|
3206
|
+
"group.join.paid.localHint": "Your wallet is managed here — click “Pay & Apply” below to send the fee and join automatically (no need to copy a transaction hash).",
|
|
3207
|
+
"group.join.paid.payApply": "Pay & Apply",
|
|
3208
|
+
"group.join.paid.paidViaLocal": "Paid {amount} USDC and applied — the owner will verify the payment and approve you.",
|
|
3209
|
+
"group.join.paid.toLabel": "Pay to (auto-filled)",
|
|
3210
|
+
"group.join.paid.payHint": "Send {price} USDC from any wallet to the address above, then paste the transaction hash to apply.",
|
|
3211
|
+
"group.join.paid.tx": "Payment transaction hash (0x…)",
|
|
3212
|
+
"group.join.paid.noPrice": "The group is paid but has no published price — ask the owner.",
|
|
3213
|
+
"group.join.paid.needProof": "This is a paid group ({price} USDC). Pay to {addr} first, then paste the transaction hash to apply.",
|
|
3214
|
+
"group.join.paid.note": "paid {price} USDC to join",
|
|
3215
|
+
"group.join.paid.applied": "Payment attached — application submitted, waiting for the owner to verify.",
|
|
2703
3216
|
"group.join.apply": "Apply",
|
|
2704
3217
|
"group.join.applied": "Application sent.",
|
|
2705
3218
|
"group.apps.badge": "{n} application(s) waiting",
|
|
3219
|
+
"col2.messages": "Messages",
|
|
2706
3220
|
"col2.contacts": "Contacts",
|
|
2707
3221
|
"col2.agents": "Agents",
|
|
2708
3222
|
"col2.groups": "Groups",
|
|
2709
3223
|
"col2.contacts.section": "You",
|
|
2710
3224
|
"col2.agents.empty": "No agents yet — create one to give it a job on your behalf.",
|
|
2711
3225
|
"col2.groups.empty": "No groups yet — create one or join with a group link.",
|
|
3226
|
+
"agents.expand": "Show {n} more",
|
|
3227
|
+
"agents.collapse": "Collapse",
|
|
3228
|
+
"messages.friends": "Friends",
|
|
3229
|
+
"messages.section": "Chats",
|
|
2712
3230
|
"groups.section": "Groups",
|
|
2713
3231
|
"pane.chat": "Chat",
|
|
2714
3232
|
"pane.announce": "Bulletin",
|
|
@@ -2717,6 +3235,7 @@ window.__ModuleLoader__.load({
|
|
|
2717
3235
|
"pane.admin": "Manage",
|
|
2718
3236
|
"pane.info": "Info",
|
|
2719
3237
|
"pane.settings": "Settings",
|
|
3238
|
+
"pane.memory": "Memory",
|
|
2720
3239
|
"friend.home.profile": "Profile",
|
|
2721
3240
|
"friend.home.fp": "Fingerprint",
|
|
2722
3241
|
"friend.home.name": "Name",
|
|
@@ -2725,6 +3244,7 @@ window.__ModuleLoader__.load({
|
|
|
2725
3244
|
"friend.home.lastActive": "Last active",
|
|
2726
3245
|
"friend.home.drafts": "Drafts waiting",
|
|
2727
3246
|
"friend.home.actions": "Actions",
|
|
3247
|
+
"friend.home.sendMessage": "Send a message",
|
|
2728
3248
|
"alter.home.profile": "Profile",
|
|
2729
3249
|
"alter.home.session": "Session",
|
|
2730
3250
|
"alter.home.friends": "Friends",
|
|
@@ -2751,7 +3271,7 @@ window.__ModuleLoader__.load({
|
|
|
2751
3271
|
"inbox.pending.noGreeting": "(没有问候语)",
|
|
2752
3272
|
"inbox.pending.accepted": "已接受 {name}。",
|
|
2753
3273
|
"inbox.empty": "还没有好友——在下面贴名片链接,或用 /add。",
|
|
2754
|
-
"inbox.empty.noIdentity": "还没有身份——到 设置 →
|
|
3274
|
+
"inbox.empty.noIdentity": "还没有身份——到 设置 → Soulnet 创建。",
|
|
2755
3275
|
"inbox.noIdentity": "还没有身份",
|
|
2756
3276
|
"inbox.noMessages": "还没有消息",
|
|
2757
3277
|
"inbox.typing": "正在输入…",
|
|
@@ -2764,17 +3284,53 @@ window.__ModuleLoader__.load({
|
|
|
2764
3284
|
"inbox.add": "添加",
|
|
2765
3285
|
"inbox.add.placeholder": "加好友:贴名片链接(soulmirror://card?…)",
|
|
2766
3286
|
"toast.newMail": "{name} 发来新消息",
|
|
3287
|
+
"memory.title": "正在帮你沉淀关键记忆",
|
|
3288
|
+
"memory.processing.hint": "你说的我有认真听,会先提炼重要信息,再变成更懂你的长期记忆。",
|
|
3289
|
+
"memory.step.clue": "识别到一条新的对话线索:“{summary}”",
|
|
3290
|
+
"memory.step.semantic": "提取关键语义:正在判断是否具有长期价值",
|
|
3291
|
+
"memory.result.hint": "这些内容会先作为预记忆保存,之后你也可以在知识空间里继续查看和管理。",
|
|
3292
|
+
"memory.result.title": "已提取出的记忆点",
|
|
3293
|
+
"memory.cancel": "取消记忆",
|
|
3294
|
+
"memory.keep": "保留记忆 {n}s",
|
|
3295
|
+
"memory.empty.hint": "这次没有发现值得长期记住的内容,先不写入记忆库。",
|
|
3296
|
+
"memory.empty.title": "未发现记忆点",
|
|
3297
|
+
"memory.empty.gotIt": "知道了 {n}s",
|
|
3298
|
+
"memory.empty.continue": "继续聊聊",
|
|
3299
|
+
"memory.guide": "您的 {count} 个关键记忆已经被记住啦~",
|
|
3300
|
+
"memory.guide.sub": "多和我聊一点,我会慢慢记住你的偏好和想法,越来越像那个懂你的分身。",
|
|
3301
|
+
"memory.tab": "记忆",
|
|
3302
|
+
"memory.add": "添加",
|
|
3303
|
+
"memory.add.placeholder": "手动添加一条记忆…",
|
|
3304
|
+
"memory.save": "保存",
|
|
3305
|
+
"memory.edit": "编辑",
|
|
3306
|
+
"memory.delete": "删除",
|
|
3307
|
+
"memory.empty.page": "还没有记忆。",
|
|
3308
|
+
"memory.origin.auto": "自动提炼",
|
|
3309
|
+
"memory.origin.manual": "手动",
|
|
3310
|
+
"memory.scope.global": "全局",
|
|
3311
|
+
"memory.scope.agent": "分身 {name}",
|
|
3312
|
+
"memory.scope.group": "群记忆",
|
|
3313
|
+
"memory.scope.friend": "好友共享",
|
|
3314
|
+
"memory.scope.label": "范围",
|
|
3315
|
+
"memory.scope.onlyAgent": "仅当前分身",
|
|
3316
|
+
"memory.scope.onlyGroup": "仅当前群",
|
|
3317
|
+
"memory.scope.onlyFriend": "仅当前好友",
|
|
3318
|
+
"memory.filter.label": "筛选",
|
|
3319
|
+
"memory.filter.all": "全部",
|
|
3320
|
+
"memory.empty.filter": "该范围暂无记忆。",
|
|
2767
3321
|
"bubble.in": "来自 {name}",
|
|
2768
3322
|
"bubble.out": "发给 {name}",
|
|
2769
3323
|
"bubble.mine": "我的分身",
|
|
2770
3324
|
"bubble.auto": "自动回复",
|
|
2771
3325
|
"bubble.note": "灵镜",
|
|
2772
|
-
"settings.nav": "
|
|
2773
|
-
"
|
|
2774
|
-
"
|
|
2775
|
-
"page.update.
|
|
2776
|
-
"
|
|
2777
|
-
"
|
|
3326
|
+
"settings.nav": "Soulnet",
|
|
3327
|
+
"sidebar.update": "升级 v{v}",
|
|
3328
|
+
"sidebar.update.busy": "升级中…",
|
|
3329
|
+
"page.update.installing": "正在安装 v{v}……",
|
|
3330
|
+
"page.update.restarting": "正在重启服务……",
|
|
3331
|
+
"page.update.reloading": "完成——正在刷新……",
|
|
3332
|
+
"settings.title": "Soulnet",
|
|
3333
|
+
"settings.intro": "这个 dsh 是Soulnet 上的一个节点:端到端加密的 A2A 身份、好友,以及你的分身——一条 dsh 会话(「我的分身」),替你和所有好友往来。",
|
|
2778
3334
|
"settings.status": "后端",
|
|
2779
3335
|
"settings.status.soulnet": "soulnet 灵网轻端",
|
|
2780
3336
|
"settings.status.fake": "内存假实现",
|
|
@@ -2839,14 +3395,14 @@ window.__ModuleLoader__.load({
|
|
|
2839
3395
|
"settings.add.sent": "已向 {name} 发出申请,对方接受后往来就会出现。",
|
|
2840
3396
|
"settings.error": "错误:{message}",
|
|
2841
3397
|
"settings.refresh": "刷新",
|
|
2842
|
-
"onboard.title": "
|
|
3398
|
+
"onboard.title": "欢迎来到Soulnet",
|
|
2843
3399
|
"onboard.body": "创建你的 A2A 身份:在本机生成一对密钥。别人贴你的名片链接就能加你。",
|
|
2844
3400
|
"onboard.name": "昵称",
|
|
2845
3401
|
"onboard.create": "创建身份",
|
|
2846
3402
|
"onboard.done": "完成",
|
|
2847
3403
|
"onboard.later": "稍后",
|
|
2848
3404
|
"onboard.created": "身份已创建。复制名片链接,并备份 identity.json。",
|
|
2849
|
-
"onboard.waiting": "soulnet 轻端还没运行({state})。请到 设置 →
|
|
3405
|
+
"onboard.waiting": "soulnet 轻端还没运行({state})。请到 设置 → Soulnet 查看。",
|
|
2850
3406
|
"cmd.friends.open": "打开与 {name} 的往来",
|
|
2851
3407
|
"cmd.friends.none": "还没有好友",
|
|
2852
3408
|
"cmd.soulmirror.page": "打开灵镜——我的分身",
|
|
@@ -2864,7 +3420,7 @@ window.__ModuleLoader__.load({
|
|
|
2864
3420
|
"page.add.note": "备注(可选,同时作为问候语)",
|
|
2865
3421
|
"page.add.send": "发送申请",
|
|
2866
3422
|
"page.empty.noFriends": "还没有好友。把对方的名片链接贴到列表底部的「加好友」,或把你的名片发给对方。",
|
|
2867
|
-
"page.empty.noFriends.noIdentity": "还没有身份——到 设置 →
|
|
3423
|
+
"page.empty.noFriends.noIdentity": "还没有身份——到 设置 → Soulnet 创建。",
|
|
2868
3424
|
"page.empty.noMatch": "没有匹配「{query}」的好友。",
|
|
2869
3425
|
"page.header.online": "在线",
|
|
2870
3426
|
"page.header.offline": "离线",
|
|
@@ -2893,13 +3449,12 @@ window.__ModuleLoader__.load({
|
|
|
2893
3449
|
"page.composer.instructing": "发送中…",
|
|
2894
3450
|
"page.composer.direct": "调试:直发给 {name} · 端到端加密 · 分身看不到",
|
|
2895
3451
|
"alter.me": "我的分身",
|
|
3452
|
+
"alter.wallet": "钱包",
|
|
2896
3453
|
"alter.row.hint": "跟你的分身直接对话",
|
|
2897
3454
|
"alter.row.drafts": "{n} 项等你拍板",
|
|
2898
3455
|
"alter.status.running": "分身正在处理…",
|
|
2899
3456
|
"alter.status.idle": "就绪 · 对所有好友共享同一记忆",
|
|
2900
3457
|
"alter.status.noSession": "分身会话启动中…",
|
|
2901
|
-
"alter.openDsh": "在 dsh 里打开",
|
|
2902
|
-
"alter.openDsh.hint": "同一段对话的 dsh 原生会话(轨迹、工具、审批)。",
|
|
2903
3458
|
"alter.pendbar": "还有 {n} 项分身拟稿等你拍板",
|
|
2904
3459
|
"alter.pendbar.go": "去「{name}」里看 →",
|
|
2905
3460
|
"alter.empty.title": "吩咐你的分身",
|
|
@@ -2910,6 +3465,8 @@ window.__ModuleLoader__.load({
|
|
|
2910
3465
|
"alter.thinking": "分身正在处理…",
|
|
2911
3466
|
"alter.item.inbound": "{name} 来信",
|
|
2912
3467
|
"alter.item.view": "看往来",
|
|
3468
|
+
"alter.item.groupInbound": "群消息 · {name}",
|
|
3469
|
+
"alter.item.viewGroup": "在 {name} 群 中查看",
|
|
2913
3470
|
"alter.item.send": "发给 {name}",
|
|
2914
3471
|
"alter.item.send.pending": "发送中…",
|
|
2915
3472
|
"alter.item.send.sent": "已发出",
|
|
@@ -2927,6 +3484,7 @@ window.__ModuleLoader__.load({
|
|
|
2927
3484
|
"draft.title": "我的分身想这样回复",
|
|
2928
3485
|
"draft.title.to": "我的分身想这样发给 {name}",
|
|
2929
3486
|
"draft.openThread": "看往来",
|
|
3487
|
+
"draft.openGroup": "在群中查看",
|
|
2930
3488
|
"draft.reason.draft-tier": "依据:这位好友的应答档位是「拟稿」(发出前先问你)。",
|
|
2931
3489
|
"draft.reason.notify-tier": "依据:这位好友的应答档位是「只通知」。",
|
|
2932
3490
|
"draft.reason.rate-limited": "依据:对这位好友的自动回复已达每小时上限。",
|
|
@@ -2965,6 +3523,7 @@ window.__ModuleLoader__.load({
|
|
|
2965
3523
|
"tier.short.auto": "自动",
|
|
2966
3524
|
"friend.settings.title": "分身如何对待 {name}",
|
|
2967
3525
|
"friend.tier": "应答档位",
|
|
3526
|
+
"friend.mute": "免打扰",
|
|
2968
3527
|
"friend.tier.hint": "只通知:来信只展示;拟稿:分身拟好回复、在本页等你拍板;自动:分身自己发(每小时最多 {n} 条)。",
|
|
2969
3528
|
"friend.protocol": "对这位好友的准则补充",
|
|
2970
3529
|
"friend.protocol.placeholder": "只对这位好友生效的规则(冲突时压过全局准则)。留空 = 没有。",
|
|
@@ -2987,8 +3546,24 @@ window.__ModuleLoader__.load({
|
|
|
2987
3546
|
"settings.alter.alterMode.full": "完整 dsh(shell + 文件,像普通会话)",
|
|
2988
3547
|
"settings.alter.alterMode.hint": "对下一个分身会话生效——切换后重启 dsh(或重新打开分身会话)。",
|
|
2989
3548
|
"settings.alter.openPage": "打开灵镜",
|
|
2990
|
-
"settings.alter.openSession": "在 dsh 里打开分身会话",
|
|
2991
3549
|
"settings.alter.legacy": "0.1.0-p4 之前的 {n} 条按好友分开的旧会话仍留在 dsh 里,但不再收信,可以删除。",
|
|
3550
|
+
"settings.wallet": "我的 USDC 钱包",
|
|
3551
|
+
"settings.wallet.loading": "加载中…",
|
|
3552
|
+
"settings.wallet.none": "还没有钱包——让分身创建一个,或绑定已有地址。",
|
|
3553
|
+
"settings.wallet.refresh": "刷新",
|
|
3554
|
+
"settings.wallet.address": "地址",
|
|
3555
|
+
"settings.wallet.balanceUsdc": "USDC",
|
|
3556
|
+
"settings.wallet.balanceEth": "ETH",
|
|
3557
|
+
"settings.pay": "USDC 支付(CDP)",
|
|
3558
|
+
"settings.pay.intro": "你的分身可以通过 Coinbase CDP 在 Base 链上持有 USDC 钱包。填入 portal.cdp.coinbase.com 生成的三项 CDP 密钥(API Keys → Secret API Key;Wallet Secret 只显示一次),分身就能自动创建钱包和转账。不配 CDP 也可以收款和验证付费进群的到账。",
|
|
3559
|
+
"settings.pay.cdpKeyId": "CDP API Key ID",
|
|
3560
|
+
"settings.pay.cdpKeySecret": "CDP API Key Secret",
|
|
3561
|
+
"settings.pay.cdpWalletSecret": "CDP Wallet Secret",
|
|
3562
|
+
"settings.pay.cdpNetwork": "CDP 网络",
|
|
3563
|
+
"settings.pay.paygateProxy": "CDP 代理地址(如 http://127.0.0.1:10808)",
|
|
3564
|
+
"settings.pay.paygateBinary": "paygate 路径(留空 = 插件内置/PATH)",
|
|
3565
|
+
"settings.pay.paygatePort": "paygate 端口(本机回环)",
|
|
3566
|
+
"settings.pay.hint": "保存以上任意字段会自动重启本地支付网关,无需重启 dsh。",
|
|
2992
3567
|
"group.section": "群",
|
|
2993
3568
|
"group.create": "新建群",
|
|
2994
3569
|
"group.create.name": "群名称",
|
|
@@ -3005,6 +3580,8 @@ window.__ModuleLoader__.load({
|
|
|
3005
3580
|
"group.leave.owner": "你是群主——目前群与群主共存亡,不能退出。",
|
|
3006
3581
|
"group.left": "已退群。",
|
|
3007
3582
|
"group.empty": "还没有消息——在下面说点什么。",
|
|
3583
|
+
"group.draftReminder": "分身拟了一份回复,等待你拍板。",
|
|
3584
|
+
"group.draftReminder.go": "去查看",
|
|
3008
3585
|
"group.sender.me": "我",
|
|
3009
3586
|
"group.composer.placeholder": "发到 {name}…",
|
|
3010
3587
|
"group.composer.hint": "以你本人身份发送,端到端加密(发送者密钥)。",
|
|
@@ -3031,6 +3608,14 @@ window.__ModuleLoader__.load({
|
|
|
3031
3608
|
"group.form.join.invite": "仅邀请",
|
|
3032
3609
|
"group.form.join.apply": "陌生人可申请",
|
|
3033
3610
|
"group.form.join.open": "开放(申请自动通过)",
|
|
3611
|
+
"group.form.join.paid": "付费进群(付 USDC 才能进)",
|
|
3612
|
+
"group.form.join.paid.noWallet": "需先有钱包",
|
|
3613
|
+
"group.form.join.paid.noWalletHint": "请先在 设置 → 灵镜网络 → USDC 支付 里创建 USDC 钱包,之后才能设置付费进群。",
|
|
3614
|
+
"group.form.joinPrice": "进群价格(USDC)",
|
|
3615
|
+
"group.form.joinAddr": "收款地址:{address}",
|
|
3616
|
+
"group.form.join.paid.membersFree": "创建时勾选的好友直接入群、无需付费;之后申请进群的陌生人才需要付费。",
|
|
3617
|
+
"group.form.join.paid.priceRequired": "请填写进群价格(USDC)后才能创建付费群。",
|
|
3618
|
+
"group.form.join.paid.autoPublic": "付费进群会自动设为公开群(陌生人需要群链接才能找到并付款)。",
|
|
3034
3619
|
"group.form.wake": "分身唤醒",
|
|
3035
3620
|
"group.form.wake.mention": "被点名时",
|
|
3036
3621
|
"group.form.wake.always": "总是",
|
|
@@ -3078,6 +3663,7 @@ window.__ModuleLoader__.load({
|
|
|
3078
3663
|
"group.speak.whoOwner": "这个群里只有群主发言。",
|
|
3079
3664
|
"group.speak.whoAdmins": "这个群里只有群主和管理员发言。",
|
|
3080
3665
|
"group.alter.toggle": "我的分身参与",
|
|
3666
|
+
"group.mute": "免打扰",
|
|
3081
3667
|
"group.mode.mention": "被@才回应",
|
|
3082
3668
|
"group.mode.always": "积极参与",
|
|
3083
3669
|
"group.by.alter": "分身",
|
|
@@ -3094,6 +3680,7 @@ window.__ModuleLoader__.load({
|
|
|
3094
3680
|
"settings.agents.none": "还没有代理——在下面添加一个。",
|
|
3095
3681
|
"settings.agents.name": "名字(群里 @ 它用)",
|
|
3096
3682
|
"settings.agents.cwd": "工作目录——它读写文件、跑命令的文件夹(选填)",
|
|
3683
|
+
"settings.agents.cwd.browse": "浏览",
|
|
3097
3684
|
"settings.agents.cwdHint": "留空 = 使用它自己的默认目录",
|
|
3098
3685
|
"settings.agents.preset": "能力预设",
|
|
3099
3686
|
"settings.agents.preset.default": "标准编码 Agent(默认)",
|
|
@@ -3110,7 +3697,6 @@ window.__ModuleLoader__.load({
|
|
|
3110
3697
|
"settings.agents.remove": "移除",
|
|
3111
3698
|
"settings.agents.saved": "代理「{name}」已保存。",
|
|
3112
3699
|
"settings.agents.removed": "已移除「{name}」。",
|
|
3113
|
-
"settings.agents.open": "打开会话",
|
|
3114
3700
|
"settings.agents.status.running": "干活中…",
|
|
3115
3701
|
"settings.agents.status.idle": "空闲",
|
|
3116
3702
|
"agents.section": "我的 Agent",
|
|
@@ -3131,15 +3717,34 @@ window.__ModuleLoader__.load({
|
|
|
3131
3717
|
"agent.thinking.done": "已思考",
|
|
3132
3718
|
"group.join.section": "加入群",
|
|
3133
3719
|
"group.join.uri": "群链接(soulmirror://group?…)",
|
|
3720
|
+
"group.join.paid.info": "该群为付费进群:请用任意钱包向 {addr} 支付 {price} USDC,然后在下面粘贴交易哈希。",
|
|
3721
|
+
"group.join.paid.amountLabel": "进群费用",
|
|
3722
|
+
"group.join.paid.confirm": "即将从你的钱包支付 {price} USDC,确认继续?",
|
|
3723
|
+
"group.join.paid.confirmPay": "确认支付",
|
|
3724
|
+
"group.join.paid.localHint": "钱包由本机管理——点击下方「支付并申请」即可自动转账进群(无需复制交易哈希)。",
|
|
3725
|
+
"group.join.paid.payApply": "支付并申请",
|
|
3726
|
+
"group.join.paid.paidViaLocal": "已支付 {amount} USDC 并提交申请,群主验证后会批准你进群。",
|
|
3727
|
+
"group.join.paid.toLabel": "收款地址(已自动填入)",
|
|
3728
|
+
"group.join.paid.payHint": "用任意钱包向上面地址支付 {price} USDC,然后粘贴交易哈希提交申请。",
|
|
3729
|
+
"group.join.paid.tx": "付款交易哈希(0x…)",
|
|
3730
|
+
"group.join.paid.noPrice": "该群是付费群但没有公布价格,请联系群主。",
|
|
3731
|
+
"group.join.paid.needProof": "这是付费群({price} USDC)。请先向 {addr} 付款,再粘贴交易哈希提交申请。",
|
|
3732
|
+
"group.join.paid.note": "已付 {price} USDC 进群",
|
|
3733
|
+
"group.join.paid.applied": "已附付款证明并提交申请,等待群主验证。",
|
|
3134
3734
|
"group.join.apply": "申请",
|
|
3135
3735
|
"group.join.applied": "申请已发出。",
|
|
3136
3736
|
"group.apps.badge": "{n} 条进群申请待处理",
|
|
3737
|
+
"col2.messages": "消息",
|
|
3137
3738
|
"col2.contacts": "通讯录",
|
|
3138
3739
|
"col2.agents": "智能体",
|
|
3139
3740
|
"col2.groups": "群聊",
|
|
3140
3741
|
"col2.contacts.section": "我",
|
|
3141
3742
|
"col2.agents.empty": "还没有智能体——创建一个,让它替你做点事。",
|
|
3142
3743
|
"col2.groups.empty": "还没有群——建一个,或用群链接加入。",
|
|
3744
|
+
"agents.expand": "展开 {n} 个",
|
|
3745
|
+
"agents.collapse": "收起",
|
|
3746
|
+
"messages.friends": "好友",
|
|
3747
|
+
"messages.section": "会话",
|
|
3143
3748
|
"groups.section": "群聊",
|
|
3144
3749
|
"pane.chat": "聊天",
|
|
3145
3750
|
"pane.announce": "公告",
|
|
@@ -3148,6 +3753,7 @@ window.__ModuleLoader__.load({
|
|
|
3148
3753
|
"pane.admin": "管理",
|
|
3149
3754
|
"pane.info": "信息",
|
|
3150
3755
|
"pane.settings": "设置",
|
|
3756
|
+
"pane.memory": "记忆",
|
|
3151
3757
|
"friend.home.profile": "名片",
|
|
3152
3758
|
"friend.home.fp": "指纹",
|
|
3153
3759
|
"friend.home.name": "名字",
|
|
@@ -3156,6 +3762,7 @@ window.__ModuleLoader__.load({
|
|
|
3156
3762
|
"friend.home.lastActive": "最近活跃",
|
|
3157
3763
|
"friend.home.drafts": "待审稿",
|
|
3158
3764
|
"friend.home.actions": "操作",
|
|
3765
|
+
"friend.home.sendMessage": "去发消息",
|
|
3159
3766
|
"alter.home.profile": "档案",
|
|
3160
3767
|
"alter.home.session": "会话",
|
|
3161
3768
|
"alter.home.friends": "好友",
|
|
@@ -3637,6 +4244,7 @@ window.__ModuleLoader__.load({
|
|
|
3637
4244
|
const [voices, setVoices] = (0, react.useState)(void 0);
|
|
3638
4245
|
const [voiceCommanders, setVoiceCommanders] = (0, react.useState)({});
|
|
3639
4246
|
const [duty, setDuty] = (0, react.useState)("");
|
|
4247
|
+
const [muted, setMuted] = (0, react.useState)(group.muted === true);
|
|
3640
4248
|
const [agentNames, setAgentNames] = (0, react.useState)([]);
|
|
3641
4249
|
const [agentsSheetOpen, setAgentsSheetOpen] = (0, react.useState)(false);
|
|
3642
4250
|
const [mention, setMention] = (0, react.useState)(void 0);
|
|
@@ -3650,6 +4258,7 @@ window.__ModuleLoader__.load({
|
|
|
3650
4258
|
const following = (0, react.useRef)(true);
|
|
3651
4259
|
const prevFirstSeq = (0, react.useRef)(void 0);
|
|
3652
4260
|
const prevHeight = (0, react.useRef)(0);
|
|
4261
|
+
const groupDrafts = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot).inbox.drafts.filter((d) => d.gid === gid);
|
|
3653
4262
|
(0, react.useEffect)(() => {
|
|
3654
4263
|
setText("");
|
|
3655
4264
|
setVoices(void 0);
|
|
@@ -3725,6 +4334,7 @@ window.__ModuleLoader__.load({
|
|
|
3725
4334
|
setVoices(map);
|
|
3726
4335
|
setVoiceCommanders(cmds);
|
|
3727
4336
|
setDuty(settings.duty ?? "");
|
|
4337
|
+
if (settings.muted !== void 0) setMuted(settings.muted === true);
|
|
3728
4338
|
};
|
|
3729
4339
|
(0, react.useEffect)(() => {
|
|
3730
4340
|
if (!showAlterChip) return;
|
|
@@ -3767,6 +4377,16 @@ window.__ModuleLoader__.load({
|
|
|
3767
4377
|
setDuty(prev);
|
|
3768
4378
|
});
|
|
3769
4379
|
};
|
|
4380
|
+
const toggleMuted = () => {
|
|
4381
|
+
const prev = muted;
|
|
4382
|
+
const next = !muted;
|
|
4383
|
+
setMuted(next);
|
|
4384
|
+
api.groupSettingsSet(gid, { muted: next }).then(({ settings }) => {
|
|
4385
|
+
applySettings(settings);
|
|
4386
|
+
}).catch(() => {
|
|
4387
|
+
setMuted(prev);
|
|
4388
|
+
});
|
|
4389
|
+
};
|
|
3770
4390
|
/** Load one of MY agents' work-session trace for this group (local; persists in the timeline). */
|
|
3771
4391
|
const loadFeed = (name) => {
|
|
3772
4392
|
api.agentHistory(name, 80, gid).then((h) => {
|
|
@@ -4124,6 +4744,18 @@ window.__ModuleLoader__.load({
|
|
|
4124
4744
|
]
|
|
4125
4745
|
})
|
|
4126
4746
|
}),
|
|
4747
|
+
groupDrafts.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4748
|
+
className: "sm-pendbar",
|
|
4749
|
+
"data-soulmirror-group-draft-reminder": true,
|
|
4750
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.draftReminder") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4751
|
+
type: "button",
|
|
4752
|
+
className: "sm-linkbtn",
|
|
4753
|
+
onClick: () => {
|
|
4754
|
+
pageStore.select(ALTER_KEY);
|
|
4755
|
+
},
|
|
4756
|
+
children: t("group.draftReminder.go")
|
|
4757
|
+
})]
|
|
4758
|
+
}) : null,
|
|
4127
4759
|
mutedHint !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4128
4760
|
className: "sm-mutebar",
|
|
4129
4761
|
"data-soulmirror-group-composer": true,
|
|
@@ -4132,120 +4764,147 @@ window.__ModuleLoader__.load({
|
|
|
4132
4764
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4133
4765
|
className: "sm-composer",
|
|
4134
4766
|
"data-soulmirror-group-composer": true,
|
|
4135
|
-
children: [
|
|
4136
|
-
|
|
4137
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4767
|
+
children: [
|
|
4768
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4138
4769
|
style: {
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4770
|
+
display: "flex",
|
|
4771
|
+
alignItems: "center",
|
|
4772
|
+
gap: 14,
|
|
4773
|
+
padding: "0 16px 6px"
|
|
4142
4774
|
},
|
|
4143
|
-
children: [
|
|
4775
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4776
|
+
className: `sm-switch${muted ? " sm-on" : ""}`,
|
|
4777
|
+
"data-soulmirror-group-mute": true,
|
|
4778
|
+
children: [
|
|
4779
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4780
|
+
type: "checkbox",
|
|
4781
|
+
checked: muted,
|
|
4782
|
+
onChange: toggleMuted
|
|
4783
|
+
}),
|
|
4784
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4785
|
+
className: "sm-switch-track",
|
|
4786
|
+
"aria-hidden": true
|
|
4787
|
+
}),
|
|
4788
|
+
t("group.mute")
|
|
4789
|
+
]
|
|
4790
|
+
}), alterSwitch]
|
|
4791
|
+
}),
|
|
4792
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4793
|
+
className: "sm-composer-box",
|
|
4794
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4144
4795
|
style: {
|
|
4145
|
-
position: "
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
marginBottom: 6,
|
|
4149
|
-
zIndex: 20,
|
|
4150
|
-
minWidth: 180,
|
|
4151
|
-
maxHeight: 220,
|
|
4152
|
-
overflowY: "auto",
|
|
4153
|
-
borderRadius: 8,
|
|
4154
|
-
border: "1px solid rgba(127,127,127,.35)",
|
|
4155
|
-
background: "var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2, #fff))",
|
|
4156
|
-
boxShadow: "0 6px 24px rgba(0,0,0,.18)",
|
|
4157
|
-
padding: 4,
|
|
4158
|
-
display: "grid"
|
|
4796
|
+
position: "relative",
|
|
4797
|
+
flex: 1,
|
|
4798
|
+
display: "flex"
|
|
4159
4799
|
},
|
|
4160
|
-
|
|
4161
|
-
children: mentionMatches.map((p, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4162
|
-
type: "button",
|
|
4163
|
-
className: "sm-linkbtn",
|
|
4800
|
+
children: [mention !== void 0 && mentionMatches.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4164
4801
|
style: {
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4802
|
+
position: "absolute",
|
|
4803
|
+
bottom: "100%",
|
|
4804
|
+
left: 0,
|
|
4805
|
+
marginBottom: 6,
|
|
4806
|
+
zIndex: 20,
|
|
4807
|
+
minWidth: 180,
|
|
4808
|
+
maxHeight: 220,
|
|
4809
|
+
overflowY: "auto",
|
|
4810
|
+
borderRadius: 8,
|
|
4811
|
+
border: "1px solid rgba(127,127,127,.35)",
|
|
4812
|
+
background: "var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2, #fff))",
|
|
4813
|
+
boxShadow: "0 6px 24px rgba(0,0,0,.18)",
|
|
4814
|
+
padding: 4,
|
|
4815
|
+
display: "grid"
|
|
4169
4816
|
},
|
|
4170
|
-
|
|
4171
|
-
|
|
4817
|
+
"data-soulmirror-mention-pop": true,
|
|
4818
|
+
children: mentionMatches.map((p, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4819
|
+
type: "button",
|
|
4820
|
+
className: "sm-linkbtn",
|
|
4821
|
+
style: {
|
|
4822
|
+
textAlign: "left",
|
|
4823
|
+
padding: "6px 8px",
|
|
4824
|
+
borderRadius: 6,
|
|
4825
|
+
...i === Math.min(mentionIdx, mentionMatches.length - 1) ? { background: "var(--dsw-alias-interactive-bg-hover)" } : {}
|
|
4826
|
+
},
|
|
4827
|
+
onMouseEnter: () => {
|
|
4828
|
+
setMentionIdx(i);
|
|
4829
|
+
},
|
|
4830
|
+
onMouseDown: (e) => {
|
|
4831
|
+
e.preventDefault();
|
|
4832
|
+
pickMention(p.name);
|
|
4833
|
+
},
|
|
4834
|
+
children: [
|
|
4835
|
+
p.owner !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4836
|
+
"aria-hidden": true,
|
|
4837
|
+
style: { marginRight: 4 },
|
|
4838
|
+
children: "🤖"
|
|
4839
|
+
}) : null,
|
|
4840
|
+
"@",
|
|
4841
|
+
p.name,
|
|
4842
|
+
p.owner !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4843
|
+
className: "sm-statepill",
|
|
4844
|
+
style: { marginLeft: 6 },
|
|
4845
|
+
children: p.owner
|
|
4846
|
+
}) : null
|
|
4847
|
+
]
|
|
4848
|
+
}, `${p.name}|${p.owner ?? ""}`))
|
|
4849
|
+
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
4850
|
+
ref: inputRef,
|
|
4851
|
+
className: "sm-textarea",
|
|
4852
|
+
rows: 1,
|
|
4853
|
+
value: text,
|
|
4854
|
+
placeholder: t("group.composer.placeholder", { name: group.name }),
|
|
4855
|
+
onChange: (e) => {
|
|
4856
|
+
setText(e.target.value);
|
|
4857
|
+
detectMention(e.target.value, e.target.selectionStart ?? e.target.value.length);
|
|
4172
4858
|
},
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4859
|
+
onBlur: () => {
|
|
4860
|
+
setTimeout(() => {
|
|
4861
|
+
setMention(void 0);
|
|
4862
|
+
}, 120);
|
|
4176
4863
|
},
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
}
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
},
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
},
|
|
4207
|
-
onKeyDown: (e) => {
|
|
4208
|
-
if (e.key === "Escape" && mention !== void 0) {
|
|
4209
|
-
e.preventDefault();
|
|
4210
|
-
e.stopPropagation();
|
|
4211
|
-
setMention(void 0);
|
|
4212
|
-
return;
|
|
4213
|
-
}
|
|
4214
|
-
if (mention !== void 0 && mentionMatches.length > 0 && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
|
|
4215
|
-
e.preventDefault();
|
|
4216
|
-
const len = mentionMatches.length;
|
|
4217
|
-
setMentionIdx((i) => (Math.min(i, len - 1) + (e.key === "ArrowDown" ? 1 : len - 1)) % len);
|
|
4218
|
-
return;
|
|
4219
|
-
}
|
|
4220
|
-
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
4221
|
-
e.preventDefault();
|
|
4222
|
-
if (mention !== void 0 && mentionMatches.length > 0) pickMention(mentionMatches[Math.min(mentionIdx, mentionMatches.length - 1)].name);
|
|
4223
|
-
else send();
|
|
4224
|
-
}
|
|
4225
|
-
},
|
|
4226
|
-
"data-soulmirror-group-input": true
|
|
4864
|
+
onKeyDown: (e) => {
|
|
4865
|
+
if (e.key === "Escape" && mention !== void 0) {
|
|
4866
|
+
e.preventDefault();
|
|
4867
|
+
e.stopPropagation();
|
|
4868
|
+
setMention(void 0);
|
|
4869
|
+
return;
|
|
4870
|
+
}
|
|
4871
|
+
if (mention !== void 0 && mentionMatches.length > 0 && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
|
|
4872
|
+
e.preventDefault();
|
|
4873
|
+
const len = mentionMatches.length;
|
|
4874
|
+
setMentionIdx((i) => (Math.min(i, len - 1) + (e.key === "ArrowDown" ? 1 : len - 1)) % len);
|
|
4875
|
+
return;
|
|
4876
|
+
}
|
|
4877
|
+
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
4878
|
+
e.preventDefault();
|
|
4879
|
+
if (mention !== void 0 && mentionMatches.length > 0) pickMention(mentionMatches[Math.min(mentionIdx, mentionMatches.length - 1)].name);
|
|
4880
|
+
else send();
|
|
4881
|
+
}
|
|
4882
|
+
},
|
|
4883
|
+
"data-soulmirror-group-input": true
|
|
4884
|
+
})]
|
|
4885
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4886
|
+
variant: "primary",
|
|
4887
|
+
size: "sm",
|
|
4888
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 14 }),
|
|
4889
|
+
disabled: text.trim() === "",
|
|
4890
|
+
onClick: send,
|
|
4891
|
+
"data-soulmirror-group-send": true,
|
|
4892
|
+
children: t("group.send")
|
|
4227
4893
|
})]
|
|
4228
|
-
}),
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
gap: 10
|
|
4243
|
-
},
|
|
4244
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4245
|
-
style: { flex: 1 },
|
|
4246
|
-
children: t("group.composer.hint")
|
|
4247
|
-
}), alterSwitch]
|
|
4248
|
-
})]
|
|
4894
|
+
}),
|
|
4895
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4896
|
+
className: "sm-composer-hint",
|
|
4897
|
+
style: {
|
|
4898
|
+
display: "flex",
|
|
4899
|
+
alignItems: "center",
|
|
4900
|
+
gap: 10
|
|
4901
|
+
},
|
|
4902
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4903
|
+
style: { flex: 1 },
|
|
4904
|
+
children: t("group.composer.hint")
|
|
4905
|
+
})
|
|
4906
|
+
})
|
|
4907
|
+
]
|
|
4249
4908
|
}),
|
|
4250
4909
|
agentsSheetOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupAgentsSheet, {
|
|
4251
4910
|
t,
|
|
@@ -4521,35 +5180,143 @@ window.__ModuleLoader__.load({
|
|
|
4521
5180
|
})]
|
|
4522
5181
|
})] });
|
|
4523
5182
|
}
|
|
4524
|
-
function
|
|
4525
|
-
const
|
|
4526
|
-
const [
|
|
5183
|
+
function WalletBlock({ t }) {
|
|
5184
|
+
const [copied, copy] = useCopy$1();
|
|
5185
|
+
const [wallet, setWallet] = (0, react.useState)(void 0);
|
|
5186
|
+
const [err, setErr] = (0, react.useState)(void 0);
|
|
5187
|
+
const refresh = (0, react.useCallback)(() => {
|
|
5188
|
+
api.payWallet().then((r) => {
|
|
5189
|
+
setWallet(r.wallet ?? null);
|
|
5190
|
+
setErr(r.error);
|
|
5191
|
+
}).catch(() => {
|
|
5192
|
+
setWallet(null);
|
|
5193
|
+
});
|
|
5194
|
+
}, []);
|
|
4527
5195
|
(0, react.useEffect)(() => {
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
5196
|
+
refresh();
|
|
5197
|
+
const timer = setInterval(refresh, 15e3);
|
|
5198
|
+
return () => {
|
|
5199
|
+
clearInterval(timer);
|
|
5200
|
+
};
|
|
5201
|
+
}, [refresh]);
|
|
5202
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5203
|
+
style: card,
|
|
5204
|
+
"data-soulmirror-wallet-block": true,
|
|
5205
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
5206
|
+
style: h4,
|
|
5207
|
+
children: t("settings.wallet")
|
|
5208
|
+
}), wallet === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5209
|
+
style: small$1,
|
|
5210
|
+
children: t("settings.wallet.loading")
|
|
5211
|
+
}) : wallet === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5212
|
+
style: small$1,
|
|
5213
|
+
children: err !== void 0 ? err : t("settings.wallet.none")
|
|
5214
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5215
|
+
style: rowStyle,
|
|
5216
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5217
|
+
type: "button",
|
|
5218
|
+
onClick: refresh,
|
|
5219
|
+
"data-soulmirror-wallet-refresh": true,
|
|
5220
|
+
children: t("settings.wallet.refresh")
|
|
5221
|
+
})
|
|
5222
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5223
|
+
style: {
|
|
5224
|
+
display: "grid",
|
|
5225
|
+
gap: 4
|
|
5226
|
+
},
|
|
5227
|
+
children: [
|
|
5228
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5229
|
+
style: rowStyle,
|
|
5230
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5231
|
+
style: {
|
|
5232
|
+
opacity: .8,
|
|
5233
|
+
fontSize: "0.82em"
|
|
5234
|
+
},
|
|
5235
|
+
children: t("settings.wallet.address")
|
|
5236
|
+
}), wallet.network !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5237
|
+
style: {
|
|
5238
|
+
...small$1,
|
|
5239
|
+
fontSize: "0.75em"
|
|
5240
|
+
},
|
|
5241
|
+
children: wallet.network
|
|
5242
|
+
}) : null]
|
|
5243
|
+
}),
|
|
5244
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5245
|
+
style: mono,
|
|
5246
|
+
"data-soulmirror-wallet-address": true,
|
|
5247
|
+
children: wallet.address
|
|
5248
|
+
}),
|
|
5249
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5250
|
+
style: rowStyle,
|
|
5251
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5252
|
+
type: "button",
|
|
5253
|
+
onClick: () => {
|
|
5254
|
+
copy(wallet.address ?? "");
|
|
5255
|
+
},
|
|
5256
|
+
children: copied ? t("settings.card.copied") : t("settings.card.copy")
|
|
5257
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5258
|
+
type: "button",
|
|
5259
|
+
onClick: refresh,
|
|
5260
|
+
"data-soulmirror-wallet-refresh": true,
|
|
5261
|
+
children: t("settings.wallet.refresh")
|
|
5262
|
+
})]
|
|
5263
|
+
}),
|
|
5264
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5265
|
+
style: {
|
|
5266
|
+
display: "grid",
|
|
5267
|
+
gridTemplateColumns: "1fr 1fr",
|
|
5268
|
+
gap: 6,
|
|
5269
|
+
marginTop: 2
|
|
5270
|
+
},
|
|
5271
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5272
|
+
style: small$1,
|
|
5273
|
+
children: [
|
|
5274
|
+
t("settings.wallet.balanceUsdc"),
|
|
5275
|
+
": ",
|
|
5276
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: wallet.balance_usdc ?? "—" })
|
|
5277
|
+
]
|
|
5278
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5279
|
+
style: small$1,
|
|
5280
|
+
children: [
|
|
5281
|
+
t("settings.wallet.balanceEth"),
|
|
5282
|
+
": ",
|
|
5283
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: wallet.balance_eth ?? "—" })
|
|
5284
|
+
]
|
|
5285
|
+
})]
|
|
5286
|
+
})
|
|
5287
|
+
]
|
|
5288
|
+
}) })]
|
|
5289
|
+
});
|
|
5290
|
+
}
|
|
5291
|
+
function SettingField({ label, field, scope, values, user, writable, type = "text", options, optionLabel, min }) {
|
|
5292
|
+
const current = values?.[field] ?? "";
|
|
5293
|
+
const [draft, setDraft] = (0, react.useState)(String(current));
|
|
5294
|
+
(0, react.useEffect)(() => {
|
|
5295
|
+
setDraft(String(current));
|
|
5296
|
+
}, [current]);
|
|
5297
|
+
const commit = () => {
|
|
5298
|
+
if (draft === String(current)) return;
|
|
5299
|
+
const value = type === "number" ? Math.max(min ?? 0, Math.floor(Number(draft) || 0)) : draft;
|
|
5300
|
+
scope.set(field, value).catch(() => {});
|
|
5301
|
+
};
|
|
5302
|
+
const overridden = field in user;
|
|
5303
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5304
|
+
style: {
|
|
5305
|
+
display: "grid",
|
|
5306
|
+
gap: 4,
|
|
5307
|
+
fontSize: "0.85em"
|
|
5308
|
+
},
|
|
5309
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5310
|
+
style: { opacity: .8 },
|
|
5311
|
+
children: [label, overridden ? " *" : ""]
|
|
5312
|
+
}), type === "select" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
5313
|
+
value: draft,
|
|
5314
|
+
disabled: !writable,
|
|
5315
|
+
onChange: (e) => {
|
|
5316
|
+
setDraft(e.target.value);
|
|
5317
|
+
scope.set(field, e.target.value).catch(() => {});
|
|
5318
|
+
},
|
|
5319
|
+
style: input,
|
|
4553
5320
|
"data-soulmirror-setting": field,
|
|
4554
5321
|
children: (options ?? []).map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4555
5322
|
value: o,
|
|
@@ -4557,7 +5324,7 @@ window.__ModuleLoader__.load({
|
|
|
4557
5324
|
}, o))
|
|
4558
5325
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4559
5326
|
style: input,
|
|
4560
|
-
type: type === "number" ? "number" : "text",
|
|
5327
|
+
type: type === "password" ? "password" : type === "number" ? "number" : "text",
|
|
4561
5328
|
min,
|
|
4562
5329
|
value: draft,
|
|
4563
5330
|
disabled: !writable,
|
|
@@ -4697,7 +5464,7 @@ window.__ModuleLoader__.load({
|
|
|
4697
5464
|
const key = BINARY_SOURCE_KEYS[source];
|
|
4698
5465
|
return key === void 0 ? source : t(key);
|
|
4699
5466
|
}
|
|
4700
|
-
function SoulmirrorSettingsSection({
|
|
5467
|
+
function SoulmirrorSettingsSection({ scope, t }) {
|
|
4701
5468
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
4702
5469
|
const subscribeScope = (0, react.useCallback)((listener) => scope.subscribe(listener), [scope]);
|
|
4703
5470
|
const readScope = (0, react.useCallback)(() => scope.getSnapshot(), [scope]);
|
|
@@ -4938,28 +5705,17 @@ window.__ModuleLoader__.load({
|
|
|
4938
5705
|
}),
|
|
4939
5706
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4940
5707
|
style: rowStyle,
|
|
4941
|
-
children: [
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
onClick: () => {
|
|
4953
|
-
openSession(state.alter.sessionId);
|
|
4954
|
-
},
|
|
4955
|
-
"data-soulmirror-settings-open-alter-session": true,
|
|
4956
|
-
children: t("settings.alter.openSession")
|
|
4957
|
-
}) : null,
|
|
4958
|
-
state?.alter?.legacyFriendSessions !== void 0 && Object.keys(state.alter.legacyFriendSessions).length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4959
|
-
style: small$1,
|
|
4960
|
-
children: t("settings.alter.legacy", { n: Object.keys(state.alter.legacyFriendSessions).length })
|
|
4961
|
-
}) : null
|
|
4962
|
-
]
|
|
5708
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5709
|
+
type: "button",
|
|
5710
|
+
onClick: () => {
|
|
5711
|
+
pageStore.open("alter");
|
|
5712
|
+
},
|
|
5713
|
+
"data-soulmirror-settings-open-page": true,
|
|
5714
|
+
children: t("settings.alter.openPage")
|
|
5715
|
+
}), state?.alter?.legacyFriendSessions !== void 0 && Object.keys(state.alter.legacyFriendSessions).length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5716
|
+
style: small$1,
|
|
5717
|
+
children: t("settings.alter.legacy", { n: Object.keys(state.alter.legacyFriendSessions).length })
|
|
5718
|
+
}) : null]
|
|
4963
5719
|
}),
|
|
4964
5720
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4965
5721
|
style: {
|
|
@@ -4980,6 +5736,87 @@ window.__ModuleLoader__.load({
|
|
|
4980
5736
|
})
|
|
4981
5737
|
]
|
|
4982
5738
|
}),
|
|
5739
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WalletBlock, { t }),
|
|
5740
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5741
|
+
style: card,
|
|
5742
|
+
"data-soulmirror-settings-pay": true,
|
|
5743
|
+
children: [
|
|
5744
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
5745
|
+
style: h4,
|
|
5746
|
+
children: t("settings.pay")
|
|
5747
|
+
}),
|
|
5748
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5749
|
+
style: small$1,
|
|
5750
|
+
children: t("settings.pay.intro")
|
|
5751
|
+
}),
|
|
5752
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5753
|
+
label: t("settings.pay.cdpKeyId"),
|
|
5754
|
+
field: "cdpKeyId",
|
|
5755
|
+
scope,
|
|
5756
|
+
values: settings.value,
|
|
5757
|
+
user: userLayer,
|
|
5758
|
+
writable
|
|
5759
|
+
}),
|
|
5760
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5761
|
+
label: t("settings.pay.cdpKeySecret"),
|
|
5762
|
+
field: "cdpKeySecret",
|
|
5763
|
+
scope,
|
|
5764
|
+
values: settings.value,
|
|
5765
|
+
user: userLayer,
|
|
5766
|
+
writable,
|
|
5767
|
+
type: "password"
|
|
5768
|
+
}),
|
|
5769
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5770
|
+
label: t("settings.pay.cdpWalletSecret"),
|
|
5771
|
+
field: "cdpWalletSecret",
|
|
5772
|
+
scope,
|
|
5773
|
+
values: settings.value,
|
|
5774
|
+
user: userLayer,
|
|
5775
|
+
writable,
|
|
5776
|
+
type: "password"
|
|
5777
|
+
}),
|
|
5778
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5779
|
+
label: t("settings.pay.cdpNetwork"),
|
|
5780
|
+
field: "cdpNetwork",
|
|
5781
|
+
scope,
|
|
5782
|
+
values: settings.value,
|
|
5783
|
+
user: userLayer,
|
|
5784
|
+
writable,
|
|
5785
|
+
type: "select",
|
|
5786
|
+
options: ["base-sepolia", "base"]
|
|
5787
|
+
}),
|
|
5788
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5789
|
+
label: t("settings.pay.paygateProxy"),
|
|
5790
|
+
field: "paygateProxy",
|
|
5791
|
+
scope,
|
|
5792
|
+
values: settings.value,
|
|
5793
|
+
user: userLayer,
|
|
5794
|
+
writable
|
|
5795
|
+
}),
|
|
5796
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5797
|
+
label: t("settings.pay.paygateBinary"),
|
|
5798
|
+
field: "paygateBinary",
|
|
5799
|
+
scope,
|
|
5800
|
+
values: settings.value,
|
|
5801
|
+
user: userLayer,
|
|
5802
|
+
writable
|
|
5803
|
+
}),
|
|
5804
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingField, {
|
|
5805
|
+
label: t("settings.pay.paygatePort"),
|
|
5806
|
+
field: "paygatePort",
|
|
5807
|
+
scope,
|
|
5808
|
+
values: settings.value,
|
|
5809
|
+
user: userLayer,
|
|
5810
|
+
writable,
|
|
5811
|
+
type: "number",
|
|
5812
|
+
min: 1
|
|
5813
|
+
}),
|
|
5814
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5815
|
+
style: small$1,
|
|
5816
|
+
children: t("settings.pay.hint")
|
|
5817
|
+
})
|
|
5818
|
+
]
|
|
5819
|
+
}),
|
|
4983
5820
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4984
5821
|
style: card,
|
|
4985
5822
|
children: [
|
|
@@ -5550,14 +6387,36 @@ window.__ModuleLoader__.load({
|
|
|
5550
6387
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5551
6388
|
style: { opacity: .8 },
|
|
5552
6389
|
children: t("settings.agents.cwd")
|
|
5553
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5554
|
-
style:
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
onChange: (e) => {
|
|
5558
|
-
setCwd(e.target.value);
|
|
6390
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6391
|
+
style: {
|
|
6392
|
+
display: "flex",
|
|
6393
|
+
gap: 6
|
|
5559
6394
|
},
|
|
5560
|
-
"
|
|
6395
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6396
|
+
style: {
|
|
6397
|
+
...field,
|
|
6398
|
+
flex: 1,
|
|
6399
|
+
minWidth: 0
|
|
6400
|
+
},
|
|
6401
|
+
value: cwd,
|
|
6402
|
+
placeholder: t("settings.agents.cwdHint"),
|
|
6403
|
+
onChange: (e) => {
|
|
6404
|
+
setCwd(e.target.value);
|
|
6405
|
+
},
|
|
6406
|
+
"data-soulmirror-agent-cwd": true
|
|
6407
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6408
|
+
type: "button",
|
|
6409
|
+
className: "sm-ghostbtn",
|
|
6410
|
+
style: { whiteSpace: "nowrap" },
|
|
6411
|
+
disabled: busy,
|
|
6412
|
+
onClick: () => {
|
|
6413
|
+
pickDirectory().then((p) => {
|
|
6414
|
+
if (p !== null) setCwd(p);
|
|
6415
|
+
});
|
|
6416
|
+
},
|
|
6417
|
+
"data-soulmirror-agent-cwd-browse": true,
|
|
6418
|
+
children: t("settings.agents.cwd.browse")
|
|
6419
|
+
})]
|
|
5561
6420
|
})]
|
|
5562
6421
|
}),
|
|
5563
6422
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
@@ -5685,15 +6544,377 @@ window.__ModuleLoader__.load({
|
|
|
5685
6544
|
});
|
|
5686
6545
|
}
|
|
5687
6546
|
//#endregion
|
|
6547
|
+
//#region src/client/MemoryPane.tsx
|
|
6548
|
+
/**
|
|
6549
|
+
* The memory page (added as a pane tab for the alter and every seat agent):
|
|
6550
|
+
* list, add-by-hand, edit and delete memories, each tagged with its origin
|
|
6551
|
+
* (auto-extracted vs manual) and its scope (global vs this agent vs group).
|
|
6552
|
+
* The add and edit forms let the owner pick the scope (global vs only this
|
|
6553
|
+
* agent / only this group) instead of forcing the pane's fixed scope.
|
|
6554
|
+
*/
|
|
6555
|
+
const pill = {
|
|
6556
|
+
fontSize: 10.5,
|
|
6557
|
+
padding: "1px 6px",
|
|
6558
|
+
borderRadius: 8,
|
|
6559
|
+
border: "1px solid rgba(127,127,127,.4)",
|
|
6560
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
6561
|
+
whiteSpace: "nowrap"
|
|
6562
|
+
};
|
|
6563
|
+
const autoPill = {
|
|
6564
|
+
...pill,
|
|
6565
|
+
borderColor: "rgba(90,150,255,.5)",
|
|
6566
|
+
color: "var(--dsw-alias-accent, #4c8dff)"
|
|
6567
|
+
};
|
|
6568
|
+
const manualPill = {
|
|
6569
|
+
...pill,
|
|
6570
|
+
borderColor: "rgba(140,200,120,.5)",
|
|
6571
|
+
color: "var(--dsw-alias-state-success-primary, #4ade80)"
|
|
6572
|
+
};
|
|
6573
|
+
function scopeLabel(t, scope) {
|
|
6574
|
+
switch (scope.kind) {
|
|
6575
|
+
case "global": return t("memory.scope.global");
|
|
6576
|
+
case "agent": return t("memory.scope.agent", { name: scope.name ?? "" });
|
|
6577
|
+
case "shared-group": return t("memory.scope.group");
|
|
6578
|
+
case "shared-friend": return t("memory.scope.friend");
|
|
6579
|
+
default: return scope.kind;
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
function MemoryPane({ t, allow, scope }) {
|
|
6583
|
+
const [items, setItems] = (0, react.useState)([]);
|
|
6584
|
+
const [loading, setLoading] = (0, react.useState)(true);
|
|
6585
|
+
const [draft, setDraft] = (0, react.useState)("");
|
|
6586
|
+
const [draftKind, setDraftKind] = (0, react.useState)(scope.kind === "agent" ? "agent" : scope.kind === "shared-group" ? "shared-group" : scope.kind === "shared-friend" ? "shared-friend" : "global");
|
|
6587
|
+
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
6588
|
+
const [editText, setEditText] = (0, react.useState)("");
|
|
6589
|
+
const [editKind, setEditKind] = (0, react.useState)("global");
|
|
6590
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
6591
|
+
/** Which scope the list is filtered to (`all` = show every allowed memory). */
|
|
6592
|
+
const [filter, setFilter] = (0, react.useState)("all");
|
|
6593
|
+
const agentName = scope.kind === "agent" ? scope.name : void 0;
|
|
6594
|
+
const groupGid = scope.kind === "shared-group" ? scope.gid : void 0;
|
|
6595
|
+
const friendFp = scope.kind === "shared-friend" ? scope.fp : void 0;
|
|
6596
|
+
/** Build the memory scope object for a selectable kind, using this pane's identity. */
|
|
6597
|
+
const scopeFor = (kind) => kind === "agent" ? {
|
|
6598
|
+
kind: "agent",
|
|
6599
|
+
name: agentName ?? ""
|
|
6600
|
+
} : kind === "shared-group" ? {
|
|
6601
|
+
kind: "shared-group",
|
|
6602
|
+
gid: groupGid ?? ""
|
|
6603
|
+
} : kind === "shared-friend" ? {
|
|
6604
|
+
kind: "shared-friend",
|
|
6605
|
+
fp: friendFp ?? ""
|
|
6606
|
+
} : { kind: "global" };
|
|
6607
|
+
/** The scope choices this pane offers (global always; its own only when it has one). */
|
|
6608
|
+
const scopeOptions = scope.kind === "agent" ? [{
|
|
6609
|
+
kind: "global",
|
|
6610
|
+
label: t("memory.scope.global")
|
|
6611
|
+
}, {
|
|
6612
|
+
kind: "agent",
|
|
6613
|
+
label: t("memory.scope.onlyAgent")
|
|
6614
|
+
}] : scope.kind === "shared-group" ? [{
|
|
6615
|
+
kind: "global",
|
|
6616
|
+
label: t("memory.scope.global")
|
|
6617
|
+
}, {
|
|
6618
|
+
kind: "shared-group",
|
|
6619
|
+
label: t("memory.scope.onlyGroup")
|
|
6620
|
+
}] : scope.kind === "shared-friend" ? [{
|
|
6621
|
+
kind: "global",
|
|
6622
|
+
label: t("memory.scope.global")
|
|
6623
|
+
}, {
|
|
6624
|
+
kind: "shared-friend",
|
|
6625
|
+
label: t("memory.scope.onlyFriend")
|
|
6626
|
+
}] : [{
|
|
6627
|
+
kind: "global",
|
|
6628
|
+
label: t("memory.scope.global")
|
|
6629
|
+
}];
|
|
6630
|
+
/** The list filtered by the active filter (`all` = everything allowed). */
|
|
6631
|
+
const filteredItems = filter === "all" ? items : items.filter((m) => m.scope.kind === filter);
|
|
6632
|
+
const reload = (0, react.useCallback)(() => {
|
|
6633
|
+
setLoading(true);
|
|
6634
|
+
api.memoryList(allow).then(({ memories }) => {
|
|
6635
|
+
setItems(memories);
|
|
6636
|
+
}).catch(() => {}).finally(() => {
|
|
6637
|
+
setLoading(false);
|
|
6638
|
+
});
|
|
6639
|
+
}, [allow]);
|
|
6640
|
+
(0, react.useEffect)(() => {
|
|
6641
|
+
reload();
|
|
6642
|
+
}, [reload]);
|
|
6643
|
+
const add = () => {
|
|
6644
|
+
if (draft.trim() === "" || busy) return;
|
|
6645
|
+
setBusy(true);
|
|
6646
|
+
api.memoryAdd({
|
|
6647
|
+
kind: "fact",
|
|
6648
|
+
content: draft.trim(),
|
|
6649
|
+
scope: scopeFor(draftKind)
|
|
6650
|
+
}).then(() => {
|
|
6651
|
+
setDraft("");
|
|
6652
|
+
reload();
|
|
6653
|
+
}).catch(() => {}).finally(() => {
|
|
6654
|
+
setBusy(false);
|
|
6655
|
+
});
|
|
6656
|
+
};
|
|
6657
|
+
const saveEdit = (uid) => {
|
|
6658
|
+
if (editText.trim() === "") return;
|
|
6659
|
+
api.memoryUpdate(uid, editText.trim(), scopeFor(editKind)).then(() => {
|
|
6660
|
+
setEditing(void 0);
|
|
6661
|
+
reload();
|
|
6662
|
+
}).catch(() => {});
|
|
6663
|
+
};
|
|
6664
|
+
const remove = (uid) => {
|
|
6665
|
+
api.memoryRemove(uid).then(() => {
|
|
6666
|
+
reload();
|
|
6667
|
+
}).catch(() => {});
|
|
6668
|
+
};
|
|
6669
|
+
const scopePicker = (value, onChange, dataAttr) => {
|
|
6670
|
+
if (scopeOptions.length <= 1) return null;
|
|
6671
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
6672
|
+
style: {
|
|
6673
|
+
display: "flex",
|
|
6674
|
+
alignItems: "center",
|
|
6675
|
+
gap: 6,
|
|
6676
|
+
fontSize: 12,
|
|
6677
|
+
opacity: .85,
|
|
6678
|
+
whiteSpace: "nowrap"
|
|
6679
|
+
},
|
|
6680
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("memory.scope.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
6681
|
+
className: "sm-select",
|
|
6682
|
+
style: {
|
|
6683
|
+
fontSize: 12,
|
|
6684
|
+
padding: "3px 6px"
|
|
6685
|
+
},
|
|
6686
|
+
value,
|
|
6687
|
+
onChange: (e) => {
|
|
6688
|
+
onChange(e.target.value);
|
|
6689
|
+
},
|
|
6690
|
+
"data-soulmirror-memory-scope-pick": dataAttr,
|
|
6691
|
+
children: scopeOptions.map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6692
|
+
value: o.kind,
|
|
6693
|
+
children: o.label
|
|
6694
|
+
}, o.kind))
|
|
6695
|
+
})]
|
|
6696
|
+
});
|
|
6697
|
+
};
|
|
6698
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6699
|
+
className: "sm-home",
|
|
6700
|
+
"data-soulmirror-memory-pane": true,
|
|
6701
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6702
|
+
className: "sm-home-inner",
|
|
6703
|
+
children: [
|
|
6704
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6705
|
+
style: {
|
|
6706
|
+
display: "flex",
|
|
6707
|
+
gap: 8,
|
|
6708
|
+
alignItems: "flex-end"
|
|
6709
|
+
},
|
|
6710
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
6711
|
+
className: "sm-textarea-box",
|
|
6712
|
+
style: {
|
|
6713
|
+
flex: 1,
|
|
6714
|
+
minHeight: 40,
|
|
6715
|
+
resize: "vertical"
|
|
6716
|
+
},
|
|
6717
|
+
value: draft,
|
|
6718
|
+
placeholder: t("memory.add.placeholder"),
|
|
6719
|
+
onChange: (e) => {
|
|
6720
|
+
setDraft(e.target.value);
|
|
6721
|
+
},
|
|
6722
|
+
"data-soulmirror-memory-draft": true
|
|
6723
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6724
|
+
type: "button",
|
|
6725
|
+
className: "sm-ghostbtn",
|
|
6726
|
+
disabled: busy || draft.trim() === "",
|
|
6727
|
+
onClick: add,
|
|
6728
|
+
"data-soulmirror-memory-add": true,
|
|
6729
|
+
children: t("memory.add")
|
|
6730
|
+
})]
|
|
6731
|
+
}),
|
|
6732
|
+
scopePicker(draftKind, setDraftKind, "add"),
|
|
6733
|
+
scopeOptions.length > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6734
|
+
style: {
|
|
6735
|
+
display: "flex",
|
|
6736
|
+
alignItems: "center",
|
|
6737
|
+
gap: 6,
|
|
6738
|
+
flexWrap: "wrap",
|
|
6739
|
+
marginTop: 8
|
|
6740
|
+
},
|
|
6741
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6742
|
+
style: {
|
|
6743
|
+
fontSize: 12,
|
|
6744
|
+
opacity: .85
|
|
6745
|
+
},
|
|
6746
|
+
children: t("memory.filter.label")
|
|
6747
|
+
}), [{
|
|
6748
|
+
kind: "all",
|
|
6749
|
+
label: t("memory.filter.all")
|
|
6750
|
+
}, ...scopeOptions].map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6751
|
+
type: "button",
|
|
6752
|
+
className: "sm-ghostbtn",
|
|
6753
|
+
style: {
|
|
6754
|
+
fontSize: 12,
|
|
6755
|
+
padding: "2px 10px",
|
|
6756
|
+
borderRadius: 12,
|
|
6757
|
+
...filter === o.kind ? {
|
|
6758
|
+
borderColor: "var(--dsw-alias-accent, #4c8dff)",
|
|
6759
|
+
color: "var(--dsw-alias-accent, #4c8dff)"
|
|
6760
|
+
} : {}
|
|
6761
|
+
},
|
|
6762
|
+
"aria-pressed": filter === o.kind,
|
|
6763
|
+
onClick: () => {
|
|
6764
|
+
setFilter(o.kind);
|
|
6765
|
+
},
|
|
6766
|
+
"data-soulmirror-memory-filter": o.kind,
|
|
6767
|
+
children: o.label
|
|
6768
|
+
}, o.kind))]
|
|
6769
|
+
}) : null,
|
|
6770
|
+
loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6771
|
+
className: "sm-muted",
|
|
6772
|
+
style: {
|
|
6773
|
+
fontSize: 12,
|
|
6774
|
+
padding: "8px 0",
|
|
6775
|
+
display: "block"
|
|
6776
|
+
},
|
|
6777
|
+
children: t("page.thread.loading")
|
|
6778
|
+
}) : items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6779
|
+
className: "sm-muted",
|
|
6780
|
+
style: {
|
|
6781
|
+
fontSize: 12,
|
|
6782
|
+
padding: "8px 0",
|
|
6783
|
+
display: "block"
|
|
6784
|
+
},
|
|
6785
|
+
children: t("memory.empty.page")
|
|
6786
|
+
}) : filteredItems.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6787
|
+
className: "sm-muted",
|
|
6788
|
+
style: {
|
|
6789
|
+
fontSize: 12,
|
|
6790
|
+
padding: "8px 0",
|
|
6791
|
+
display: "block"
|
|
6792
|
+
},
|
|
6793
|
+
children: t("memory.empty.filter")
|
|
6794
|
+
}) : null,
|
|
6795
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6796
|
+
style: {
|
|
6797
|
+
display: "grid",
|
|
6798
|
+
gap: 8,
|
|
6799
|
+
marginTop: 8
|
|
6800
|
+
},
|
|
6801
|
+
children: filteredItems.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6802
|
+
className: "sm-home-card",
|
|
6803
|
+
style: { padding: "10px 12px" },
|
|
6804
|
+
"data-soulmirror-memory": m.uid,
|
|
6805
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6806
|
+
style: {
|
|
6807
|
+
display: "flex",
|
|
6808
|
+
gap: 6,
|
|
6809
|
+
alignItems: "center",
|
|
6810
|
+
flexWrap: "wrap"
|
|
6811
|
+
},
|
|
6812
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6813
|
+
style: m.origin === "manual" ? manualPill : autoPill,
|
|
6814
|
+
"data-soulmirror-memory-origin": m.origin,
|
|
6815
|
+
children: m.origin === "manual" ? t("memory.origin.manual") : t("memory.origin.auto")
|
|
6816
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6817
|
+
style: pill,
|
|
6818
|
+
"data-soulmirror-memory-scope": m.scope.kind,
|
|
6819
|
+
children: scopeLabel(t, m.scope)
|
|
6820
|
+
})]
|
|
6821
|
+
}), editing === m.uid ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6822
|
+
style: {
|
|
6823
|
+
display: "grid",
|
|
6824
|
+
gap: 8,
|
|
6825
|
+
marginTop: 8
|
|
6826
|
+
},
|
|
6827
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
6828
|
+
className: "sm-textarea-box",
|
|
6829
|
+
style: {
|
|
6830
|
+
flex: 1,
|
|
6831
|
+
minHeight: 40
|
|
6832
|
+
},
|
|
6833
|
+
value: editText,
|
|
6834
|
+
onChange: (e) => {
|
|
6835
|
+
setEditText(e.target.value);
|
|
6836
|
+
}
|
|
6837
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6838
|
+
style: {
|
|
6839
|
+
display: "flex",
|
|
6840
|
+
gap: 8,
|
|
6841
|
+
alignItems: "center",
|
|
6842
|
+
flexWrap: "wrap"
|
|
6843
|
+
},
|
|
6844
|
+
children: [
|
|
6845
|
+
scopePicker(editKind, setEditKind, "edit"),
|
|
6846
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
6847
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6848
|
+
type: "button",
|
|
6849
|
+
className: "sm-ghostbtn",
|
|
6850
|
+
onClick: () => {
|
|
6851
|
+
saveEdit(m.uid);
|
|
6852
|
+
},
|
|
6853
|
+
"data-soulmirror-memory-save": true,
|
|
6854
|
+
children: t("memory.save")
|
|
6855
|
+
}),
|
|
6856
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6857
|
+
type: "button",
|
|
6858
|
+
className: "sm-ghostbtn",
|
|
6859
|
+
onClick: () => {
|
|
6860
|
+
setEditing(void 0);
|
|
6861
|
+
},
|
|
6862
|
+
children: t("inbox.close")
|
|
6863
|
+
})
|
|
6864
|
+
]
|
|
6865
|
+
})]
|
|
6866
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6867
|
+
style: {
|
|
6868
|
+
marginTop: 6,
|
|
6869
|
+
fontSize: 13,
|
|
6870
|
+
lineHeight: 1.5,
|
|
6871
|
+
whiteSpace: "pre-wrap",
|
|
6872
|
+
overflowWrap: "anywhere"
|
|
6873
|
+
},
|
|
6874
|
+
children: m.content
|
|
6875
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6876
|
+
style: {
|
|
6877
|
+
display: "flex",
|
|
6878
|
+
gap: 8,
|
|
6879
|
+
marginTop: 6
|
|
6880
|
+
},
|
|
6881
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6882
|
+
type: "button",
|
|
6883
|
+
className: "sm-linkbtn sm-muted",
|
|
6884
|
+
style: { fontSize: 11.5 },
|
|
6885
|
+
onClick: () => {
|
|
6886
|
+
setEditing(m.uid);
|
|
6887
|
+
setEditText(m.content);
|
|
6888
|
+
setEditKind(m.scope.kind === "agent" ? "agent" : m.scope.kind === "shared-group" ? "shared-group" : m.scope.kind === "shared-friend" ? "shared-friend" : "global");
|
|
6889
|
+
},
|
|
6890
|
+
"data-soulmirror-memory-edit": true,
|
|
6891
|
+
children: t("memory.edit")
|
|
6892
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6893
|
+
type: "button",
|
|
6894
|
+
className: "sm-linkbtn sm-muted",
|
|
6895
|
+
style: { fontSize: 11.5 },
|
|
6896
|
+
onClick: () => {
|
|
6897
|
+
remove(m.uid);
|
|
6898
|
+
},
|
|
6899
|
+
"data-soulmirror-memory-delete": true,
|
|
6900
|
+
children: t("memory.delete")
|
|
6901
|
+
})]
|
|
6902
|
+
})] })]
|
|
6903
|
+
}, m.uid))
|
|
6904
|
+
})
|
|
6905
|
+
]
|
|
6906
|
+
})
|
|
6907
|
+
});
|
|
6908
|
+
}
|
|
6909
|
+
//#endregion
|
|
5688
6910
|
//#region src/client/AgentPane.tsx
|
|
5689
6911
|
/**
|
|
5690
6912
|
* Right pane for one NAMED seat agent: the owner talks to it directly here
|
|
5691
6913
|
* (composer → `agent.instruct`), watches its transcript (`agent.history`,
|
|
5692
6914
|
* same fold as the alter's — owner bubbles right, the agent's notes left,
|
|
5693
6915
|
* the group messages that woke it as compact cards, its group posts as send
|
|
5694
|
-
* lines) and reaches its settings (the sheet)
|
|
5695
|
-
*
|
|
5696
|
-
* debounced refetch.
|
|
6916
|
+
* lines) and reaches its settings (the sheet). Live: SSE `agent` frames for
|
|
6917
|
+
* this name trigger a debounced refetch.
|
|
5697
6918
|
*/
|
|
5698
6919
|
const FOLLOW_SLACK$2 = 48;
|
|
5699
6920
|
const HISTORY_LIMIT = 200;
|
|
@@ -5702,7 +6923,7 @@ window.__ModuleLoader__.load({
|
|
|
5702
6923
|
const d = new Date(ts);
|
|
5703
6924
|
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
|
|
5704
6925
|
}
|
|
5705
|
-
function AgentPane({ t, agent,
|
|
6926
|
+
function AgentPane({ t, agent, onRemoved }) {
|
|
5706
6927
|
const name = agent.name;
|
|
5707
6928
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
5708
6929
|
const [history, setHistory] = (0, react.useState)(void 0);
|
|
@@ -5999,13 +7220,13 @@ window.__ModuleLoader__.load({
|
|
|
5999
7220
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6000
7221
|
className: "sm-home-title",
|
|
6001
7222
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("agent.home.actions") })
|
|
6002
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7223
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6003
7224
|
style: {
|
|
6004
7225
|
display: "flex",
|
|
6005
7226
|
gap: 6,
|
|
6006
7227
|
flexWrap: "wrap"
|
|
6007
7228
|
},
|
|
6008
|
-
children:
|
|
7229
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
6009
7230
|
type: "button",
|
|
6010
7231
|
className: "sm-ghostbtn",
|
|
6011
7232
|
onClick: () => {
|
|
@@ -6016,18 +7237,7 @@ window.__ModuleLoader__.load({
|
|
|
6016
7237
|
" ",
|
|
6017
7238
|
t("agent.settings")
|
|
6018
7239
|
]
|
|
6019
|
-
})
|
|
6020
|
-
type: "button",
|
|
6021
|
-
className: "sm-ghostbtn",
|
|
6022
|
-
onClick: () => {
|
|
6023
|
-
onOpenSession(sessionId);
|
|
6024
|
-
},
|
|
6025
|
-
children: [
|
|
6026
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 }),
|
|
6027
|
-
" ",
|
|
6028
|
-
t("alter.openDsh")
|
|
6029
|
-
]
|
|
6030
|
-
}) : null]
|
|
7240
|
+
})
|
|
6031
7241
|
})]
|
|
6032
7242
|
})
|
|
6033
7243
|
]
|
|
@@ -6071,9 +7281,9 @@ window.__ModuleLoader__.load({
|
|
|
6071
7281
|
]
|
|
6072
7282
|
})]
|
|
6073
7283
|
}),
|
|
6074
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7284
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6075
7285
|
className: "sm-chat-head-actions",
|
|
6076
|
-
children:
|
|
7286
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6077
7287
|
label: t("agent.settings"),
|
|
6078
7288
|
side: "bottom",
|
|
6079
7289
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -6089,23 +7299,7 @@ window.__ModuleLoader__.load({
|
|
|
6089
7299
|
t("agent.settings")
|
|
6090
7300
|
]
|
|
6091
7301
|
})
|
|
6092
|
-
})
|
|
6093
|
-
label: t("alter.openDsh.hint"),
|
|
6094
|
-
side: "bottom",
|
|
6095
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
6096
|
-
type: "button",
|
|
6097
|
-
className: "sm-ghostbtn",
|
|
6098
|
-
onClick: () => {
|
|
6099
|
-
onOpenSession(sessionId);
|
|
6100
|
-
},
|
|
6101
|
-
"data-soulmirror-agent-open-dsh": true,
|
|
6102
|
-
children: [
|
|
6103
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 }),
|
|
6104
|
-
" ",
|
|
6105
|
-
t("alter.openDsh")
|
|
6106
|
-
]
|
|
6107
|
-
})
|
|
6108
|
-
}) : null]
|
|
7302
|
+
})
|
|
6109
7303
|
})
|
|
6110
7304
|
]
|
|
6111
7305
|
}),
|
|
@@ -6115,7 +7309,17 @@ window.__ModuleLoader__.load({
|
|
|
6115
7309
|
onChange: pageStore.setPaneTab,
|
|
6116
7310
|
t
|
|
6117
7311
|
}),
|
|
6118
|
-
paneTab === "info" ? agentInfo : /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7312
|
+
paneTab === "info" ? agentInfo : paneTab === "memory" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryPane, {
|
|
7313
|
+
t,
|
|
7314
|
+
allow: {
|
|
7315
|
+
global: true,
|
|
7316
|
+
agent: name
|
|
7317
|
+
},
|
|
7318
|
+
scope: {
|
|
7319
|
+
kind: "agent",
|
|
7320
|
+
name
|
|
7321
|
+
}
|
|
7322
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6119
7323
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6120
7324
|
ref: scroller,
|
|
6121
7325
|
className: "sm-thread",
|
|
@@ -6244,12 +7448,17 @@ window.__ModuleLoader__.load({
|
|
|
6244
7448
|
default: return t("draft.reason.unknown-trigger");
|
|
6245
7449
|
}
|
|
6246
7450
|
}
|
|
6247
|
-
function DraftCard({ draft, t, showTarget, onGoFriend }) {
|
|
7451
|
+
function DraftCard({ draft, t, showTarget, onGoFriend, onGoGroup }) {
|
|
6248
7452
|
const busy = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot).deciding.includes(draft.id);
|
|
6249
7453
|
const [mode, setMode] = (0, react.useState)("idle");
|
|
6250
7454
|
const [text, setText] = (0, react.useState)(draft.body);
|
|
6251
7455
|
const [feedback, setFeedback] = (0, react.useState)("");
|
|
6252
7456
|
const inReplyTo = draft.trigger?.kind === "inbound" ? draft.trigger.name ?? draft.name : void 0;
|
|
7457
|
+
const openTarget = draft.gid !== void 0 && onGoGroup !== void 0 ? () => {
|
|
7458
|
+
onGoGroup(draft.gid);
|
|
7459
|
+
} : onGoFriend !== void 0 ? () => {
|
|
7460
|
+
onGoFriend(draft.fp);
|
|
7461
|
+
} : void 0;
|
|
6253
7462
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6254
7463
|
className: "sm-draft",
|
|
6255
7464
|
"data-soulmirror-draft": draft.id,
|
|
@@ -6263,13 +7472,11 @@ window.__ModuleLoader__.load({
|
|
|
6263
7472
|
children: t("draft.tag")
|
|
6264
7473
|
}),
|
|
6265
7474
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: showTarget === true ? t("draft.title.to", { name: draft.name }) : t("draft.title") }),
|
|
6266
|
-
showTarget === true &&
|
|
7475
|
+
showTarget === true && openTarget !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6267
7476
|
type: "button",
|
|
6268
7477
|
className: "sm-linkbtn",
|
|
6269
|
-
onClick:
|
|
6270
|
-
|
|
6271
|
-
},
|
|
6272
|
-
children: t("draft.openThread")
|
|
7478
|
+
onClick: openTarget,
|
|
7479
|
+
children: draft.gid !== void 0 ? t("draft.openGroup") : t("draft.openThread")
|
|
6273
7480
|
}) : null,
|
|
6274
7481
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6275
7482
|
className: "sm-row-time",
|
|
@@ -6436,7 +7643,7 @@ window.__ModuleLoader__.load({
|
|
|
6436
7643
|
const d = new Date(ts);
|
|
6437
7644
|
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
|
|
6438
7645
|
}
|
|
6439
|
-
function AlterPane({ t,
|
|
7646
|
+
function AlterPane({ t, onGoFriend, onGoGroup, renderCards, scope }) {
|
|
6440
7647
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
6441
7648
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
6442
7649
|
const alter = page.alter;
|
|
@@ -6444,6 +7651,23 @@ window.__ModuleLoader__.load({
|
|
|
6444
7651
|
const drafts = net.inbox.drafts;
|
|
6445
7652
|
const running = alter.status === "running" || alter.chat.running || alter.instructing;
|
|
6446
7653
|
const [draft, setDraft] = (0, react.useState)("");
|
|
7654
|
+
const [wallet, setWallet] = (0, react.useState)(void 0);
|
|
7655
|
+
(0, react.useEffect)(() => {
|
|
7656
|
+
let alive = true;
|
|
7657
|
+
const load = () => {
|
|
7658
|
+
api.payWallet().then((r) => {
|
|
7659
|
+
if (alive) setWallet(r.wallet ?? null);
|
|
7660
|
+
}).catch(() => {
|
|
7661
|
+
if (alive) setWallet(null);
|
|
7662
|
+
});
|
|
7663
|
+
};
|
|
7664
|
+
load();
|
|
7665
|
+
const timer = setInterval(load, 15e3);
|
|
7666
|
+
return () => {
|
|
7667
|
+
alive = false;
|
|
7668
|
+
clearInterval(timer);
|
|
7669
|
+
};
|
|
7670
|
+
}, []);
|
|
6447
7671
|
const scroller = (0, react.useRef)(null);
|
|
6448
7672
|
const textarea = (0, react.useRef)(null);
|
|
6449
7673
|
const following = (0, react.useRef)(true);
|
|
@@ -6460,7 +7684,7 @@ window.__ModuleLoader__.load({
|
|
|
6460
7684
|
if (el === null) return;
|
|
6461
7685
|
if (firstPaint.current && items.length > 0) {
|
|
6462
7686
|
firstPaint.current = false;
|
|
6463
|
-
el.scrollTop =
|
|
7687
|
+
el.scrollTop = el.scrollHeight;
|
|
6464
7688
|
return;
|
|
6465
7689
|
}
|
|
6466
7690
|
if (following.current) el.scrollTop = el.scrollHeight;
|
|
@@ -6568,31 +7792,33 @@ window.__ModuleLoader__.load({
|
|
|
6568
7792
|
})]
|
|
6569
7793
|
});
|
|
6570
7794
|
case "inbound": {
|
|
6571
|
-
const
|
|
7795
|
+
const group = item.gid === void 0 ? void 0 : net.inbox.groups.find((g) => g.gid === item.gid);
|
|
7796
|
+
const name = group !== void 0 ? group.name : nameOf(friends, item.fp, item.name);
|
|
7797
|
+
const open = () => {
|
|
7798
|
+
if (group !== void 0) onGoGroup(group.gid);
|
|
7799
|
+
else onGoFriend(item.fp);
|
|
7800
|
+
};
|
|
6572
7801
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6573
7802
|
className: "sm-citem sm-wide",
|
|
6574
|
-
"data-soulmirror-alter-item": "inbound",
|
|
7803
|
+
"data-soulmirror-alter-item": group !== void 0 ? "group" : "inbound",
|
|
6575
7804
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6576
7805
|
className: "sm-inmail",
|
|
6577
7806
|
role: "button",
|
|
6578
7807
|
tabIndex: 0,
|
|
6579
|
-
onClick:
|
|
6580
|
-
onGoFriend(item.fp);
|
|
6581
|
-
},
|
|
7808
|
+
onClick: open,
|
|
6582
7809
|
onKeyDown: (e) => {
|
|
6583
|
-
if (e.key === "Enter")
|
|
7810
|
+
if (e.key === "Enter") open();
|
|
6584
7811
|
},
|
|
6585
7812
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6586
7813
|
className: "sm-inmail-head",
|
|
6587
7814
|
children: [
|
|
6588
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.item.inbound", { name: "" }) }),
|
|
6589
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: name }),
|
|
7815
|
+
group !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.item.groupInbound", { name }) }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.item.inbound", { name: "" }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: name })] }),
|
|
6590
7816
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["· ", formatClock(item.ts)] }),
|
|
6591
7817
|
item.auto ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["· ", t("bubble.auto")] }) : null,
|
|
6592
7818
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6593
7819
|
style: { marginLeft: "auto" },
|
|
6594
7820
|
className: "sm-linkbtn",
|
|
6595
|
-
children: t("alter.item.view")
|
|
7821
|
+
children: group !== void 0 ? t("alter.item.viewGroup", { name }) : t("alter.item.view")
|
|
6596
7822
|
})
|
|
6597
7823
|
]
|
|
6598
7824
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -6725,110 +7951,88 @@ window.__ModuleLoader__.load({
|
|
|
6725
7951
|
"data-soulmirror-alter-home": true,
|
|
6726
7952
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6727
7953
|
className: "sm-home-inner",
|
|
6728
|
-
children: [
|
|
6729
|
-
|
|
6730
|
-
|
|
7954
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7955
|
+
className: "sm-home-id",
|
|
7956
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7957
|
+
className: "sm-avatar sm-avatar-alter sm-avatar-lg",
|
|
7958
|
+
"aria-hidden": true,
|
|
7959
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SoulMirrorIcon, { size: 18 })
|
|
7960
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7961
|
+
style: {
|
|
7962
|
+
display: "grid",
|
|
7963
|
+
gap: 2,
|
|
7964
|
+
minWidth: 0
|
|
7965
|
+
},
|
|
6731
7966
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6732
|
-
className: "sm-
|
|
6733
|
-
"
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
style: {
|
|
6737
|
-
display: "grid",
|
|
6738
|
-
gap: 2,
|
|
6739
|
-
minWidth: 0
|
|
6740
|
-
},
|
|
7967
|
+
className: "sm-home-id-name",
|
|
7968
|
+
children: t("alter.me")
|
|
7969
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7970
|
+
className: "sm-home-id-sub",
|
|
6741
7971
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6742
|
-
className: "sm-
|
|
6743
|
-
|
|
6744
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
6745
|
-
className: "sm-home-id-sub",
|
|
6746
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6747
|
-
className: `sm-livedot${running ? " sm-busy" : ""}`,
|
|
6748
|
-
"aria-hidden": true
|
|
6749
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: alter.sessionId === void 0 ? t("alter.status.noSession") : running ? t("alter.status.running") : t("alter.status.idle") })]
|
|
6750
|
-
})]
|
|
7972
|
+
className: `sm-livedot${running ? " sm-busy" : ""}`,
|
|
7973
|
+
"aria-hidden": true
|
|
7974
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: alter.sessionId === void 0 ? t("alter.status.noSession") : running ? t("alter.status.running") : t("alter.status.idle") })]
|
|
6751
7975
|
})]
|
|
6752
|
-
})
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
className: "sm-home-title",
|
|
6758
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.home.profile") })
|
|
6759
|
-
}),
|
|
6760
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6761
|
-
className: "sm-home-line",
|
|
6762
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6763
|
-
className: "sm-home-line-key",
|
|
6764
|
-
children: t("alter.home.session")
|
|
6765
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6766
|
-
className: "sm-home-line-val",
|
|
6767
|
-
children: alter.sessionId ?? t("alter.home.none")
|
|
6768
|
-
})]
|
|
6769
|
-
}),
|
|
6770
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6771
|
-
className: "sm-home-line",
|
|
6772
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6773
|
-
className: "sm-home-line-key",
|
|
6774
|
-
children: t("alter.home.friends")
|
|
6775
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6776
|
-
className: "sm-home-line-val",
|
|
6777
|
-
children: friends.length
|
|
6778
|
-
})]
|
|
6779
|
-
}),
|
|
6780
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6781
|
-
className: "sm-home-line",
|
|
6782
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6783
|
-
className: "sm-home-line-key",
|
|
6784
|
-
children: t("alter.home.drafts")
|
|
6785
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6786
|
-
className: "sm-home-line-val",
|
|
6787
|
-
children: drafts.length
|
|
6788
|
-
})]
|
|
6789
|
-
}),
|
|
6790
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6791
|
-
className: "sm-home-line",
|
|
6792
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6793
|
-
className: "sm-home-line-key",
|
|
6794
|
-
children: t("alter.home.defaultTier")
|
|
6795
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6796
|
-
className: "sm-home-line-val",
|
|
6797
|
-
children: t(`tier.short.${net.state?.alter?.defaultTier ?? "draft"}`)
|
|
6798
|
-
})]
|
|
6799
|
-
}),
|
|
6800
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6801
|
-
className: "sm-home-line",
|
|
6802
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6803
|
-
className: "sm-home-line-key",
|
|
6804
|
-
children: t("alter.home.perHour")
|
|
6805
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6806
|
-
className: "sm-home-line-val",
|
|
6807
|
-
children: net.state?.alter?.autoReplyPerHour ?? 20
|
|
6808
|
-
})]
|
|
6809
|
-
})
|
|
6810
|
-
]
|
|
6811
|
-
}),
|
|
6812
|
-
alter.sessionId !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6813
|
-
className: "sm-home-card",
|
|
6814
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7976
|
+
})]
|
|
7977
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7978
|
+
className: "sm-home-card",
|
|
7979
|
+
children: [
|
|
7980
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6815
7981
|
className: "sm-home-title",
|
|
6816
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.home.
|
|
6817
|
-
}),
|
|
6818
|
-
|
|
6819
|
-
className: "sm-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
"
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
7982
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.home.profile") })
|
|
7983
|
+
}),
|
|
7984
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7985
|
+
className: "sm-home-line",
|
|
7986
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7987
|
+
className: "sm-home-line-key",
|
|
7988
|
+
children: t("alter.home.session")
|
|
7989
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7990
|
+
className: "sm-home-line-val",
|
|
7991
|
+
children: alter.sessionId ?? t("alter.home.none")
|
|
7992
|
+
})]
|
|
7993
|
+
}),
|
|
7994
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7995
|
+
className: "sm-home-line",
|
|
7996
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7997
|
+
className: "sm-home-line-key",
|
|
7998
|
+
children: t("alter.home.friends")
|
|
7999
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8000
|
+
className: "sm-home-line-val",
|
|
8001
|
+
children: friends.length
|
|
8002
|
+
})]
|
|
8003
|
+
}),
|
|
8004
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8005
|
+
className: "sm-home-line",
|
|
8006
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8007
|
+
className: "sm-home-line-key",
|
|
8008
|
+
children: t("alter.home.drafts")
|
|
8009
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8010
|
+
className: "sm-home-line-val",
|
|
8011
|
+
children: drafts.length
|
|
8012
|
+
})]
|
|
8013
|
+
}),
|
|
8014
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8015
|
+
className: "sm-home-line",
|
|
8016
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8017
|
+
className: "sm-home-line-key",
|
|
8018
|
+
children: t("alter.home.defaultTier")
|
|
8019
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8020
|
+
className: "sm-home-line-val",
|
|
8021
|
+
children: t(`tier.short.${net.state?.alter?.defaultTier ?? "draft"}`)
|
|
8022
|
+
})]
|
|
8023
|
+
}),
|
|
8024
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8025
|
+
className: "sm-home-line",
|
|
8026
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8027
|
+
className: "sm-home-line-key",
|
|
8028
|
+
children: t("alter.home.perHour")
|
|
8029
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8030
|
+
className: "sm-home-line-val",
|
|
8031
|
+
children: net.state?.alter?.autoReplyPerHour ?? 20
|
|
8032
|
+
})]
|
|
8033
|
+
})
|
|
8034
|
+
]
|
|
8035
|
+
})]
|
|
6832
8036
|
})
|
|
6833
8037
|
});
|
|
6834
8038
|
const cardProps = {
|
|
@@ -6836,10 +8040,7 @@ window.__ModuleLoader__.load({
|
|
|
6836
8040
|
sessionId: alter.sessionId,
|
|
6837
8041
|
status: alter.status
|
|
6838
8042
|
},
|
|
6839
|
-
scope
|
|
6840
|
-
openSession: () => {
|
|
6841
|
-
if (alter.sessionId !== void 0) onOpenSession(alter.sessionId);
|
|
6842
|
-
}
|
|
8043
|
+
scope
|
|
6843
8044
|
};
|
|
6844
8045
|
const alterSettings = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6845
8046
|
className: "sm-home",
|
|
@@ -6857,58 +8058,86 @@ window.__ModuleLoader__.load({
|
|
|
6857
8058
|
children: [
|
|
6858
8059
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
6859
8060
|
className: "sm-chat-head",
|
|
8061
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8062
|
+
className: "sm-avatar sm-avatar-alter sm-avatar-lg",
|
|
8063
|
+
"aria-hidden": true,
|
|
8064
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SoulMirrorIcon, { size: 18 })
|
|
8065
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8066
|
+
style: {
|
|
8067
|
+
flex: 1,
|
|
8068
|
+
minWidth: 0,
|
|
8069
|
+
display: "grid"
|
|
8070
|
+
},
|
|
8071
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8072
|
+
className: "sm-chat-head-name",
|
|
8073
|
+
children: t("alter.me")
|
|
8074
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8075
|
+
className: "sm-chat-head-sub",
|
|
8076
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8077
|
+
className: `sm-livedot${running ? " sm-busy" : ""}`,
|
|
8078
|
+
"aria-hidden": true
|
|
8079
|
+
}), alter.sessionId === void 0 ? t("alter.status.noSession") : running ? t("alter.status.running") : t("alter.status.idle")]
|
|
8080
|
+
})]
|
|
8081
|
+
})]
|
|
8082
|
+
}),
|
|
8083
|
+
wallet !== void 0 && wallet !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8084
|
+
className: "sm-alter-wallet",
|
|
8085
|
+
"data-soulmirror-alter-wallet": true,
|
|
8086
|
+
style: {
|
|
8087
|
+
display: "flex",
|
|
8088
|
+
alignItems: "center",
|
|
8089
|
+
gap: 8,
|
|
8090
|
+
padding: "6px 14px",
|
|
8091
|
+
fontSize: "0.8em",
|
|
8092
|
+
opacity: .9,
|
|
8093
|
+
borderBottom: "1px solid rgba(127,127,127,.18)"
|
|
8094
|
+
},
|
|
6860
8095
|
children: [
|
|
6861
8096
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6862
|
-
|
|
6863
|
-
"
|
|
6864
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SoulMirrorIcon, { size: 18 })
|
|
8097
|
+
style: { opacity: .7 },
|
|
8098
|
+
children: t("alter.wallet")
|
|
6865
8099
|
}),
|
|
6866
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
8100
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6867
8101
|
style: {
|
|
8102
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
6868
8103
|
flex: 1,
|
|
6869
8104
|
minWidth: 0,
|
|
6870
|
-
|
|
8105
|
+
overflow: "hidden",
|
|
8106
|
+
textOverflow: "ellipsis",
|
|
8107
|
+
whiteSpace: "nowrap"
|
|
6871
8108
|
},
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
}
|
|
8109
|
+
title: wallet.address,
|
|
8110
|
+
"data-soulmirror-alter-wallet-address": true,
|
|
8111
|
+
children: wallet.address
|
|
8112
|
+
}),
|
|
8113
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8114
|
+
style: {
|
|
8115
|
+
opacity: .85,
|
|
8116
|
+
whiteSpace: "nowrap"
|
|
8117
|
+
},
|
|
8118
|
+
children: wallet.balance_usdc !== void 0 ? `USDC ${wallet.balance_usdc}` : ""
|
|
6882
8119
|
}),
|
|
6883
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
onClick: () => {
|
|
6892
|
-
onOpenSession(alter.sessionId);
|
|
6893
|
-
},
|
|
6894
|
-
"data-soulmirror-alter-open-dsh": true,
|
|
6895
|
-
children: [
|
|
6896
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 }),
|
|
6897
|
-
" ",
|
|
6898
|
-
t("alter.openDsh")
|
|
6899
|
-
]
|
|
6900
|
-
})
|
|
6901
|
-
}) : null
|
|
6902
|
-
})
|
|
8120
|
+
wallet.balance_eth !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8121
|
+
style: {
|
|
8122
|
+
opacity: .6,
|
|
8123
|
+
whiteSpace: "nowrap"
|
|
8124
|
+
},
|
|
8125
|
+
"data-soulmirror-alter-wallet-eth": true,
|
|
8126
|
+
children: ["ETH ", Number(wallet.balance_eth).toFixed(4)]
|
|
8127
|
+
}) : null
|
|
6903
8128
|
]
|
|
6904
|
-
}),
|
|
8129
|
+
}) : null,
|
|
6905
8130
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContentTabs, {
|
|
6906
8131
|
tabs,
|
|
6907
8132
|
active: paneTab,
|
|
6908
8133
|
onChange: pageStore.setPaneTab,
|
|
6909
8134
|
t
|
|
6910
8135
|
}),
|
|
6911
|
-
paneTab === "settings" ? alterSettings : paneTab === "home" ? alterHome : /* @__PURE__ */ (0, react_jsx_runtime.
|
|
8136
|
+
paneTab === "settings" ? alterSettings : paneTab === "home" ? alterHome : paneTab === "memory" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryPane, {
|
|
8137
|
+
t,
|
|
8138
|
+
allow: { global: true },
|
|
8139
|
+
scope: { kind: "global" }
|
|
8140
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6912
8141
|
drafts.length > 0 && firstDraft !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6913
8142
|
className: "sm-pendbar",
|
|
6914
8143
|
"data-soulmirror-alter-pendbar": drafts.length,
|
|
@@ -6965,7 +8194,8 @@ window.__ModuleLoader__.load({
|
|
|
6965
8194
|
draft: d,
|
|
6966
8195
|
t,
|
|
6967
8196
|
showTarget: true,
|
|
6968
|
-
onGoFriend
|
|
8197
|
+
onGoFriend,
|
|
8198
|
+
onGoGroup
|
|
6969
8199
|
}, d.id)),
|
|
6970
8200
|
running ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6971
8201
|
className: "sm-citem sm-alter",
|
|
@@ -7028,6 +8258,36 @@ window.__ModuleLoader__.load({
|
|
|
7028
8258
|
});
|
|
7029
8259
|
}
|
|
7030
8260
|
//#endregion
|
|
8261
|
+
//#region src/group-contract.ts
|
|
8262
|
+
/**
|
|
8263
|
+
* Paid-join compatibility encoding: on relays that only accept
|
|
8264
|
+
* join ∈ {invite, apply, open}, the paid config is carried as a convention
|
|
8265
|
+
* line in `rules` (`#paid-join <price> <0xaddr>`) — a field old relays keep
|
|
8266
|
+
* verbatim. The line is hidden from every user-facing rules display.
|
|
8267
|
+
*/
|
|
8268
|
+
const PAID_JOIN_PREFIX = "#paid-join ";
|
|
8269
|
+
/** Parse the paid-join marker out of rules (any line, trimmed). */
|
|
8270
|
+
function paidJoinFromRules(rules) {
|
|
8271
|
+
if (rules === void 0 || rules === "") return void 0;
|
|
8272
|
+
for (const line of rules.split("\n")) {
|
|
8273
|
+
const t = line.trim();
|
|
8274
|
+
if (t.startsWith("#paid-join ")) {
|
|
8275
|
+
const rest = t.slice(11).trim().split(/\s+/);
|
|
8276
|
+
const price = rest[0];
|
|
8277
|
+
const addr = rest[1];
|
|
8278
|
+
if (price !== void 0 && addr !== void 0 && addr.startsWith("0x") && price !== "") return {
|
|
8279
|
+
price,
|
|
8280
|
+
addr
|
|
8281
|
+
};
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8284
|
+
}
|
|
8285
|
+
/** rules without the paid-join marker line (for display / prompts). */
|
|
8286
|
+
function rulesWithoutPaidJoin(rules) {
|
|
8287
|
+
if (rules === void 0 || rules === "") return "";
|
|
8288
|
+
return rules.split("\n").filter((l) => !l.trim().startsWith(PAID_JOIN_PREFIX)).join("\n").trim();
|
|
8289
|
+
}
|
|
8290
|
+
//#endregion
|
|
7031
8291
|
//#region src/client/group-templates.ts
|
|
7032
8292
|
const base = (id, patch) => ({
|
|
7033
8293
|
id,
|
|
@@ -7099,7 +8359,7 @@ window.__ModuleLoader__.load({
|
|
|
7099
8359
|
* The dialog owns the form state; the caller owns the actual creation
|
|
7100
8360
|
* (`onCreate`) and the busy flag.
|
|
7101
8361
|
*/
|
|
7102
|
-
function GroupCreateDialog({ t, friends, busy, onCreate, onClose }) {
|
|
8362
|
+
function GroupCreateDialog({ t, friends, busy, walletAddress, onCreate, onClose }) {
|
|
7103
8363
|
const std = GROUP_TEMPLATES[0].profile;
|
|
7104
8364
|
const [name, setName] = (0, react.useState)("");
|
|
7105
8365
|
const [sel, setSel] = (0, react.useState)({});
|
|
@@ -7110,6 +8370,7 @@ window.__ModuleLoader__.load({
|
|
|
7110
8370
|
speakAgents: std.speakAgents,
|
|
7111
8371
|
speakWho: std.speakWho ?? "all",
|
|
7112
8372
|
join: std.join ?? "invite",
|
|
8373
|
+
joinPrice: "",
|
|
7113
8374
|
agentWake: std.agentWake ?? "mention",
|
|
7114
8375
|
agentTier: std.agentTier ?? "draft",
|
|
7115
8376
|
rules: "",
|
|
@@ -7126,10 +8387,12 @@ window.__ModuleLoader__.load({
|
|
|
7126
8387
|
};
|
|
7127
8388
|
}, [onClose]);
|
|
7128
8389
|
const members = Object.entries(sel).filter(([, v]) => v).map(([k]) => k);
|
|
7129
|
-
const
|
|
8390
|
+
const paidIncomplete = adv.join === "paid" && (walletAddress === void 0 || adv.joinPrice.trim() === "");
|
|
8391
|
+
const ready = !busy && name.trim() !== "" && members.length > 0 && !paidIncomplete;
|
|
7130
8392
|
const submit = () => {
|
|
7131
8393
|
if (!ready) return;
|
|
7132
8394
|
const tags = adv.tags.split(",").map((s) => s.trim()).filter((s) => s !== "");
|
|
8395
|
+
const paid = adv.join === "paid" && walletAddress !== void 0 && adv.joinPrice.trim() !== "";
|
|
7133
8396
|
const profile = templateProfile(tpl, {
|
|
7134
8397
|
speakHumans: adv.speakHumans,
|
|
7135
8398
|
speakAgents: adv.speakAgents,
|
|
@@ -7138,6 +8401,10 @@ window.__ModuleLoader__.load({
|
|
|
7138
8401
|
agentWake: adv.agentWake,
|
|
7139
8402
|
agentTier: adv.agentTier,
|
|
7140
8403
|
...adv.rules.trim() === "" ? {} : { rules: adv.rules },
|
|
8404
|
+
...paid ? {
|
|
8405
|
+
joinPrice: adv.joinPrice.trim(),
|
|
8406
|
+
joinAddr: walletAddress
|
|
8407
|
+
} : {},
|
|
7141
8408
|
...adv.isPublic ? { public: true } : {},
|
|
7142
8409
|
...tags.length === 0 ? {} : { tags }
|
|
7143
8410
|
});
|
|
@@ -7301,31 +8568,92 @@ window.__ModuleLoader__.load({
|
|
|
7301
8568
|
}),
|
|
7302
8569
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7303
8570
|
className: "sm-field",
|
|
7304
|
-
children: [
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
8571
|
+
children: [
|
|
8572
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.join") }),
|
|
8573
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
8574
|
+
className: "sm-select",
|
|
8575
|
+
value: adv.join,
|
|
8576
|
+
onChange: (e) => {
|
|
8577
|
+
setAdv({
|
|
8578
|
+
...adv,
|
|
8579
|
+
join: e.target.value,
|
|
8580
|
+
...e.target.value === "paid" ? { isPublic: true } : {}
|
|
8581
|
+
});
|
|
8582
|
+
},
|
|
8583
|
+
children: [
|
|
8584
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
8585
|
+
value: "invite",
|
|
8586
|
+
children: t("group.form.join.invite")
|
|
8587
|
+
}),
|
|
8588
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
8589
|
+
value: "apply",
|
|
8590
|
+
children: t("group.form.join.apply")
|
|
8591
|
+
}),
|
|
8592
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
8593
|
+
value: "open",
|
|
8594
|
+
children: t("group.form.join.open")
|
|
8595
|
+
}),
|
|
8596
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
8597
|
+
value: "paid",
|
|
8598
|
+
disabled: walletAddress === void 0,
|
|
8599
|
+
children: [t("group.form.join.paid"), walletAddress === void 0 ? `(${t("group.form.join.paid.noWallet")})` : ""]
|
|
8600
|
+
})
|
|
8601
|
+
]
|
|
8602
|
+
}),
|
|
8603
|
+
adv.join === "paid" && !adv.isPublic ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8604
|
+
style: {
|
|
8605
|
+
fontSize: "0.82em",
|
|
8606
|
+
margin: 0
|
|
8607
|
+
},
|
|
8608
|
+
children: t("group.form.join.paid.autoPublic")
|
|
8609
|
+
}) : null
|
|
8610
|
+
]
|
|
7328
8611
|
}),
|
|
8612
|
+
adv.join === "paid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
8613
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
8614
|
+
className: "sm-field",
|
|
8615
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.joinPrice") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
8616
|
+
className: "sm-input",
|
|
8617
|
+
type: "text",
|
|
8618
|
+
placeholder: "1.00",
|
|
8619
|
+
value: adv.joinPrice,
|
|
8620
|
+
disabled: walletAddress === void 0,
|
|
8621
|
+
onChange: (e) => {
|
|
8622
|
+
setAdv({
|
|
8623
|
+
...adv,
|
|
8624
|
+
joinPrice: e.target.value
|
|
8625
|
+
});
|
|
8626
|
+
},
|
|
8627
|
+
"data-soulmirror-group-create-join-price": true
|
|
8628
|
+
})]
|
|
8629
|
+
}),
|
|
8630
|
+
paidIncomplete && adv.joinPrice.trim() === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8631
|
+
style: {
|
|
8632
|
+
fontSize: "0.82em",
|
|
8633
|
+
margin: 0,
|
|
8634
|
+
color: "rgb(220,80,60)"
|
|
8635
|
+
},
|
|
8636
|
+
"data-soulmirror-group-create-paid-missing": true,
|
|
8637
|
+
children: t("group.form.join.paid.priceRequired")
|
|
8638
|
+
}) : null,
|
|
8639
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8640
|
+
style: {
|
|
8641
|
+
fontSize: "0.82em",
|
|
8642
|
+
opacity: .7,
|
|
8643
|
+
margin: 0
|
|
8644
|
+
},
|
|
8645
|
+
children: walletAddress === void 0 ? t("group.form.join.paid.noWalletHint") : t("group.form.joinAddr", { address: walletAddress })
|
|
8646
|
+
}),
|
|
8647
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8648
|
+
style: {
|
|
8649
|
+
fontSize: "0.82em",
|
|
8650
|
+
opacity: .7,
|
|
8651
|
+
margin: 0
|
|
8652
|
+
},
|
|
8653
|
+
"data-soulmirror-group-create-paid-hint": true,
|
|
8654
|
+
children: t("group.form.join.paid.membersFree")
|
|
8655
|
+
})
|
|
8656
|
+
] }) : null,
|
|
7329
8657
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7330
8658
|
className: "sm-field",
|
|
7331
8659
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.wake") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
@@ -7460,6 +8788,10 @@ window.__ModuleLoader__.load({
|
|
|
7460
8788
|
* (card URI + note) at the bottom. The selected row is highlighted; clicking
|
|
7461
8789
|
* a friend row selects it (the friend pane marks it read).
|
|
7462
8790
|
*/
|
|
8791
|
+
/** How many seat agents are shown before the rest collapses behind an expander. */
|
|
8792
|
+
const AGENT_COLLAPSE = 3;
|
|
8793
|
+
/** How many friends / groups the address book shows before the rest collapses. */
|
|
8794
|
+
const CONTACT_COLLAPSE = 10;
|
|
7463
8795
|
function useCopy() {
|
|
7464
8796
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
7465
8797
|
return [copied, (0, react.useCallback)((text) => {
|
|
@@ -7599,7 +8931,77 @@ window.__ModuleLoader__.load({
|
|
|
7599
8931
|
})]
|
|
7600
8932
|
}) });
|
|
7601
8933
|
}
|
|
7602
|
-
|
|
8934
|
+
/** One row of the address book (通讯录): avatar + name + presence, alphabetical, no message preview. */
|
|
8935
|
+
function ContactRow({ f, selected, t, onSelect }) {
|
|
8936
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8937
|
+
type: "button",
|
|
8938
|
+
className: `sm-row${selected ? " sm-selected" : ""}`,
|
|
8939
|
+
onClick: onSelect,
|
|
8940
|
+
"aria-pressed": selected,
|
|
8941
|
+
"data-soulmirror-page-contact": f.fp,
|
|
8942
|
+
"data-soulmirror-selected": selected ? "true" : void 0,
|
|
8943
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8944
|
+
className: "sm-avawrap",
|
|
8945
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8946
|
+
className: "sm-avatar",
|
|
8947
|
+
"aria-hidden": true,
|
|
8948
|
+
children: f.name.slice(0, 1)
|
|
8949
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8950
|
+
className: `sm-presence${f.online === true ? " sm-online" : ""}`,
|
|
8951
|
+
title: f.online === true ? t("inbox.online") : t("inbox.offline")
|
|
8952
|
+
})]
|
|
8953
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8954
|
+
className: "sm-row-body",
|
|
8955
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8956
|
+
className: "sm-row-title",
|
|
8957
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8958
|
+
className: "sm-row-name",
|
|
8959
|
+
children: f.name
|
|
8960
|
+
}), f.tier !== void 0 && f.tier !== "draft" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TierPill, {
|
|
8961
|
+
tier: f.tier,
|
|
8962
|
+
t
|
|
8963
|
+
}) : null]
|
|
8964
|
+
})
|
|
8965
|
+
})]
|
|
8966
|
+
}) });
|
|
8967
|
+
}
|
|
8968
|
+
/** One group row of the address book (通讯录): avatar with the group mark + name + member count. */
|
|
8969
|
+
function GroupContactRow({ g, selected, t, onSelect }) {
|
|
8970
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8971
|
+
type: "button",
|
|
8972
|
+
className: `sm-row${selected ? " sm-selected" : ""}`,
|
|
8973
|
+
onClick: onSelect,
|
|
8974
|
+
"aria-pressed": selected,
|
|
8975
|
+
"data-soulmirror-page-contact-group": g.gid,
|
|
8976
|
+
"data-soulmirror-selected": selected ? "true" : void 0,
|
|
8977
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8978
|
+
className: "sm-avawrap",
|
|
8979
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8980
|
+
className: "sm-avatar",
|
|
8981
|
+
"aria-hidden": true,
|
|
8982
|
+
children: g.name.slice(0, 1)
|
|
8983
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8984
|
+
className: "sm-gmark",
|
|
8985
|
+
"aria-hidden": true,
|
|
8986
|
+
title: t("group.section"),
|
|
8987
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupMarkIcon, {})
|
|
8988
|
+
})]
|
|
8989
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8990
|
+
className: "sm-row-body",
|
|
8991
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8992
|
+
className: "sm-row-title",
|
|
8993
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8994
|
+
className: "sm-row-name",
|
|
8995
|
+
children: g.name
|
|
8996
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8997
|
+
className: "sm-row-time",
|
|
8998
|
+
children: t("group.members", { n: g.members })
|
|
8999
|
+
})]
|
|
9000
|
+
})
|
|
9001
|
+
})]
|
|
9002
|
+
}) });
|
|
9003
|
+
}
|
|
9004
|
+
function FriendList({ t, selected, onSelect, onSelectContact, onAccepted, onClose }) {
|
|
7603
9005
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
7604
9006
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
7605
9007
|
const { inbox } = net;
|
|
@@ -7613,10 +9015,26 @@ window.__ModuleLoader__.load({
|
|
|
7613
9015
|
const [note, setNote] = (0, react.useState)(void 0);
|
|
7614
9016
|
const [protocolOpen, setProtocolOpen] = (0, react.useState)(false);
|
|
7615
9017
|
const [createOpen, setCreateOpen] = (0, react.useState)(false);
|
|
9018
|
+
const [walletAddress, setWalletAddress] = (0, react.useState)(void 0);
|
|
9019
|
+
const loadWallet = (0, react.useCallback)(() => {
|
|
9020
|
+
api.payWallet().then((r) => {
|
|
9021
|
+
setWalletAddress(r.wallet?.address);
|
|
9022
|
+
}).catch(() => {});
|
|
9023
|
+
}, []);
|
|
9024
|
+
(0, react.useEffect)(() => {
|
|
9025
|
+
loadWallet();
|
|
9026
|
+
}, [loadWallet]);
|
|
7616
9027
|
const [joinUri, setJoinUri] = (0, react.useState)("");
|
|
9028
|
+
/** The join dialog's group card lookup (paid groups require a payment proof). */
|
|
9029
|
+
const [joinCard, setJoinCard] = (0, react.useState)(void 0);
|
|
9030
|
+
const [joinTx, setJoinTx] = (0, react.useState)("");
|
|
9031
|
+
const [payConfirming, setPayConfirming] = (0, react.useState)(false);
|
|
7617
9032
|
/** The WeChat-style "+" menu and the small dialog it opens. */
|
|
7618
9033
|
const [plusOpen, setPlusOpen] = (0, react.useState)(false);
|
|
7619
9034
|
const [agentSheetOpen, setAgentSheetOpen] = (0, react.useState)(false);
|
|
9035
|
+
const [agentsExpanded, setAgentsExpanded] = (0, react.useState)(false);
|
|
9036
|
+
const [friendsExpanded, setFriendsExpanded] = (0, react.useState)(false);
|
|
9037
|
+
const [groupsExpanded, setGroupsExpanded] = (0, react.useState)(false);
|
|
7620
9038
|
const [dialog, setDialog] = (0, react.useState)(void 0);
|
|
7621
9039
|
(0, react.useEffect)(() => {
|
|
7622
9040
|
if (query.trim() === "") return;
|
|
@@ -7657,8 +9075,15 @@ window.__ModuleLoader__.load({
|
|
|
7657
9075
|
const nb = b.kind === "friend" ? b.f.name : b.g.name;
|
|
7658
9076
|
return na.localeCompare(nb);
|
|
7659
9077
|
});
|
|
7660
|
-
const
|
|
7661
|
-
const
|
|
9078
|
+
const contactRows = filterFriends(inbox.friends, query).sort((a, b) => a.name.localeCompare(b.name));
|
|
9079
|
+
const groupContactRows = inbox.groups.filter((g) => q === "" || g.name.toLowerCase().includes(q)).sort((a, b) => a.name.localeCompare(b.name));
|
|
9080
|
+
const agents = net.state?.agents ?? [];
|
|
9081
|
+
const agentsExpandedNow = agentsExpanded || agents.length <= AGENT_COLLAPSE;
|
|
9082
|
+
const visibleAgents = agentsExpandedNow ? agents : agents.slice(0, AGENT_COLLAPSE);
|
|
9083
|
+
const friendsExpandedNow = friendsExpanded || contactRows.length <= CONTACT_COLLAPSE;
|
|
9084
|
+
const visibleContactRows = friendsExpandedNow ? contactRows : contactRows.slice(0, CONTACT_COLLAPSE);
|
|
9085
|
+
const groupsExpandedNow = groupsExpanded || groupContactRows.length <= CONTACT_COLLAPSE;
|
|
9086
|
+
const visibleGroupContactRows = groupsExpandedNow ? groupContactRows : groupContactRows.slice(0, CONTACT_COLLAPSE);
|
|
7662
9087
|
const nameHits = q === "" ? [] : rows.filter((r) => r.kind === "friend" ? r.f.name.toLowerCase().includes(q) || (r.f.remark ?? "").toLowerCase().includes(q) || r.f.fp.toLowerCase().startsWith(q) : r.g.name.toLowerCase().includes(q));
|
|
7663
9088
|
const contentHits = q === "" ? [] : (() => {
|
|
7664
9089
|
const out = [];
|
|
@@ -7725,33 +9150,74 @@ window.__ModuleLoader__.load({
|
|
|
7725
9150
|
const submitJoin = () => {
|
|
7726
9151
|
if (busy !== void 0 || joinUri.trim() === "" || identity === null) return;
|
|
7727
9152
|
run("group.apply", async () => {
|
|
9153
|
+
let card = null;
|
|
9154
|
+
try {
|
|
9155
|
+
card = (await api.groupLookup(joinUri.trim())).card;
|
|
9156
|
+
} catch {
|
|
9157
|
+
card = null;
|
|
9158
|
+
}
|
|
9159
|
+
const paid = card !== null ? card.join === "paid" ? {
|
|
9160
|
+
price: card.joinPrice,
|
|
9161
|
+
addr: card.joinAddr
|
|
9162
|
+
} : paidJoinFromRules(card.rulesHead) : void 0;
|
|
9163
|
+
setJoinCard(card === null ? void 0 : {
|
|
9164
|
+
name: card.name,
|
|
9165
|
+
join: card.join,
|
|
9166
|
+
...paid === void 0 ? {} : {
|
|
9167
|
+
price: paid.price,
|
|
9168
|
+
addr: paid.addr
|
|
9169
|
+
}
|
|
9170
|
+
});
|
|
9171
|
+
if (paid !== void 0) {
|
|
9172
|
+
if (paid.price === void 0 || paid.addr === void 0) throw new Error(t("group.join.paid.noPrice"));
|
|
9173
|
+
if (walletAddress !== void 0) {
|
|
9174
|
+
if (!payConfirming) {
|
|
9175
|
+
setPayConfirming(true);
|
|
9176
|
+
return;
|
|
9177
|
+
}
|
|
9178
|
+
setPayConfirming(false);
|
|
9179
|
+
const { gid, tx_hash, amount } = await api.groupPaidJoin(joinUri.trim());
|
|
9180
|
+
setJoinUri("");
|
|
9181
|
+
setJoinTx("");
|
|
9182
|
+
setJoinCard(void 0);
|
|
9183
|
+
setDialog(void 0);
|
|
9184
|
+
if (gid !== "") onSelect(groupKey(gid));
|
|
9185
|
+
return t("group.join.paid.paidViaLocal", {
|
|
9186
|
+
amount: amount ?? paid.price,
|
|
9187
|
+
tx: tx_hash ?? ""
|
|
9188
|
+
});
|
|
9189
|
+
}
|
|
9190
|
+
if (joinTx.trim() === "") throw new Error(t("group.join.paid.needProof", {
|
|
9191
|
+
price: paid.price,
|
|
9192
|
+
addr: paid.addr
|
|
9193
|
+
}));
|
|
9194
|
+
const { gid } = await api.groupApply(joinUri.trim(), t("group.join.paid.note", { price: paid.price }), {
|
|
9195
|
+
tx_hash: joinTx.trim(),
|
|
9196
|
+
amount: paid.price,
|
|
9197
|
+
to: paid.addr
|
|
9198
|
+
});
|
|
9199
|
+
setJoinUri("");
|
|
9200
|
+
setJoinTx("");
|
|
9201
|
+
setJoinCard(void 0);
|
|
9202
|
+
setDialog(void 0);
|
|
9203
|
+
if (gid !== "") onSelect(groupKey(gid));
|
|
9204
|
+
return t("group.join.paid.applied");
|
|
9205
|
+
}
|
|
7728
9206
|
const { gid } = await api.groupApply(joinUri.trim());
|
|
7729
9207
|
setJoinUri("");
|
|
9208
|
+
setJoinCard(void 0);
|
|
7730
9209
|
setDialog(void 0);
|
|
7731
9210
|
if (gid !== "") {
|
|
7732
|
-
pageStore.setCol2Tab("
|
|
9211
|
+
pageStore.setCol2Tab("messages");
|
|
7733
9212
|
onSelect(groupKey(gid));
|
|
7734
9213
|
}
|
|
7735
9214
|
return t("group.join.applied");
|
|
7736
9215
|
});
|
|
7737
9216
|
};
|
|
7738
|
-
const upgrade = (0, react.useSyncExternalStore)(upgradeStore.subscribe, upgradeStore.getSnapshot);
|
|
7739
|
-
const upgradeBusy = upgrade.phase === "installing" || upgrade.phase === "restarting" || upgrade.phase === "reloading";
|
|
7740
9217
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
7741
9218
|
className: "sm-list-col",
|
|
7742
9219
|
"data-soulmirror-page-list": true,
|
|
7743
9220
|
children: [
|
|
7744
|
-
upgrade.hasUpdate || upgradeBusy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7745
|
-
type: "button",
|
|
7746
|
-
className: "sm-update-banner",
|
|
7747
|
-
disabled: upgradeBusy,
|
|
7748
|
-
"data-soulmirror-update-banner": upgrade.latest,
|
|
7749
|
-
onClick: () => {
|
|
7750
|
-
if (upgradeBusy || upgrade.latest === void 0) return;
|
|
7751
|
-
if (window.confirm(t("page.update.confirm", { v: upgrade.latest }))) upgradeStore.run();
|
|
7752
|
-
},
|
|
7753
|
-
children: upgradeBusy ? t("page.update.busy") : t("page.update.banner", { v: upgrade.latest ?? "" })
|
|
7754
|
-
}) : null,
|
|
7755
9221
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7756
9222
|
className: "sm-list-head",
|
|
7757
9223
|
children: [
|
|
@@ -8038,7 +9504,7 @@ window.__ModuleLoader__.load({
|
|
|
8038
9504
|
role: "menuitem",
|
|
8039
9505
|
onClick: () => {
|
|
8040
9506
|
setPlusOpen(false);
|
|
8041
|
-
pageStore.setCol2Tab("
|
|
9507
|
+
pageStore.setCol2Tab("messages");
|
|
8042
9508
|
setCreateOpen(true);
|
|
8043
9509
|
},
|
|
8044
9510
|
"data-soulmirror-plus-new-group": true,
|
|
@@ -8060,6 +9526,7 @@ window.__ModuleLoader__.load({
|
|
|
8060
9526
|
onClick: () => {
|
|
8061
9527
|
setPlusOpen(false);
|
|
8062
9528
|
setDialog("join");
|
|
9529
|
+
loadWallet();
|
|
8063
9530
|
},
|
|
8064
9531
|
"data-soulmirror-plus-join-group": true,
|
|
8065
9532
|
children: t("foot.joinGroup")
|
|
@@ -8072,11 +9539,7 @@ window.__ModuleLoader__.load({
|
|
|
8072
9539
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8073
9540
|
className: "sm-col2-tabs",
|
|
8074
9541
|
"data-soulmirror-col2-tabs": true,
|
|
8075
|
-
children: [
|
|
8076
|
-
"contacts",
|
|
8077
|
-
"agents",
|
|
8078
|
-
"groups"
|
|
8079
|
-
].map((tab) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9542
|
+
children: ["messages", "contacts"].map((tab) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8080
9543
|
type: "button",
|
|
8081
9544
|
className: `sm-col2-tab${col2Tab === tab ? " sm-active" : ""}`,
|
|
8082
9545
|
onClick: () => {
|
|
@@ -8091,7 +9554,7 @@ window.__ModuleLoader__.load({
|
|
|
8091
9554
|
className: "sm-list-body",
|
|
8092
9555
|
children: [
|
|
8093
9556
|
protocolOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProtocolEditor, { t }) : null,
|
|
8094
|
-
col2Tab === "
|
|
9557
|
+
col2Tab === "messages" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
8095
9558
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8096
9559
|
className: "sm-section",
|
|
8097
9560
|
children: t("col2.contacts.section")
|
|
@@ -8144,6 +9607,134 @@ window.__ModuleLoader__.load({
|
|
|
8144
9607
|
})]
|
|
8145
9608
|
}) })
|
|
8146
9609
|
}),
|
|
9610
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9611
|
+
className: "sm-section",
|
|
9612
|
+
style: {
|
|
9613
|
+
display: "flex",
|
|
9614
|
+
alignItems: "center",
|
|
9615
|
+
gap: 8
|
|
9616
|
+
},
|
|
9617
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9618
|
+
style: { flex: 1 },
|
|
9619
|
+
children: t("agents.section")
|
|
9620
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9621
|
+
type: "button",
|
|
9622
|
+
className: "sm-linkbtn",
|
|
9623
|
+
onClick: () => {
|
|
9624
|
+
setAgentSheetOpen(true);
|
|
9625
|
+
},
|
|
9626
|
+
"data-soulmirror-agents-add": true,
|
|
9627
|
+
children: ["+ ", t("settings.agents.add")]
|
|
9628
|
+
})]
|
|
9629
|
+
}),
|
|
9630
|
+
agents.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9631
|
+
className: "sm-muted",
|
|
9632
|
+
style: {
|
|
9633
|
+
margin: 0,
|
|
9634
|
+
padding: "4px 10px 10px",
|
|
9635
|
+
fontSize: 12
|
|
9636
|
+
},
|
|
9637
|
+
"data-soulmirror-page-empty-list": true,
|
|
9638
|
+
children: t("col2.agents.empty")
|
|
9639
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
9640
|
+
style: {
|
|
9641
|
+
listStyle: "none",
|
|
9642
|
+
margin: 0,
|
|
9643
|
+
padding: 0
|
|
9644
|
+
},
|
|
9645
|
+
children: visibleAgents.map((a) => {
|
|
9646
|
+
const key = agentKey(a.name);
|
|
9647
|
+
const agentSelected = selected === key;
|
|
9648
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9649
|
+
type: "button",
|
|
9650
|
+
className: `sm-row${agentSelected ? " sm-selected" : ""}`,
|
|
9651
|
+
onClick: () => {
|
|
9652
|
+
onSelect(key);
|
|
9653
|
+
},
|
|
9654
|
+
"aria-pressed": agentSelected,
|
|
9655
|
+
"data-soulmirror-page-agent": a.name,
|
|
9656
|
+
"data-soulmirror-selected": agentSelected ? "true" : void 0,
|
|
9657
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9658
|
+
className: "sm-avawrap",
|
|
9659
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9660
|
+
className: "sm-avatar",
|
|
9661
|
+
"aria-hidden": true,
|
|
9662
|
+
children: "🤖"
|
|
9663
|
+
})
|
|
9664
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9665
|
+
className: "sm-row-body",
|
|
9666
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9667
|
+
className: "sm-row-title",
|
|
9668
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9669
|
+
className: "sm-row-name",
|
|
9670
|
+
children: [
|
|
9671
|
+
a.name,
|
|
9672
|
+
" ",
|
|
9673
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9674
|
+
className: `sm-livedot${a.status === "running" ? " sm-busy" : ""}`,
|
|
9675
|
+
"aria-hidden": true
|
|
9676
|
+
})
|
|
9677
|
+
]
|
|
9678
|
+
})
|
|
9679
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9680
|
+
className: "sm-row-preview",
|
|
9681
|
+
children: a.status === "running" ? t("settings.agents.status.running") : a.cwd ?? t("settings.agents.status.idle")
|
|
9682
|
+
})]
|
|
9683
|
+
})]
|
|
9684
|
+
}) }, a.name);
|
|
9685
|
+
})
|
|
9686
|
+
}), agents.length > AGENT_COLLAPSE ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9687
|
+
type: "button",
|
|
9688
|
+
className: "sm-linkbtn",
|
|
9689
|
+
style: { margin: "2px 10px 6px" },
|
|
9690
|
+
onClick: () => {
|
|
9691
|
+
setAgentsExpanded((v) => !v);
|
|
9692
|
+
},
|
|
9693
|
+
"data-soulmirror-agents-expand": true,
|
|
9694
|
+
children: agentsExpandedNow ? t("agents.collapse") : t("agents.expand", { n: agents.length - AGENT_COLLAPSE })
|
|
9695
|
+
}) : null] }),
|
|
9696
|
+
agentSheetOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentSettingsSheet, {
|
|
9697
|
+
t,
|
|
9698
|
+
onClose: () => {
|
|
9699
|
+
setAgentSheetOpen(false);
|
|
9700
|
+
},
|
|
9701
|
+
onSaved: (name) => {
|
|
9702
|
+
onSelect(agentKey(name));
|
|
9703
|
+
}
|
|
9704
|
+
}) : null,
|
|
9705
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9706
|
+
className: "sm-section",
|
|
9707
|
+
children: t("chats.section")
|
|
9708
|
+
}),
|
|
9709
|
+
rows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9710
|
+
className: "sm-muted",
|
|
9711
|
+
style: {
|
|
9712
|
+
margin: 0,
|
|
9713
|
+
padding: "4px 10px 10px",
|
|
9714
|
+
fontSize: 12
|
|
9715
|
+
},
|
|
9716
|
+
"data-soulmirror-page-empty-list": true,
|
|
9717
|
+
children: identity === null ? t("page.empty.noFriends.noIdentity") : t("chats.empty")
|
|
9718
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
9719
|
+
style: {
|
|
9720
|
+
listStyle: "none",
|
|
9721
|
+
margin: 0,
|
|
9722
|
+
padding: 0
|
|
9723
|
+
},
|
|
9724
|
+
"data-soulmirror-page-chats": true,
|
|
9725
|
+
children: rows.map((r) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChatRow, {
|
|
9726
|
+
row: r,
|
|
9727
|
+
typing: r.kind === "friend" && (inbox.typing[r.f.fp] === true || r.f.typing === true),
|
|
9728
|
+
apps: r.kind === "group" ? inbox.groupApps[r.g.gid] ?? 0 : 0,
|
|
9729
|
+
selected: selected === r.rowKey,
|
|
9730
|
+
t,
|
|
9731
|
+
onSelect: () => {
|
|
9732
|
+
onSelect(r.rowKey);
|
|
9733
|
+
}
|
|
9734
|
+
}, r.rowKey))
|
|
9735
|
+
})
|
|
9736
|
+
] }),
|
|
9737
|
+
col2Tab === "contacts" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
8147
9738
|
inbox.pending.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8148
9739
|
className: "sm-section",
|
|
8149
9740
|
children: [
|
|
@@ -8223,9 +9814,9 @@ window.__ModuleLoader__.load({
|
|
|
8223
9814
|
})] }) : null,
|
|
8224
9815
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8225
9816
|
className: "sm-section",
|
|
8226
|
-
children: t("
|
|
9817
|
+
children: t("inbox.friends")
|
|
8227
9818
|
}),
|
|
8228
|
-
|
|
9819
|
+
contactRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8229
9820
|
className: "sm-muted",
|
|
8230
9821
|
style: {
|
|
8231
9822
|
margin: 0,
|
|
@@ -8233,49 +9824,37 @@ window.__ModuleLoader__.load({
|
|
|
8233
9824
|
fontSize: 12
|
|
8234
9825
|
},
|
|
8235
9826
|
"data-soulmirror-page-empty-list": true,
|
|
8236
|
-
children: identity === null ? t("page.empty.noFriends.noIdentity") : q !== "" ? t("page.empty.noMatch", { query }) : t("
|
|
8237
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
9827
|
+
children: identity === null ? t("page.empty.noFriends.noIdentity") : q !== "" ? t("page.empty.noMatch", { query }) : t("inbox.empty")
|
|
9828
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
8238
9829
|
style: {
|
|
8239
9830
|
listStyle: "none",
|
|
8240
9831
|
margin: 0,
|
|
8241
9832
|
padding: 0
|
|
8242
9833
|
},
|
|
8243
|
-
"data-soulmirror-page-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
typing: inbox.typing[r.f.fp] === true || r.f.typing === true,
|
|
8248
|
-
apps: 0,
|
|
8249
|
-
selected: selected === r.rowKey,
|
|
9834
|
+
"data-soulmirror-page-contacts": true,
|
|
9835
|
+
children: visibleContactRows.map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContactRow, {
|
|
9836
|
+
f,
|
|
9837
|
+
selected: selected === f.fp,
|
|
8250
9838
|
t,
|
|
8251
9839
|
onSelect: () => {
|
|
8252
|
-
|
|
9840
|
+
onSelectContact(f.fp);
|
|
8253
9841
|
}
|
|
8254
|
-
},
|
|
8255
|
-
})
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
display: "flex",
|
|
8262
|
-
alignItems: "center",
|
|
8263
|
-
gap: 8
|
|
9842
|
+
}, f.fp))
|
|
9843
|
+
}), contactRows.length > CONTACT_COLLAPSE ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9844
|
+
type: "button",
|
|
9845
|
+
className: "sm-linkbtn",
|
|
9846
|
+
style: { margin: "2px 10px 6px" },
|
|
9847
|
+
onClick: () => {
|
|
9848
|
+
setFriendsExpanded((v) => !v);
|
|
8264
9849
|
},
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
onClick: () => {
|
|
8272
|
-
setAgentSheetOpen(true);
|
|
8273
|
-
},
|
|
8274
|
-
"data-soulmirror-agents-add": true,
|
|
8275
|
-
children: ["+ ", t("settings.agents.add")]
|
|
8276
|
-
})]
|
|
9850
|
+
"data-soulmirror-contacts-friends-expand": true,
|
|
9851
|
+
children: friendsExpandedNow ? t("agents.collapse") : t("agents.expand", { n: contactRows.length - CONTACT_COLLAPSE })
|
|
9852
|
+
}) : null] }),
|
|
9853
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9854
|
+
className: "sm-section",
|
|
9855
|
+
children: t("groups.section")
|
|
8277
9856
|
}),
|
|
8278
|
-
|
|
9857
|
+
groupContactRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8279
9858
|
className: "sm-muted",
|
|
8280
9859
|
style: {
|
|
8281
9860
|
margin: 0,
|
|
@@ -8283,95 +9862,33 @@ window.__ModuleLoader__.load({
|
|
|
8283
9862
|
fontSize: 12
|
|
8284
9863
|
},
|
|
8285
9864
|
"data-soulmirror-page-empty-list": true,
|
|
8286
|
-
children: t("col2.
|
|
8287
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
9865
|
+
children: q !== "" ? t("page.empty.noMatch", { query }) : t("col2.groups.empty")
|
|
9866
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
8288
9867
|
style: {
|
|
8289
9868
|
listStyle: "none",
|
|
8290
9869
|
margin: 0,
|
|
8291
9870
|
padding: 0
|
|
8292
9871
|
},
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
className: "sm-avatar",
|
|
8309
|
-
"aria-hidden": true,
|
|
8310
|
-
children: "🤖"
|
|
8311
|
-
})
|
|
8312
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8313
|
-
className: "sm-row-body",
|
|
8314
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8315
|
-
className: "sm-row-title",
|
|
8316
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8317
|
-
className: "sm-row-name",
|
|
8318
|
-
children: [
|
|
8319
|
-
a.name,
|
|
8320
|
-
" ",
|
|
8321
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8322
|
-
className: `sm-livedot${a.status === "running" ? " sm-busy" : ""}`,
|
|
8323
|
-
"aria-hidden": true
|
|
8324
|
-
})
|
|
8325
|
-
]
|
|
8326
|
-
})
|
|
8327
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8328
|
-
className: "sm-row-preview",
|
|
8329
|
-
children: a.status === "running" ? t("settings.agents.status.running") : a.cwd ?? t("settings.agents.status.idle")
|
|
8330
|
-
})]
|
|
8331
|
-
})]
|
|
8332
|
-
}) }, a.name);
|
|
8333
|
-
})
|
|
8334
|
-
}),
|
|
8335
|
-
agentSheetOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentSettingsSheet, {
|
|
8336
|
-
t,
|
|
8337
|
-
onClose: () => {
|
|
8338
|
-
setAgentSheetOpen(false);
|
|
9872
|
+
"data-soulmirror-page-contact-groups": true,
|
|
9873
|
+
children: visibleGroupContactRows.map((g) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupContactRow, {
|
|
9874
|
+
g,
|
|
9875
|
+
selected: selected === groupKey(g.gid),
|
|
9876
|
+
t,
|
|
9877
|
+
onSelect: () => {
|
|
9878
|
+
onSelect(groupKey(g.gid));
|
|
9879
|
+
}
|
|
9880
|
+
}, g.gid))
|
|
9881
|
+
}), groupContactRows.length > CONTACT_COLLAPSE ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9882
|
+
type: "button",
|
|
9883
|
+
className: "sm-linkbtn",
|
|
9884
|
+
style: { margin: "2px 10px 6px" },
|
|
9885
|
+
onClick: () => {
|
|
9886
|
+
setGroupsExpanded((v) => !v);
|
|
8339
9887
|
},
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
] }),
|
|
8345
|
-
col2Tab === "groups" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8346
|
-
className: "sm-section",
|
|
8347
|
-
children: t("groups.section")
|
|
8348
|
-
}), groupRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8349
|
-
className: "sm-muted",
|
|
8350
|
-
style: {
|
|
8351
|
-
margin: 0,
|
|
8352
|
-
padding: "4px 10px 10px",
|
|
8353
|
-
fontSize: 12
|
|
8354
|
-
},
|
|
8355
|
-
"data-soulmirror-page-empty-list": true,
|
|
8356
|
-
children: q !== "" ? t("page.empty.noMatch", { query }) : t("col2.groups.empty")
|
|
8357
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
8358
|
-
style: {
|
|
8359
|
-
listStyle: "none",
|
|
8360
|
-
margin: 0,
|
|
8361
|
-
padding: 0
|
|
8362
|
-
},
|
|
8363
|
-
"data-soulmirror-page-groups": true,
|
|
8364
|
-
children: groupRows.map((r) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChatRow, {
|
|
8365
|
-
row: r,
|
|
8366
|
-
typing: false,
|
|
8367
|
-
apps: inbox.groupApps[r.g.gid] ?? 0,
|
|
8368
|
-
selected: selected === r.rowKey,
|
|
8369
|
-
t,
|
|
8370
|
-
onSelect: () => {
|
|
8371
|
-
onSelect(r.rowKey);
|
|
8372
|
-
}
|
|
8373
|
-
}, r.rowKey))
|
|
8374
|
-
})] })
|
|
9888
|
+
"data-soulmirror-contacts-groups-expand": true,
|
|
9889
|
+
children: groupsExpandedNow ? t("agents.collapse") : t("agents.expand", { n: groupContactRows.length - CONTACT_COLLAPSE })
|
|
9890
|
+
}) : null] })
|
|
9891
|
+
] })
|
|
8375
9892
|
]
|
|
8376
9893
|
}),
|
|
8377
9894
|
note !== void 0 || net.error !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -8395,6 +9912,7 @@ window.__ModuleLoader__.load({
|
|
|
8395
9912
|
t,
|
|
8396
9913
|
friends: inbox.friends,
|
|
8397
9914
|
busy: busy !== void 0,
|
|
9915
|
+
...walletAddress === void 0 ? {} : { walletAddress },
|
|
8398
9916
|
onCreate: createGroup,
|
|
8399
9917
|
onClose: () => {
|
|
8400
9918
|
setCreateOpen(false);
|
|
@@ -8515,6 +10033,8 @@ window.__ModuleLoader__.load({
|
|
|
8515
10033
|
autoFocus: true,
|
|
8516
10034
|
onChange: (e) => {
|
|
8517
10035
|
setJoinUri(e.target.value);
|
|
10036
|
+
setJoinCard(void 0);
|
|
10037
|
+
setJoinTx("");
|
|
8518
10038
|
},
|
|
8519
10039
|
onKeyDown: (e) => {
|
|
8520
10040
|
if (e.key === "Enter" && !e.nativeEvent.isComposing) submitJoin();
|
|
@@ -8522,22 +10042,122 @@ window.__ModuleLoader__.load({
|
|
|
8522
10042
|
"data-soulmirror-group-join-uri": true
|
|
8523
10043
|
})]
|
|
8524
10044
|
}),
|
|
10045
|
+
joinCard !== void 0 && joinCard.price !== void 0 && joinCard.addr !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10046
|
+
style: {
|
|
10047
|
+
display: "grid",
|
|
10048
|
+
gap: 8
|
|
10049
|
+
},
|
|
10050
|
+
"data-soulmirror-group-join-paid": true,
|
|
10051
|
+
children: [
|
|
10052
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10053
|
+
style: {
|
|
10054
|
+
border: "1px solid rgba(127,127,127,.3)",
|
|
10055
|
+
borderRadius: 8,
|
|
10056
|
+
padding: "8px 10px",
|
|
10057
|
+
display: "grid",
|
|
10058
|
+
gap: 4,
|
|
10059
|
+
background: "rgba(127,127,127,.06)"
|
|
10060
|
+
},
|
|
10061
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10062
|
+
style: {
|
|
10063
|
+
fontSize: "0.75em",
|
|
10064
|
+
opacity: .7
|
|
10065
|
+
},
|
|
10066
|
+
children: t("group.join.paid.amountLabel")
|
|
10067
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10068
|
+
style: {
|
|
10069
|
+
fontSize: "1.25em",
|
|
10070
|
+
fontWeight: 700,
|
|
10071
|
+
color: "var(--dsw-alias-state-warn-primary, rgb(220,160,60))"
|
|
10072
|
+
},
|
|
10073
|
+
"data-soulmirror-group-join-price": true,
|
|
10074
|
+
children: [joinCard.price, " USDC"]
|
|
10075
|
+
})]
|
|
10076
|
+
}),
|
|
10077
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10078
|
+
style: {
|
|
10079
|
+
display: "grid",
|
|
10080
|
+
gap: 2
|
|
10081
|
+
},
|
|
10082
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10083
|
+
style: {
|
|
10084
|
+
fontSize: "0.75em",
|
|
10085
|
+
opacity: .7
|
|
10086
|
+
},
|
|
10087
|
+
children: t("group.join.paid.toLabel")
|
|
10088
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10089
|
+
style: {
|
|
10090
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
10091
|
+
fontSize: "0.82em",
|
|
10092
|
+
wordBreak: "break-all"
|
|
10093
|
+
},
|
|
10094
|
+
"data-soulmirror-group-join-addr": true,
|
|
10095
|
+
children: joinCard.addr
|
|
10096
|
+
})]
|
|
10097
|
+
}),
|
|
10098
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10099
|
+
style: {
|
|
10100
|
+
fontSize: "0.8em",
|
|
10101
|
+
margin: 0,
|
|
10102
|
+
opacity: .8
|
|
10103
|
+
},
|
|
10104
|
+
children: t("group.join.paid.payHint", { price: joinCard.price })
|
|
10105
|
+
}),
|
|
10106
|
+
walletAddress !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10107
|
+
style: {
|
|
10108
|
+
display: "grid",
|
|
10109
|
+
gap: 4
|
|
10110
|
+
},
|
|
10111
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10112
|
+
style: {
|
|
10113
|
+
fontSize: "0.8em",
|
|
10114
|
+
margin: 0,
|
|
10115
|
+
opacity: .8
|
|
10116
|
+
},
|
|
10117
|
+
"data-soulmirror-group-join-localpay": true,
|
|
10118
|
+
children: t("group.join.paid.localHint")
|
|
10119
|
+
}), payConfirming ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10120
|
+
style: {
|
|
10121
|
+
fontSize: "0.85em",
|
|
10122
|
+
margin: 0,
|
|
10123
|
+
color: "var(--dsw-alias-state-warn-primary, rgb(220,160,60))",
|
|
10124
|
+
fontWeight: 600
|
|
10125
|
+
},
|
|
10126
|
+
"data-soulmirror-group-join-confirm": true,
|
|
10127
|
+
children: t("group.join.paid.confirm", { price: joinCard.price })
|
|
10128
|
+
}) : null]
|
|
10129
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
10130
|
+
className: "sm-field",
|
|
10131
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.join.paid.tx") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
10132
|
+
className: "sm-input",
|
|
10133
|
+
placeholder: "0x…",
|
|
10134
|
+
value: joinTx,
|
|
10135
|
+
onChange: (e) => {
|
|
10136
|
+
setJoinTx(e.target.value);
|
|
10137
|
+
},
|
|
10138
|
+
"data-soulmirror-group-join-tx": true
|
|
10139
|
+
})]
|
|
10140
|
+
})
|
|
10141
|
+
]
|
|
10142
|
+
}) : null,
|
|
8525
10143
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8526
10144
|
className: "sm-modal-foot",
|
|
8527
10145
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8528
10146
|
variant: "outline",
|
|
8529
10147
|
size: "sm",
|
|
8530
10148
|
onClick: () => {
|
|
8531
|
-
|
|
10149
|
+
if (payConfirming) setPayConfirming(false);
|
|
10150
|
+
else setDialog(void 0);
|
|
8532
10151
|
},
|
|
8533
|
-
|
|
10152
|
+
"data-soulmirror-group-join-back": true,
|
|
10153
|
+
children: payConfirming ? t("group.home.edit.cancel") : t("inbox.close")
|
|
8534
10154
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8535
|
-
variant: "
|
|
10155
|
+
variant: "primary",
|
|
8536
10156
|
size: "sm",
|
|
8537
|
-
disabled: busy !== void 0 || joinUri.trim() === "",
|
|
10157
|
+
disabled: busy !== void 0 || joinUri.trim() === "" || joinCard?.price !== void 0 && walletAddress === void 0 && joinTx.trim() === "",
|
|
8538
10158
|
onClick: submitJoin,
|
|
8539
10159
|
"data-soulmirror-group-join-apply": true,
|
|
8540
|
-
children: t("group.join.apply")
|
|
10160
|
+
children: joinCard?.price !== void 0 && walletAddress !== void 0 ? payConfirming ? t("group.join.paid.confirmPay") : t("group.join.paid.payApply") : t("group.join.apply")
|
|
8541
10161
|
})]
|
|
8542
10162
|
})
|
|
8543
10163
|
]
|
|
@@ -8908,7 +10528,7 @@ window.__ModuleLoader__.load({
|
|
|
8908
10528
|
variant: "primary",
|
|
8909
10529
|
size: "sm",
|
|
8910
10530
|
onClick: onGoAlter,
|
|
8911
|
-
children: t("friend.
|
|
10531
|
+
children: t("friend.home.sendMessage")
|
|
8912
10532
|
})
|
|
8913
10533
|
]
|
|
8914
10534
|
})]
|
|
@@ -8919,6 +10539,7 @@ window.__ModuleLoader__.load({
|
|
|
8919
10539
|
tier: friend.tier,
|
|
8920
10540
|
tierExplicit: friend.tierExplicit === true,
|
|
8921
10541
|
protocol: friend.protocol,
|
|
10542
|
+
muted: friend.muted === true,
|
|
8922
10543
|
defaultTier: alterConfig?.defaultTier ?? "draft",
|
|
8923
10544
|
perHour: alterConfig?.autoReplyPerHour ?? 20,
|
|
8924
10545
|
t,
|
|
@@ -8993,7 +10614,17 @@ window.__ModuleLoader__.load({
|
|
|
8993
10614
|
onChange: pageStore.setPaneTab,
|
|
8994
10615
|
t
|
|
8995
10616
|
}),
|
|
8996
|
-
paneTab === "home" ? friendHome : /* @__PURE__ */ (0, react_jsx_runtime.
|
|
10617
|
+
paneTab === "home" ? friendHome : paneTab === "memory" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryPane, {
|
|
10618
|
+
t,
|
|
10619
|
+
allow: {
|
|
10620
|
+
global: true,
|
|
10621
|
+
friend: fp
|
|
10622
|
+
},
|
|
10623
|
+
scope: {
|
|
10624
|
+
kind: "shared-friend",
|
|
10625
|
+
fp
|
|
10626
|
+
}
|
|
10627
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
8997
10628
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8998
10629
|
className: "sm-banner",
|
|
8999
10630
|
role: "note",
|
|
@@ -9168,6 +10799,7 @@ window.__ModuleLoader__.load({
|
|
|
9168
10799
|
tier: friend.tier,
|
|
9169
10800
|
tierExplicit: friend.tierExplicit === true,
|
|
9170
10801
|
protocol: friend.protocol,
|
|
10802
|
+
muted: friend.muted === true,
|
|
9171
10803
|
defaultTier: alterConfig?.defaultTier ?? "draft",
|
|
9172
10804
|
perHour: alterConfig?.autoReplyPerHour ?? 20,
|
|
9173
10805
|
t,
|
|
@@ -9330,6 +10962,8 @@ window.__ModuleLoader__.load({
|
|
|
9330
10962
|
*/
|
|
9331
10963
|
/** Roster info survives pane switches, so revisiting a group paints names instantly. */
|
|
9332
10964
|
const infoCache = /* @__PURE__ */ new Map();
|
|
10965
|
+
/** 很久没来群(未读 >= 此阈值)进群时,触发一次群记忆提炼(避免每条消息都总结)。 */
|
|
10966
|
+
const GROUP_MEMORY_MIN_UNREAD = 20;
|
|
9333
10967
|
const templateLabel = (t, id) => {
|
|
9334
10968
|
switch (id) {
|
|
9335
10969
|
case "standard": return t("template.standard");
|
|
@@ -9340,7 +10974,7 @@ window.__ModuleLoader__.load({
|
|
|
9340
10974
|
default: return id ?? "";
|
|
9341
10975
|
}
|
|
9342
10976
|
};
|
|
9343
|
-
const joinLabel = (t, join) => join === "apply" ? t("group.form.join.apply") : join === "open" ? t("group.form.join.open") : t("group.form.join.invite");
|
|
10977
|
+
const joinLabel = (t, join, paid) => paid === true || join === "paid" ? t("group.form.join.paid") : join === "apply" ? t("group.form.join.apply") : join === "open" ? t("group.form.join.open") : t("group.form.join.invite");
|
|
9344
10978
|
const wakeLabel = (t, wake) => wake === "always" ? t("group.form.wake.always") : wake === "never" ? t("group.form.wake.never") : t("group.form.wake.mention");
|
|
9345
10979
|
const tierLabel = (t, tier) => tier === "notify" ? t("tier.short.notify") : tier === "auto" ? t("tier.short.auto") : t("tier.short.draft");
|
|
9346
10980
|
const whoLabel = (t, who) => who === "owner" ? t("group.form.speakWho.owner") : who === "admins" ? t("group.form.speakWho.admins") : t("group.form.speakWho.all");
|
|
@@ -9358,6 +10992,12 @@ window.__ModuleLoader__.load({
|
|
|
9358
10992
|
const [inviteFp, setInviteFp] = (0, react.useState)("");
|
|
9359
10993
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
9360
10994
|
const [editOpen, setEditOpen] = (0, react.useState)(false);
|
|
10995
|
+
const [walletAddress, setWalletAddress] = (0, react.useState)(void 0);
|
|
10996
|
+
(0, react.useEffect)(() => {
|
|
10997
|
+
api.payWallet().then((r) => {
|
|
10998
|
+
setWalletAddress(r.wallet?.address);
|
|
10999
|
+
}).catch(() => {});
|
|
11000
|
+
}, []);
|
|
9361
11001
|
const [edit, setEdit] = (0, react.useState)({
|
|
9362
11002
|
speakHumans: true,
|
|
9363
11003
|
speakAgents: true,
|
|
@@ -9365,6 +11005,7 @@ window.__ModuleLoader__.load({
|
|
|
9365
11005
|
join: "invite",
|
|
9366
11006
|
agentWake: "mention",
|
|
9367
11007
|
agentTier: "draft",
|
|
11008
|
+
joinPrice: "",
|
|
9368
11009
|
rules: "",
|
|
9369
11010
|
isPublic: false,
|
|
9370
11011
|
tags: ""
|
|
@@ -9425,6 +11066,10 @@ window.__ModuleLoader__.load({
|
|
|
9425
11066
|
visible,
|
|
9426
11067
|
thread.entries.length
|
|
9427
11068
|
]);
|
|
11069
|
+
(0, react.useEffect)(() => {
|
|
11070
|
+
if (group.unread < GROUP_MEMORY_MIN_UNREAD) return;
|
|
11071
|
+
api.memorySummarize(gid).catch(() => {});
|
|
11072
|
+
}, [gid]);
|
|
9428
11073
|
const run = async (key, action) => {
|
|
9429
11074
|
setBusy(key);
|
|
9430
11075
|
setError(void 0);
|
|
@@ -9487,7 +11132,8 @@ window.__ModuleLoader__.load({
|
|
|
9487
11132
|
speakHumans: profile?.speakHumans ?? true,
|
|
9488
11133
|
speakAgents: profile?.speakAgents ?? true,
|
|
9489
11134
|
speakWho: profile?.speakWho ?? "all",
|
|
9490
|
-
join: profile?.join ?? "invite",
|
|
11135
|
+
join: profile?.join === "paid" ? "paid" : paidJoinFromRules(profile?.rules) !== void 0 ? "paid" : profile?.join ?? "invite",
|
|
11136
|
+
joinPrice: profile?.joinPrice ?? paidJoinFromRules(profile?.rules)?.price ?? "",
|
|
9491
11137
|
agentWake: profile?.agentWake ?? "mention",
|
|
9492
11138
|
agentTier: profile?.agentTier ?? "draft",
|
|
9493
11139
|
rules: profile?.rules ?? "",
|
|
@@ -9498,6 +11144,14 @@ window.__ModuleLoader__.load({
|
|
|
9498
11144
|
};
|
|
9499
11145
|
const saveProfile = () => {
|
|
9500
11146
|
const tags = edit.tags.split(",").map((s) => s.trim()).filter((s) => s !== "");
|
|
11147
|
+
if (edit.join === "paid" && edit.joinPrice.trim() === "") {
|
|
11148
|
+
setError(t("group.form.join.paid.priceRequired"));
|
|
11149
|
+
return;
|
|
11150
|
+
}
|
|
11151
|
+
if (edit.join === "paid" && edit.joinPrice.trim() !== "" && walletAddress === void 0) {
|
|
11152
|
+
setError(t("group.form.join.paid.noWallet"));
|
|
11153
|
+
return;
|
|
11154
|
+
}
|
|
9501
11155
|
run("profile.save", async () => {
|
|
9502
11156
|
await api.groupSetProfile(gid, {
|
|
9503
11157
|
...profile ?? {},
|
|
@@ -9508,6 +11162,10 @@ window.__ModuleLoader__.load({
|
|
|
9508
11162
|
agentWake: edit.agentWake,
|
|
9509
11163
|
agentTier: edit.agentTier,
|
|
9510
11164
|
rules: edit.rules,
|
|
11165
|
+
...edit.join === "paid" && edit.joinPrice.trim() !== "" && walletAddress !== void 0 ? {
|
|
11166
|
+
joinPrice: edit.joinPrice.trim(),
|
|
11167
|
+
joinAddr: walletAddress
|
|
11168
|
+
} : {},
|
|
9511
11169
|
public: edit.isPublic,
|
|
9512
11170
|
tags
|
|
9513
11171
|
});
|
|
@@ -9527,7 +11185,7 @@ window.__ModuleLoader__.load({
|
|
|
9527
11185
|
};
|
|
9528
11186
|
const chips = profile === void 0 ? [] : [
|
|
9529
11187
|
templateLabel(t, profile.template),
|
|
9530
|
-
joinLabel(t, profile.join),
|
|
11188
|
+
joinLabel(t, profile.join === "paid" ? "paid" : profile.join, profile.join === "paid" ? true : paidJoinFromRules(profile.rules) !== void 0),
|
|
9531
11189
|
whoLabel(t, profile.speakWho),
|
|
9532
11190
|
`${t("group.form.wake")} · ${wakeLabel(t, profile.agentWake)}`,
|
|
9533
11191
|
`${t("group.form.tier")} · ${tierLabel(t, profile.agentTier)}`,
|
|
@@ -9601,7 +11259,7 @@ window.__ModuleLoader__.load({
|
|
|
9601
11259
|
"data-soulmirror-group-profile-edit": true,
|
|
9602
11260
|
children: t("group.home.edit")
|
|
9603
11261
|
}) : null,
|
|
9604
|
-
|
|
11262
|
+
relay !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9605
11263
|
type: "button",
|
|
9606
11264
|
className: "sm-ghostbtn",
|
|
9607
11265
|
onClick: copyUri,
|
|
@@ -9678,31 +11336,71 @@ window.__ModuleLoader__.load({
|
|
|
9678
11336
|
}),
|
|
9679
11337
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
9680
11338
|
className: "sm-field",
|
|
9681
|
-
children: [
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
11339
|
+
children: [
|
|
11340
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.join") }),
|
|
11341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
11342
|
+
className: "sm-select",
|
|
11343
|
+
value: edit.join,
|
|
11344
|
+
onChange: (e) => {
|
|
11345
|
+
setEdit({
|
|
11346
|
+
...edit,
|
|
11347
|
+
join: e.target.value,
|
|
11348
|
+
...e.target.value === "paid" ? { isPublic: true } : {}
|
|
11349
|
+
});
|
|
11350
|
+
},
|
|
11351
|
+
children: [
|
|
11352
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
11353
|
+
value: "invite",
|
|
11354
|
+
children: t("group.form.join.invite")
|
|
11355
|
+
}),
|
|
11356
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
11357
|
+
value: "apply",
|
|
11358
|
+
children: t("group.form.join.apply")
|
|
11359
|
+
}),
|
|
11360
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
11361
|
+
value: "open",
|
|
11362
|
+
children: t("group.form.join.open")
|
|
11363
|
+
}),
|
|
11364
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
11365
|
+
value: "paid",
|
|
11366
|
+
disabled: walletAddress === void 0 && paidJoinFromRules(profile?.rules) === void 0,
|
|
11367
|
+
children: t("group.form.join.paid")
|
|
11368
|
+
})
|
|
11369
|
+
]
|
|
11370
|
+
}),
|
|
11371
|
+
edit.join === "paid" && !edit.isPublic ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11372
|
+
style: { fontSize: "0.82em" },
|
|
11373
|
+
children: t("group.form.join.paid.autoPublic")
|
|
11374
|
+
}) : null
|
|
11375
|
+
]
|
|
9705
11376
|
}),
|
|
11377
|
+
edit.join === "paid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
11378
|
+
className: "sm-field",
|
|
11379
|
+
children: [
|
|
11380
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.joinPrice") }),
|
|
11381
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
11382
|
+
className: "sm-input",
|
|
11383
|
+
type: "text",
|
|
11384
|
+
placeholder: "1.00",
|
|
11385
|
+
value: edit.joinPrice,
|
|
11386
|
+
onChange: (e) => {
|
|
11387
|
+
setEdit({
|
|
11388
|
+
...edit,
|
|
11389
|
+
joinPrice: e.target.value
|
|
11390
|
+
});
|
|
11391
|
+
},
|
|
11392
|
+
"data-soulmirror-group-edit-join-price": true
|
|
11393
|
+
}),
|
|
11394
|
+
edit.joinPrice.trim() === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11395
|
+
style: {
|
|
11396
|
+
fontSize: "0.82em",
|
|
11397
|
+
color: "rgb(220,80,60)"
|
|
11398
|
+
},
|
|
11399
|
+
"data-soulmirror-group-edit-paid-missing": true,
|
|
11400
|
+
children: t("group.form.join.paid.priceRequired")
|
|
11401
|
+
}) : null
|
|
11402
|
+
]
|
|
11403
|
+
}) : null,
|
|
9706
11404
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
9707
11405
|
className: "sm-field",
|
|
9708
11406
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.wake") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
@@ -9836,10 +11534,10 @@ window.__ModuleLoader__.load({
|
|
|
9836
11534
|
className: "sm-statepill",
|
|
9837
11535
|
children: c
|
|
9838
11536
|
}, `${c}-${i}`))
|
|
9839
|
-
}), profile?.rules !== void 0 && profile.rules !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
11537
|
+
}), profile?.rules !== void 0 && rulesWithoutPaidJoin(profile.rules) !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9840
11538
|
className: "sm-home-rules",
|
|
9841
11539
|
"data-soulmirror-group-rules": true,
|
|
9842
|
-
children: profile.rules
|
|
11540
|
+
children: rulesWithoutPaidJoin(profile.rules)
|
|
9843
11541
|
}) : null] })]
|
|
9844
11542
|
}),
|
|
9845
11543
|
pins.length > 0 || canAdmin ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -10564,7 +12262,7 @@ window.__ModuleLoader__.load({
|
|
|
10564
12262
|
className: "sm-home-card",
|
|
10565
12263
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10566
12264
|
className: "sm-home-title",
|
|
10567
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.home.profile") }),
|
|
12265
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.home.profile") }), relay !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
10568
12266
|
type: "button",
|
|
10569
12267
|
className: "sm-ghostbtn",
|
|
10570
12268
|
onClick: copyUri,
|
|
@@ -10895,7 +12593,17 @@ window.__ModuleLoader__.load({
|
|
|
10895
12593
|
...roomOwner,
|
|
10896
12594
|
t
|
|
10897
12595
|
})] })
|
|
10898
|
-
}) : paneTab === "announce" ? announce : paneTab === "
|
|
12596
|
+
}) : paneTab === "announce" ? announce : paneTab === "memory" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryPane, {
|
|
12597
|
+
t,
|
|
12598
|
+
allow: {
|
|
12599
|
+
global: true,
|
|
12600
|
+
group: gid
|
|
12601
|
+
},
|
|
12602
|
+
scope: {
|
|
12603
|
+
kind: "shared-group",
|
|
12604
|
+
gid
|
|
12605
|
+
}
|
|
12606
|
+
}) : paneTab === "members" ? membersPane : paneTab === "admin" ? admin : home
|
|
10899
12607
|
]
|
|
10900
12608
|
});
|
|
10901
12609
|
}
|
|
@@ -10940,7 +12648,7 @@ window.__ModuleLoader__.load({
|
|
|
10940
12648
|
node = parent;
|
|
10941
12649
|
}
|
|
10942
12650
|
}
|
|
10943
|
-
function SoulmirrorPage({
|
|
12651
|
+
function SoulmirrorPage({ scope, t, renderSlot }) {
|
|
10944
12652
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
10945
12653
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
10946
12654
|
const subscribeScope = (0, react.useCallback)((listener) => scope.subscribe(listener), [scope]);
|
|
@@ -11001,6 +12709,10 @@ window.__ModuleLoader__.load({
|
|
|
11001
12709
|
if (!target.isConnected) return;
|
|
11002
12710
|
if (rootEl.contains(target)) return;
|
|
11003
12711
|
if (target?.closest?.("[data-soulmirror-footer]") != null) return;
|
|
12712
|
+
if (target?.closest?.("[data-soulmirror-modal]") != null) return;
|
|
12713
|
+
if (target?.closest?.("[data-soulmirror-mention-pop]") != null) return;
|
|
12714
|
+
if (target?.closest?.("[data-soulmirror-float]") != null) return;
|
|
12715
|
+
if (target?.closest?.("[data-shell-overlay]") != null) return;
|
|
11004
12716
|
pageStore.close();
|
|
11005
12717
|
};
|
|
11006
12718
|
document.addEventListener("mousedown", onDown);
|
|
@@ -11036,9 +12748,12 @@ window.__ModuleLoader__.load({
|
|
|
11036
12748
|
const goFriend = (fp) => {
|
|
11037
12749
|
pageStore.select(fp);
|
|
11038
12750
|
};
|
|
11039
|
-
const
|
|
11040
|
-
|
|
11041
|
-
|
|
12751
|
+
const goGroup = (gid) => {
|
|
12752
|
+
pageStore.select(groupKey(gid));
|
|
12753
|
+
};
|
|
12754
|
+
const openContact = (fp) => {
|
|
12755
|
+
pageStore.select(fp);
|
|
12756
|
+
pageStore.setPaneTab("home");
|
|
11042
12757
|
};
|
|
11043
12758
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11044
12759
|
ref: root,
|
|
@@ -11054,6 +12769,7 @@ window.__ModuleLoader__.load({
|
|
|
11054
12769
|
onSelect: (key) => {
|
|
11055
12770
|
pageStore.select(key);
|
|
11056
12771
|
},
|
|
12772
|
+
onSelectContact: openContact,
|
|
11057
12773
|
onAccepted: (fp) => {
|
|
11058
12774
|
pageStore.select(fp);
|
|
11059
12775
|
},
|
|
@@ -11075,18 +12791,87 @@ window.__ModuleLoader__.load({
|
|
|
11075
12791
|
}) : seatAgent !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentPane, {
|
|
11076
12792
|
t,
|
|
11077
12793
|
agent: seatAgent,
|
|
11078
|
-
onOpenSession: openAlterSession,
|
|
11079
12794
|
onRemoved: goAlter
|
|
11080
12795
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlterPane, {
|
|
11081
12796
|
t,
|
|
11082
|
-
onOpenSession: openAlterSession,
|
|
11083
12797
|
onGoFriend: goFriend,
|
|
12798
|
+
onGoGroup: goGroup,
|
|
11084
12799
|
renderCards: renderSlot,
|
|
11085
12800
|
scope
|
|
11086
12801
|
})]
|
|
11087
12802
|
});
|
|
11088
12803
|
}
|
|
11089
12804
|
//#endregion
|
|
12805
|
+
//#region src/client/UpdateAction.tsx
|
|
12806
|
+
/**
|
|
12807
|
+
* Icon-only update button at the RIGHT end of the sidebar-foot SoulMirror row
|
|
12808
|
+
* (list seat `sidebar.footer.action`, ordered after the entry): invisible
|
|
12809
|
+
* until a newer release is known, then a small circled arrow. One click runs
|
|
12810
|
+
* the full install-restart-reload chain; while busy the tooltip narrates the
|
|
12811
|
+
* phase and the icon pulses. The reloaded page re-checks as current and the
|
|
12812
|
+
* button removes itself.
|
|
12813
|
+
*/
|
|
12814
|
+
/** Upward arrow (update available). */
|
|
12815
|
+
function ArrowUpIcon({ size = 13 }) {
|
|
12816
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
12817
|
+
width: size,
|
|
12818
|
+
height: size,
|
|
12819
|
+
viewBox: "0 0 16 16",
|
|
12820
|
+
fill: "none",
|
|
12821
|
+
"aria-hidden": true,
|
|
12822
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
12823
|
+
d: "M8 13.2V3.6M3.6 7.6 8 3.2l4.4 4.4",
|
|
12824
|
+
stroke: "currentColor",
|
|
12825
|
+
strokeWidth: "1.7",
|
|
12826
|
+
strokeLinecap: "round",
|
|
12827
|
+
strokeLinejoin: "round"
|
|
12828
|
+
})
|
|
12829
|
+
});
|
|
12830
|
+
}
|
|
12831
|
+
/** Spinning arc shown while the upgrade chain runs. */
|
|
12832
|
+
function SpinnerIcon({ size = 13 }) {
|
|
12833
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
12834
|
+
width: size,
|
|
12835
|
+
height: size,
|
|
12836
|
+
viewBox: "0 0 16 16",
|
|
12837
|
+
fill: "none",
|
|
12838
|
+
"aria-hidden": true,
|
|
12839
|
+
className: "sm-update-spin",
|
|
12840
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
12841
|
+
cx: "8",
|
|
12842
|
+
cy: "8",
|
|
12843
|
+
r: "6",
|
|
12844
|
+
stroke: "currentColor",
|
|
12845
|
+
strokeWidth: "1.7",
|
|
12846
|
+
strokeLinecap: "round",
|
|
12847
|
+
strokeDasharray: "28",
|
|
12848
|
+
strokeDashoffset: "20"
|
|
12849
|
+
})
|
|
12850
|
+
});
|
|
12851
|
+
}
|
|
12852
|
+
function UpdateAction({ t }) {
|
|
12853
|
+
const upgrade = (0, react.useSyncExternalStore)(upgradeStore.subscribe, upgradeStore.getSnapshot);
|
|
12854
|
+
const busy = upgrade.phase === "installing" || upgrade.phase === "restarting" || upgrade.phase === "reloading";
|
|
12855
|
+
if (!upgrade.hasUpdate && !busy) return null;
|
|
12856
|
+
const label = busy ? upgrade.phase === "installing" ? t("page.update.installing", { v: upgrade.latest ?? "" }) : upgrade.phase === "restarting" ? t("page.update.restarting") : t("page.update.reloading") : t("sidebar.update", { v: upgrade.latest ?? "" });
|
|
12857
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
12858
|
+
label,
|
|
12859
|
+
delayMs: 200,
|
|
12860
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
12861
|
+
type: "button",
|
|
12862
|
+
className: `sm-update-fab${busy ? " sm-busy" : ""}`,
|
|
12863
|
+
disabled: busy,
|
|
12864
|
+
"aria-label": label,
|
|
12865
|
+
"data-soulmirror-update-action": upgrade.latest,
|
|
12866
|
+
onClick: () => {
|
|
12867
|
+
if (busy || upgrade.latest === void 0) return;
|
|
12868
|
+
upgradeStore.run();
|
|
12869
|
+
},
|
|
12870
|
+
children: busy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SpinnerIcon, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArrowUpIcon, {})
|
|
12871
|
+
})
|
|
12872
|
+
});
|
|
12873
|
+
}
|
|
12874
|
+
//#endregion
|
|
11090
12875
|
//#region src/client/styles.ts
|
|
11091
12876
|
/**
|
|
11092
12877
|
* The rules the SoulMirror surfaces need that inline styles cannot express
|
|
@@ -11101,13 +12886,40 @@ window.__ModuleLoader__.load({
|
|
|
11101
12886
|
*/
|
|
11102
12887
|
const STYLE_ID = "soulmirror-styles";
|
|
11103
12888
|
const CSS = `
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
12889
|
+
/* New-mail toast: our own pill (the host Toast surface stays light on the
|
|
12890
|
+
dark theme). Fixed top-center, themed, auto-dismissing. */
|
|
12891
|
+
.sm-mail-toast {
|
|
12892
|
+
position: fixed; top: 14px; left: 50%; transform: translateX(-50%); z-index: 90;
|
|
12893
|
+
display: flex; align-items: center; gap: 8px; max-width: min(420px, 80vw);
|
|
12894
|
+
padding: 8px 14px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 999px;
|
|
12895
|
+
background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2)); color: var(--dsw-alias-label-primary);
|
|
12896
|
+
box-shadow: var(--dsw-shadow-lv3, 0 8px 24px rgba(0,0,0,.35)); cursor: pointer;
|
|
12897
|
+
font: inherit; font-size: 12px; animation: sm-page-in 140ms ease-out;
|
|
12898
|
+
}
|
|
12899
|
+
.sm-mail-toast:hover { border-color: var(--dsw-alias-brand-primary); }
|
|
12900
|
+
|
|
12901
|
+
/* Icon-only update button at the right end of the SoulMirror foot row:
|
|
12902
|
+
invisible until a release is known, small circled arrow, tooltip carries
|
|
12903
|
+
the words. Sits beside the entry (the row is a flex line). */
|
|
12904
|
+
.sm-update-fab {
|
|
12905
|
+
flex: none; align-self: center; width: 24px; height: 24px; margin: 4px 2px 0 0;
|
|
12906
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
12907
|
+
border: 1px solid var(--dsw-alias-brand-primary); border-radius: 50%;
|
|
12908
|
+
background: transparent; color: var(--dsw-alias-brand-primary); cursor: pointer; padding: 0;
|
|
11108
12909
|
}
|
|
11109
|
-
.sm-update-
|
|
11110
|
-
.sm-update-
|
|
12910
|
+
.sm-update-fab:hover { background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-label-primary-inverted); }
|
|
12911
|
+
.sm-update-fab:disabled, .sm-update-fab.sm-busy { opacity: .8; cursor: default; }
|
|
12912
|
+
.sm-update-spin { animation: sm-update-spin 900ms linear infinite; }
|
|
12913
|
+
@keyframes sm-update-spin { to { transform: rotate(360deg); } }
|
|
12914
|
+
display: inline-flex; align-items: center; gap: 5px; max-width: 100%; min-width: 0;
|
|
12915
|
+
padding: 2px 9px; border: 1px solid var(--dsw-alias-brand-primary); border-radius: 999px;
|
|
12916
|
+
background: transparent; color: var(--dsw-alias-brand-primary);
|
|
12917
|
+
font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
12918
|
+
}
|
|
12919
|
+
.sm-update-chip:hover { background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-label-primary-inverted); }
|
|
12920
|
+
.sm-update-chip:disabled { opacity: .75; cursor: default; }
|
|
12921
|
+
.sm-update-chip.sm-rail { padding: 2px 6px; }
|
|
12922
|
+
|
|
11111
12923
|
|
|
11112
12924
|
/* Native form controls follow the ACTIVE theme: the option list of a <select>
|
|
11113
12925
|
(and scrollbars, checkboxes...) is OS-rendered and ignores CSS tokens - it
|
|
@@ -11116,8 +12928,8 @@ body[data-ds-dark-theme] { color-scheme: dark; }
|
|
|
11116
12928
|
.sm-page-root select option, .sm-page-root select optgroup { background: var(--dsw-specific-menu); color: var(--dsw-alias-label-primary); }
|
|
11117
12929
|
|
|
11118
12930
|
.sm-footer {
|
|
11119
|
-
flex:
|
|
11120
|
-
width:
|
|
12931
|
+
flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px;
|
|
12932
|
+
width: auto; height: 42px; margin: 4px -2px 0; padding: 0 10px 0 8px;
|
|
11121
12933
|
box-sizing: border-box; border: none; border-radius: 12px; background: transparent;
|
|
11122
12934
|
cursor: pointer; overflow: hidden; color: var(--dsw-alias-label-primary);
|
|
11123
12935
|
font-family: inherit; font-size: 14px; line-height: 22px; position: relative;
|
|
@@ -11256,7 +13068,7 @@ body[data-ds-dark-theme] { color-scheme: dark; }
|
|
|
11256
13068
|
.sm-pendbar b { color: var(--dsw-alias-state-warn-primary); }
|
|
11257
13069
|
.sm-pendbar .sm-linkbtn { margin-left: auto; }
|
|
11258
13070
|
.sm-thread { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 20px; display: flex; flex-direction: column; }
|
|
11259
|
-
.sm-thread-inner {
|
|
13071
|
+
.sm-thread-inner { display: flex; flex-direction: column; gap: 4px; }
|
|
11260
13072
|
.sm-day { align-self: center; margin: 10px 0 6px; padding: 1px 10px; border-radius: 10px; font-size: 11px;
|
|
11261
13073
|
color: var(--dsw-alias-label-tertiary); background: var(--dsw-alias-interactive-bg-hover); }
|
|
11262
13074
|
.sm-msg { display: flex; flex-direction: column; max-width: 72%; }
|
|
@@ -11500,7 +13312,8 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11500
13312
|
"sessions",
|
|
11501
13313
|
"settingsScope",
|
|
11502
13314
|
"commandUi",
|
|
11503
|
-
"theme"
|
|
13315
|
+
"theme",
|
|
13316
|
+
"workspaces"
|
|
11504
13317
|
];
|
|
11505
13318
|
/** Whether a session cwd is the SoulMirror workspace (`<home>/a2a`, e.g. `~/.soulnet/a2a`). */
|
|
11506
13319
|
function isSoulmirrorCwd(cwd) {
|
|
@@ -11514,14 +13327,12 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11514
13327
|
en
|
|
11515
13328
|
}), "soulmirror: dictionaries");
|
|
11516
13329
|
const t = ctx.locale.bind(NS);
|
|
13330
|
+
setDirectoryPicker(() => ctx.workspaces.pickDirectory());
|
|
11517
13331
|
ctx.effect(() => {
|
|
11518
13332
|
ensureStyles();
|
|
11519
13333
|
return removeStyles;
|
|
11520
13334
|
}, "soulmirror: inbox styles");
|
|
11521
13335
|
installBranding(ctx);
|
|
11522
|
-
const openSession = (id) => {
|
|
11523
|
-
ctx.sessions.open(id);
|
|
11524
|
-
};
|
|
11525
13336
|
ctx.conversationEvents.register(a2aRelayDefinition);
|
|
11526
13337
|
ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({
|
|
11527
13338
|
name: "conversation.chat.node",
|
|
@@ -11534,6 +13345,12 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11534
13345
|
order: 0,
|
|
11535
13346
|
locale: NS
|
|
11536
13347
|
}, SidebarEntry));
|
|
13348
|
+
ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
|
|
13349
|
+
name: "sidebar.footer.action",
|
|
13350
|
+
id: "soulmirror-update",
|
|
13351
|
+
order: 1,
|
|
13352
|
+
locale: NS
|
|
13353
|
+
}, UpdateAction));
|
|
11537
13354
|
ctx.slots.inject("sidebar.nav.primary", () => {
|
|
11538
13355
|
navSeatStore.set(true);
|
|
11539
13356
|
const dispose = ctx.slots.register({
|
|
@@ -11548,10 +13365,7 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11548
13365
|
};
|
|
11549
13366
|
});
|
|
11550
13367
|
const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
|
|
11551
|
-
const pageInjected = () => ({
|
|
11552
|
-
openSession,
|
|
11553
|
-
scope
|
|
11554
|
-
});
|
|
13368
|
+
const pageInjected = () => ({ scope });
|
|
11555
13369
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
11556
13370
|
name: "shell.overlay",
|
|
11557
13371
|
id: "soulmirror-page",
|
|
@@ -11599,18 +13413,30 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11599
13413
|
clearInterval(timer);
|
|
11600
13414
|
};
|
|
11601
13415
|
});
|
|
11602
|
-
const settingsInjected = () => ({
|
|
11603
|
-
|
|
11604
|
-
|
|
13416
|
+
const settingsInjected = () => ({ scope });
|
|
13417
|
+
ctx.slots.inject("settings.section", () => {
|
|
13418
|
+
const make = () => ctx.slots.register({
|
|
13419
|
+
name: "settings.section",
|
|
13420
|
+
id: "soulmirror",
|
|
13421
|
+
order: 80,
|
|
13422
|
+
locale: NS,
|
|
13423
|
+
label: () => upgradeStore.getSnapshot().hasUpdate ? `${t("settings.nav")} ●` : t("settings.nav"),
|
|
13424
|
+
inject: settingsInjected
|
|
13425
|
+
}, SoulmirrorSettingsSection);
|
|
13426
|
+
let hadUpdate = upgradeStore.getSnapshot().hasUpdate;
|
|
13427
|
+
let disposeSection = make();
|
|
13428
|
+
const unsubscribe = upgradeStore.subscribe(() => {
|
|
13429
|
+
const now = upgradeStore.getSnapshot().hasUpdate;
|
|
13430
|
+
if (now === hadUpdate) return;
|
|
13431
|
+
hadUpdate = now;
|
|
13432
|
+
disposeSection();
|
|
13433
|
+
disposeSection = make();
|
|
13434
|
+
});
|
|
13435
|
+
return () => {
|
|
13436
|
+
unsubscribe();
|
|
13437
|
+
disposeSection();
|
|
13438
|
+
};
|
|
11605
13439
|
});
|
|
11606
|
-
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
11607
|
-
name: "settings.section",
|
|
11608
|
-
id: "soulmirror",
|
|
11609
|
-
order: 80,
|
|
11610
|
-
locale: NS,
|
|
11611
|
-
label: () => upgradeStore.getSnapshot().hasUpdate ? `${t("settings.nav")} ●` : t("settings.nav"),
|
|
11612
|
-
inject: settingsInjected
|
|
11613
|
-
}, SoulmirrorSettingsSection));
|
|
11614
13440
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
11615
13441
|
name: "settings.onboarding",
|
|
11616
13442
|
id: "soulmirror-identity",
|