soulnet-dsh 0.1.9 → 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 +2341 -612
- 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/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 +89 -4
- 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
|
|
@@ -2333,6 +2766,40 @@ 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",
|
|
@@ -2464,13 +2931,12 @@ window.__ModuleLoader__.load({
|
|
|
2464
2931
|
"page.composer.instructing": "Sending…",
|
|
2465
2932
|
"page.composer.direct": "Debug: direct to {name} · end-to-end encrypted · your alter does not see it",
|
|
2466
2933
|
"alter.me": "My alter",
|
|
2934
|
+
"alter.wallet": "Wallet",
|
|
2467
2935
|
"alter.row.hint": "Talk to your alter directly",
|
|
2468
2936
|
"alter.row.drafts": "{n} draft(s) waiting for you",
|
|
2469
2937
|
"alter.status.running": "Your alter is working…",
|
|
2470
2938
|
"alter.status.idle": "Ready · one memory shared across every friend",
|
|
2471
2939
|
"alter.status.noSession": "Starting the alter session…",
|
|
2472
|
-
"alter.openDsh": "Open in dsh",
|
|
2473
|
-
"alter.openDsh.hint": "The same conversation as a native dsh session (trajectory, tools, approvals).",
|
|
2474
2940
|
"alter.pendbar": "{n} draft(s) of your alter wait for your decision",
|
|
2475
2941
|
"alter.pendbar.go": "Review in {name}'s thread →",
|
|
2476
2942
|
"alter.empty.title": "Tell your alter what to do",
|
|
@@ -2481,6 +2947,8 @@ window.__ModuleLoader__.load({
|
|
|
2481
2947
|
"alter.thinking": "Your alter is working…",
|
|
2482
2948
|
"alter.item.inbound": "Mail from {name}",
|
|
2483
2949
|
"alter.item.view": "open thread",
|
|
2950
|
+
"alter.item.groupInbound": "Group message · {name}",
|
|
2951
|
+
"alter.item.viewGroup": "view in {name}",
|
|
2484
2952
|
"alter.item.send": "To {name}",
|
|
2485
2953
|
"alter.item.send.pending": "sending…",
|
|
2486
2954
|
"alter.item.send.sent": "sent",
|
|
@@ -2498,6 +2966,7 @@ window.__ModuleLoader__.load({
|
|
|
2498
2966
|
"draft.title": "Your alter wants to send this",
|
|
2499
2967
|
"draft.title.to": "Your alter wants to send this to {name}",
|
|
2500
2968
|
"draft.openThread": "open thread",
|
|
2969
|
+
"draft.openGroup": "view in group",
|
|
2501
2970
|
"draft.reason.draft-tier": "Held because this friend's reply tier is \"draft\" (you review before anything goes out).",
|
|
2502
2971
|
"draft.reason.notify-tier": "Held because this friend's reply tier is \"notify\".",
|
|
2503
2972
|
"draft.reason.rate-limited": "Held because the hourly auto-reply cap for this friend is reached.",
|
|
@@ -2536,6 +3005,7 @@ window.__ModuleLoader__.load({
|
|
|
2536
3005
|
"tier.short.auto": "auto",
|
|
2537
3006
|
"friend.settings.title": "How your alter handles {name}",
|
|
2538
3007
|
"friend.tier": "Reply tier",
|
|
3008
|
+
"friend.mute": "Mute (do not disturb)",
|
|
2539
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).",
|
|
2540
3010
|
"friend.protocol": "Protocol override for this friend",
|
|
2541
3011
|
"friend.protocol.placeholder": "Rules for this friend only (they win over the global protocol on conflict). Empty = none.",
|
|
@@ -2558,8 +3028,24 @@ window.__ModuleLoader__.load({
|
|
|
2558
3028
|
"settings.alter.alterMode.full": "Full dsh (shell + files, like a normal session)",
|
|
2559
3029
|
"settings.alter.alterMode.hint": "Applies to the next alter session — restart dsh (or reopen the alter session) to switch.",
|
|
2560
3030
|
"settings.alter.openPage": "Open SoulMirror",
|
|
2561
|
-
"settings.alter.openSession": "Open the alter session in dsh",
|
|
2562
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.",
|
|
2563
3049
|
"group.section": "Groups",
|
|
2564
3050
|
"group.create": "New group",
|
|
2565
3051
|
"group.create.name": "Group name",
|
|
@@ -2576,6 +3062,8 @@ window.__ModuleLoader__.load({
|
|
|
2576
3062
|
"group.leave.owner": "You are the owner — a group lives and dies with its owner for now.",
|
|
2577
3063
|
"group.left": "Left the group.",
|
|
2578
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",
|
|
2579
3067
|
"group.sender.me": "me",
|
|
2580
3068
|
"group.composer.placeholder": "Message {name}…",
|
|
2581
3069
|
"group.composer.hint": "Sent as yourself, end-to-end encrypted (sender key).",
|
|
@@ -2602,6 +3090,14 @@ window.__ModuleLoader__.load({
|
|
|
2602
3090
|
"group.form.join.invite": "invite only",
|
|
2603
3091
|
"group.form.join.apply": "strangers may apply",
|
|
2604
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).",
|
|
2605
3101
|
"group.form.wake": "Alter wake-up",
|
|
2606
3102
|
"group.form.wake.mention": "on mention",
|
|
2607
3103
|
"group.form.wake.always": "always",
|
|
@@ -2649,6 +3145,7 @@ window.__ModuleLoader__.load({
|
|
|
2649
3145
|
"group.speak.whoOwner": "Only the owner posts in this group.",
|
|
2650
3146
|
"group.speak.whoAdmins": "Only the owner and admins post in this group.",
|
|
2651
3147
|
"group.alter.toggle": "My alter participates",
|
|
3148
|
+
"group.mute": "Mute (do not disturb)",
|
|
2652
3149
|
"group.mode.mention": "replies when @mentioned",
|
|
2653
3150
|
"group.mode.always": "active — may reply to anything",
|
|
2654
3151
|
"group.by.alter": "alter",
|
|
@@ -2665,6 +3162,7 @@ window.__ModuleLoader__.load({
|
|
|
2665
3162
|
"settings.agents.none": "No agents yet — add one below.",
|
|
2666
3163
|
"settings.agents.name": "Name (used as @mention)",
|
|
2667
3164
|
"settings.agents.cwd": "Working directory - the folder it reads, writes and runs commands in (optional)",
|
|
3165
|
+
"settings.agents.cwd.browse": "Browse",
|
|
2668
3166
|
"settings.agents.cwdHint": "Leave empty for its own default folder",
|
|
2669
3167
|
"settings.agents.preset": "Capability preset",
|
|
2670
3168
|
"settings.agents.preset.default": "standard coding agent (default)",
|
|
@@ -2681,7 +3179,6 @@ window.__ModuleLoader__.load({
|
|
|
2681
3179
|
"settings.agents.remove": "Remove",
|
|
2682
3180
|
"settings.agents.saved": "Agent \"{name}\" saved.",
|
|
2683
3181
|
"settings.agents.removed": "Removed \"{name}\".",
|
|
2684
|
-
"settings.agents.open": "Open session",
|
|
2685
3182
|
"settings.agents.status.running": "working…",
|
|
2686
3183
|
"settings.agents.status.idle": "idle",
|
|
2687
3184
|
"agents.section": "My agents",
|
|
@@ -2702,15 +3199,34 @@ window.__ModuleLoader__.load({
|
|
|
2702
3199
|
"agent.thinking.done": "Thought",
|
|
2703
3200
|
"group.join.section": "Join a group",
|
|
2704
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.",
|
|
2705
3216
|
"group.join.apply": "Apply",
|
|
2706
3217
|
"group.join.applied": "Application sent.",
|
|
2707
3218
|
"group.apps.badge": "{n} application(s) waiting",
|
|
3219
|
+
"col2.messages": "Messages",
|
|
2708
3220
|
"col2.contacts": "Contacts",
|
|
2709
3221
|
"col2.agents": "Agents",
|
|
2710
3222
|
"col2.groups": "Groups",
|
|
2711
3223
|
"col2.contacts.section": "You",
|
|
2712
3224
|
"col2.agents.empty": "No agents yet — create one to give it a job on your behalf.",
|
|
2713
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",
|
|
2714
3230
|
"groups.section": "Groups",
|
|
2715
3231
|
"pane.chat": "Chat",
|
|
2716
3232
|
"pane.announce": "Bulletin",
|
|
@@ -2719,6 +3235,7 @@ window.__ModuleLoader__.load({
|
|
|
2719
3235
|
"pane.admin": "Manage",
|
|
2720
3236
|
"pane.info": "Info",
|
|
2721
3237
|
"pane.settings": "Settings",
|
|
3238
|
+
"pane.memory": "Memory",
|
|
2722
3239
|
"friend.home.profile": "Profile",
|
|
2723
3240
|
"friend.home.fp": "Fingerprint",
|
|
2724
3241
|
"friend.home.name": "Name",
|
|
@@ -2727,6 +3244,7 @@ window.__ModuleLoader__.load({
|
|
|
2727
3244
|
"friend.home.lastActive": "Last active",
|
|
2728
3245
|
"friend.home.drafts": "Drafts waiting",
|
|
2729
3246
|
"friend.home.actions": "Actions",
|
|
3247
|
+
"friend.home.sendMessage": "Send a message",
|
|
2730
3248
|
"alter.home.profile": "Profile",
|
|
2731
3249
|
"alter.home.session": "Session",
|
|
2732
3250
|
"alter.home.friends": "Friends",
|
|
@@ -2766,6 +3284,40 @@ window.__ModuleLoader__.load({
|
|
|
2766
3284
|
"inbox.add": "添加",
|
|
2767
3285
|
"inbox.add.placeholder": "加好友:贴名片链接(soulmirror://card?…)",
|
|
2768
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": "该范围暂无记忆。",
|
|
2769
3321
|
"bubble.in": "来自 {name}",
|
|
2770
3322
|
"bubble.out": "发给 {name}",
|
|
2771
3323
|
"bubble.mine": "我的分身",
|
|
@@ -2897,13 +3449,12 @@ window.__ModuleLoader__.load({
|
|
|
2897
3449
|
"page.composer.instructing": "发送中…",
|
|
2898
3450
|
"page.composer.direct": "调试:直发给 {name} · 端到端加密 · 分身看不到",
|
|
2899
3451
|
"alter.me": "我的分身",
|
|
3452
|
+
"alter.wallet": "钱包",
|
|
2900
3453
|
"alter.row.hint": "跟你的分身直接对话",
|
|
2901
3454
|
"alter.row.drafts": "{n} 项等你拍板",
|
|
2902
3455
|
"alter.status.running": "分身正在处理…",
|
|
2903
3456
|
"alter.status.idle": "就绪 · 对所有好友共享同一记忆",
|
|
2904
3457
|
"alter.status.noSession": "分身会话启动中…",
|
|
2905
|
-
"alter.openDsh": "在 dsh 里打开",
|
|
2906
|
-
"alter.openDsh.hint": "同一段对话的 dsh 原生会话(轨迹、工具、审批)。",
|
|
2907
3458
|
"alter.pendbar": "还有 {n} 项分身拟稿等你拍板",
|
|
2908
3459
|
"alter.pendbar.go": "去「{name}」里看 →",
|
|
2909
3460
|
"alter.empty.title": "吩咐你的分身",
|
|
@@ -2914,6 +3465,8 @@ window.__ModuleLoader__.load({
|
|
|
2914
3465
|
"alter.thinking": "分身正在处理…",
|
|
2915
3466
|
"alter.item.inbound": "{name} 来信",
|
|
2916
3467
|
"alter.item.view": "看往来",
|
|
3468
|
+
"alter.item.groupInbound": "群消息 · {name}",
|
|
3469
|
+
"alter.item.viewGroup": "在 {name} 群 中查看",
|
|
2917
3470
|
"alter.item.send": "发给 {name}",
|
|
2918
3471
|
"alter.item.send.pending": "发送中…",
|
|
2919
3472
|
"alter.item.send.sent": "已发出",
|
|
@@ -2931,6 +3484,7 @@ window.__ModuleLoader__.load({
|
|
|
2931
3484
|
"draft.title": "我的分身想这样回复",
|
|
2932
3485
|
"draft.title.to": "我的分身想这样发给 {name}",
|
|
2933
3486
|
"draft.openThread": "看往来",
|
|
3487
|
+
"draft.openGroup": "在群中查看",
|
|
2934
3488
|
"draft.reason.draft-tier": "依据:这位好友的应答档位是「拟稿」(发出前先问你)。",
|
|
2935
3489
|
"draft.reason.notify-tier": "依据:这位好友的应答档位是「只通知」。",
|
|
2936
3490
|
"draft.reason.rate-limited": "依据:对这位好友的自动回复已达每小时上限。",
|
|
@@ -2969,6 +3523,7 @@ window.__ModuleLoader__.load({
|
|
|
2969
3523
|
"tier.short.auto": "自动",
|
|
2970
3524
|
"friend.settings.title": "分身如何对待 {name}",
|
|
2971
3525
|
"friend.tier": "应答档位",
|
|
3526
|
+
"friend.mute": "免打扰",
|
|
2972
3527
|
"friend.tier.hint": "只通知:来信只展示;拟稿:分身拟好回复、在本页等你拍板;自动:分身自己发(每小时最多 {n} 条)。",
|
|
2973
3528
|
"friend.protocol": "对这位好友的准则补充",
|
|
2974
3529
|
"friend.protocol.placeholder": "只对这位好友生效的规则(冲突时压过全局准则)。留空 = 没有。",
|
|
@@ -2991,8 +3546,24 @@ window.__ModuleLoader__.load({
|
|
|
2991
3546
|
"settings.alter.alterMode.full": "完整 dsh(shell + 文件,像普通会话)",
|
|
2992
3547
|
"settings.alter.alterMode.hint": "对下一个分身会话生效——切换后重启 dsh(或重新打开分身会话)。",
|
|
2993
3548
|
"settings.alter.openPage": "打开灵镜",
|
|
2994
|
-
"settings.alter.openSession": "在 dsh 里打开分身会话",
|
|
2995
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。",
|
|
2996
3567
|
"group.section": "群",
|
|
2997
3568
|
"group.create": "新建群",
|
|
2998
3569
|
"group.create.name": "群名称",
|
|
@@ -3009,6 +3580,8 @@ window.__ModuleLoader__.load({
|
|
|
3009
3580
|
"group.leave.owner": "你是群主——目前群与群主共存亡,不能退出。",
|
|
3010
3581
|
"group.left": "已退群。",
|
|
3011
3582
|
"group.empty": "还没有消息——在下面说点什么。",
|
|
3583
|
+
"group.draftReminder": "分身拟了一份回复,等待你拍板。",
|
|
3584
|
+
"group.draftReminder.go": "去查看",
|
|
3012
3585
|
"group.sender.me": "我",
|
|
3013
3586
|
"group.composer.placeholder": "发到 {name}…",
|
|
3014
3587
|
"group.composer.hint": "以你本人身份发送,端到端加密(发送者密钥)。",
|
|
@@ -3035,6 +3608,14 @@ window.__ModuleLoader__.load({
|
|
|
3035
3608
|
"group.form.join.invite": "仅邀请",
|
|
3036
3609
|
"group.form.join.apply": "陌生人可申请",
|
|
3037
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": "付费进群会自动设为公开群(陌生人需要群链接才能找到并付款)。",
|
|
3038
3619
|
"group.form.wake": "分身唤醒",
|
|
3039
3620
|
"group.form.wake.mention": "被点名时",
|
|
3040
3621
|
"group.form.wake.always": "总是",
|
|
@@ -3082,6 +3663,7 @@ window.__ModuleLoader__.load({
|
|
|
3082
3663
|
"group.speak.whoOwner": "这个群里只有群主发言。",
|
|
3083
3664
|
"group.speak.whoAdmins": "这个群里只有群主和管理员发言。",
|
|
3084
3665
|
"group.alter.toggle": "我的分身参与",
|
|
3666
|
+
"group.mute": "免打扰",
|
|
3085
3667
|
"group.mode.mention": "被@才回应",
|
|
3086
3668
|
"group.mode.always": "积极参与",
|
|
3087
3669
|
"group.by.alter": "分身",
|
|
@@ -3098,6 +3680,7 @@ window.__ModuleLoader__.load({
|
|
|
3098
3680
|
"settings.agents.none": "还没有代理——在下面添加一个。",
|
|
3099
3681
|
"settings.agents.name": "名字(群里 @ 它用)",
|
|
3100
3682
|
"settings.agents.cwd": "工作目录——它读写文件、跑命令的文件夹(选填)",
|
|
3683
|
+
"settings.agents.cwd.browse": "浏览",
|
|
3101
3684
|
"settings.agents.cwdHint": "留空 = 使用它自己的默认目录",
|
|
3102
3685
|
"settings.agents.preset": "能力预设",
|
|
3103
3686
|
"settings.agents.preset.default": "标准编码 Agent(默认)",
|
|
@@ -3114,7 +3697,6 @@ window.__ModuleLoader__.load({
|
|
|
3114
3697
|
"settings.agents.remove": "移除",
|
|
3115
3698
|
"settings.agents.saved": "代理「{name}」已保存。",
|
|
3116
3699
|
"settings.agents.removed": "已移除「{name}」。",
|
|
3117
|
-
"settings.agents.open": "打开会话",
|
|
3118
3700
|
"settings.agents.status.running": "干活中…",
|
|
3119
3701
|
"settings.agents.status.idle": "空闲",
|
|
3120
3702
|
"agents.section": "我的 Agent",
|
|
@@ -3135,15 +3717,34 @@ window.__ModuleLoader__.load({
|
|
|
3135
3717
|
"agent.thinking.done": "已思考",
|
|
3136
3718
|
"group.join.section": "加入群",
|
|
3137
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": "已附付款证明并提交申请,等待群主验证。",
|
|
3138
3734
|
"group.join.apply": "申请",
|
|
3139
3735
|
"group.join.applied": "申请已发出。",
|
|
3140
3736
|
"group.apps.badge": "{n} 条进群申请待处理",
|
|
3737
|
+
"col2.messages": "消息",
|
|
3141
3738
|
"col2.contacts": "通讯录",
|
|
3142
3739
|
"col2.agents": "智能体",
|
|
3143
3740
|
"col2.groups": "群聊",
|
|
3144
3741
|
"col2.contacts.section": "我",
|
|
3145
3742
|
"col2.agents.empty": "还没有智能体——创建一个,让它替你做点事。",
|
|
3146
3743
|
"col2.groups.empty": "还没有群——建一个,或用群链接加入。",
|
|
3744
|
+
"agents.expand": "展开 {n} 个",
|
|
3745
|
+
"agents.collapse": "收起",
|
|
3746
|
+
"messages.friends": "好友",
|
|
3747
|
+
"messages.section": "会话",
|
|
3147
3748
|
"groups.section": "群聊",
|
|
3148
3749
|
"pane.chat": "聊天",
|
|
3149
3750
|
"pane.announce": "公告",
|
|
@@ -3152,6 +3753,7 @@ window.__ModuleLoader__.load({
|
|
|
3152
3753
|
"pane.admin": "管理",
|
|
3153
3754
|
"pane.info": "信息",
|
|
3154
3755
|
"pane.settings": "设置",
|
|
3756
|
+
"pane.memory": "记忆",
|
|
3155
3757
|
"friend.home.profile": "名片",
|
|
3156
3758
|
"friend.home.fp": "指纹",
|
|
3157
3759
|
"friend.home.name": "名字",
|
|
@@ -3160,6 +3762,7 @@ window.__ModuleLoader__.load({
|
|
|
3160
3762
|
"friend.home.lastActive": "最近活跃",
|
|
3161
3763
|
"friend.home.drafts": "待审稿",
|
|
3162
3764
|
"friend.home.actions": "操作",
|
|
3765
|
+
"friend.home.sendMessage": "去发消息",
|
|
3163
3766
|
"alter.home.profile": "档案",
|
|
3164
3767
|
"alter.home.session": "会话",
|
|
3165
3768
|
"alter.home.friends": "好友",
|
|
@@ -3641,6 +4244,7 @@ window.__ModuleLoader__.load({
|
|
|
3641
4244
|
const [voices, setVoices] = (0, react.useState)(void 0);
|
|
3642
4245
|
const [voiceCommanders, setVoiceCommanders] = (0, react.useState)({});
|
|
3643
4246
|
const [duty, setDuty] = (0, react.useState)("");
|
|
4247
|
+
const [muted, setMuted] = (0, react.useState)(group.muted === true);
|
|
3644
4248
|
const [agentNames, setAgentNames] = (0, react.useState)([]);
|
|
3645
4249
|
const [agentsSheetOpen, setAgentsSheetOpen] = (0, react.useState)(false);
|
|
3646
4250
|
const [mention, setMention] = (0, react.useState)(void 0);
|
|
@@ -3654,6 +4258,7 @@ window.__ModuleLoader__.load({
|
|
|
3654
4258
|
const following = (0, react.useRef)(true);
|
|
3655
4259
|
const prevFirstSeq = (0, react.useRef)(void 0);
|
|
3656
4260
|
const prevHeight = (0, react.useRef)(0);
|
|
4261
|
+
const groupDrafts = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot).inbox.drafts.filter((d) => d.gid === gid);
|
|
3657
4262
|
(0, react.useEffect)(() => {
|
|
3658
4263
|
setText("");
|
|
3659
4264
|
setVoices(void 0);
|
|
@@ -3729,6 +4334,7 @@ window.__ModuleLoader__.load({
|
|
|
3729
4334
|
setVoices(map);
|
|
3730
4335
|
setVoiceCommanders(cmds);
|
|
3731
4336
|
setDuty(settings.duty ?? "");
|
|
4337
|
+
if (settings.muted !== void 0) setMuted(settings.muted === true);
|
|
3732
4338
|
};
|
|
3733
4339
|
(0, react.useEffect)(() => {
|
|
3734
4340
|
if (!showAlterChip) return;
|
|
@@ -3771,6 +4377,16 @@ window.__ModuleLoader__.load({
|
|
|
3771
4377
|
setDuty(prev);
|
|
3772
4378
|
});
|
|
3773
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
|
+
};
|
|
3774
4390
|
/** Load one of MY agents' work-session trace for this group (local; persists in the timeline). */
|
|
3775
4391
|
const loadFeed = (name) => {
|
|
3776
4392
|
api.agentHistory(name, 80, gid).then((h) => {
|
|
@@ -4128,6 +4744,18 @@ window.__ModuleLoader__.load({
|
|
|
4128
4744
|
]
|
|
4129
4745
|
})
|
|
4130
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,
|
|
4131
4759
|
mutedHint !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4132
4760
|
className: "sm-mutebar",
|
|
4133
4761
|
"data-soulmirror-group-composer": true,
|
|
@@ -4136,120 +4764,147 @@ window.__ModuleLoader__.load({
|
|
|
4136
4764
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4137
4765
|
className: "sm-composer",
|
|
4138
4766
|
"data-soulmirror-group-composer": true,
|
|
4139
|
-
children: [
|
|
4140
|
-
|
|
4141
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4767
|
+
children: [
|
|
4768
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4142
4769
|
style: {
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4770
|
+
display: "flex",
|
|
4771
|
+
alignItems: "center",
|
|
4772
|
+
gap: 14,
|
|
4773
|
+
padding: "0 16px 6px"
|
|
4146
4774
|
},
|
|
4147
|
-
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", {
|
|
4148
4795
|
style: {
|
|
4149
|
-
position: "
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
marginBottom: 6,
|
|
4153
|
-
zIndex: 20,
|
|
4154
|
-
minWidth: 180,
|
|
4155
|
-
maxHeight: 220,
|
|
4156
|
-
overflowY: "auto",
|
|
4157
|
-
borderRadius: 8,
|
|
4158
|
-
border: "1px solid rgba(127,127,127,.35)",
|
|
4159
|
-
background: "var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2, #fff))",
|
|
4160
|
-
boxShadow: "0 6px 24px rgba(0,0,0,.18)",
|
|
4161
|
-
padding: 4,
|
|
4162
|
-
display: "grid"
|
|
4796
|
+
position: "relative",
|
|
4797
|
+
flex: 1,
|
|
4798
|
+
display: "flex"
|
|
4163
4799
|
},
|
|
4164
|
-
|
|
4165
|
-
children: mentionMatches.map((p, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4166
|
-
type: "button",
|
|
4167
|
-
className: "sm-linkbtn",
|
|
4800
|
+
children: [mention !== void 0 && mentionMatches.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4168
4801
|
style: {
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
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"
|
|
4173
4816
|
},
|
|
4174
|
-
|
|
4175
|
-
|
|
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);
|
|
4176
4858
|
},
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4859
|
+
onBlur: () => {
|
|
4860
|
+
setTimeout(() => {
|
|
4861
|
+
setMention(void 0);
|
|
4862
|
+
}, 120);
|
|
4180
4863
|
},
|
|
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
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
},
|
|
4211
|
-
onKeyDown: (e) => {
|
|
4212
|
-
if (e.key === "Escape" && mention !== void 0) {
|
|
4213
|
-
e.preventDefault();
|
|
4214
|
-
e.stopPropagation();
|
|
4215
|
-
setMention(void 0);
|
|
4216
|
-
return;
|
|
4217
|
-
}
|
|
4218
|
-
if (mention !== void 0 && mentionMatches.length > 0 && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
|
|
4219
|
-
e.preventDefault();
|
|
4220
|
-
const len = mentionMatches.length;
|
|
4221
|
-
setMentionIdx((i) => (Math.min(i, len - 1) + (e.key === "ArrowDown" ? 1 : len - 1)) % len);
|
|
4222
|
-
return;
|
|
4223
|
-
}
|
|
4224
|
-
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
4225
|
-
e.preventDefault();
|
|
4226
|
-
if (mention !== void 0 && mentionMatches.length > 0) pickMention(mentionMatches[Math.min(mentionIdx, mentionMatches.length - 1)].name);
|
|
4227
|
-
else send();
|
|
4228
|
-
}
|
|
4229
|
-
},
|
|
4230
|
-
"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")
|
|
4231
4893
|
})]
|
|
4232
|
-
}),
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
gap: 10
|
|
4247
|
-
},
|
|
4248
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4249
|
-
style: { flex: 1 },
|
|
4250
|
-
children: t("group.composer.hint")
|
|
4251
|
-
}), alterSwitch]
|
|
4252
|
-
})]
|
|
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
|
+
]
|
|
4253
4908
|
}),
|
|
4254
4909
|
agentsSheetOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupAgentsSheet, {
|
|
4255
4910
|
t,
|
|
@@ -4525,35 +5180,143 @@ window.__ModuleLoader__.load({
|
|
|
4525
5180
|
})]
|
|
4526
5181
|
})] });
|
|
4527
5182
|
}
|
|
4528
|
-
function
|
|
4529
|
-
const
|
|
4530
|
-
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
|
+
}, []);
|
|
4531
5195
|
(0, react.useEffect)(() => {
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
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,
|
|
4557
5320
|
"data-soulmirror-setting": field,
|
|
4558
5321
|
children: (options ?? []).map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4559
5322
|
value: o,
|
|
@@ -4561,7 +5324,7 @@ window.__ModuleLoader__.load({
|
|
|
4561
5324
|
}, o))
|
|
4562
5325
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4563
5326
|
style: input,
|
|
4564
|
-
type: type === "number" ? "number" : "text",
|
|
5327
|
+
type: type === "password" ? "password" : type === "number" ? "number" : "text",
|
|
4565
5328
|
min,
|
|
4566
5329
|
value: draft,
|
|
4567
5330
|
disabled: !writable,
|
|
@@ -4701,7 +5464,7 @@ window.__ModuleLoader__.load({
|
|
|
4701
5464
|
const key = BINARY_SOURCE_KEYS[source];
|
|
4702
5465
|
return key === void 0 ? source : t(key);
|
|
4703
5466
|
}
|
|
4704
|
-
function SoulmirrorSettingsSection({
|
|
5467
|
+
function SoulmirrorSettingsSection({ scope, t }) {
|
|
4705
5468
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
4706
5469
|
const subscribeScope = (0, react.useCallback)((listener) => scope.subscribe(listener), [scope]);
|
|
4707
5470
|
const readScope = (0, react.useCallback)(() => scope.getSnapshot(), [scope]);
|
|
@@ -4942,28 +5705,17 @@ window.__ModuleLoader__.load({
|
|
|
4942
5705
|
}),
|
|
4943
5706
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4944
5707
|
style: rowStyle,
|
|
4945
|
-
children: [
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
onClick: () => {
|
|
4957
|
-
openSession(state.alter.sessionId);
|
|
4958
|
-
},
|
|
4959
|
-
"data-soulmirror-settings-open-alter-session": true,
|
|
4960
|
-
children: t("settings.alter.openSession")
|
|
4961
|
-
}) : null,
|
|
4962
|
-
state?.alter?.legacyFriendSessions !== void 0 && Object.keys(state.alter.legacyFriendSessions).length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4963
|
-
style: small$1,
|
|
4964
|
-
children: t("settings.alter.legacy", { n: Object.keys(state.alter.legacyFriendSessions).length })
|
|
4965
|
-
}) : null
|
|
4966
|
-
]
|
|
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]
|
|
4967
5719
|
}),
|
|
4968
5720
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4969
5721
|
style: {
|
|
@@ -4984,6 +5736,87 @@ window.__ModuleLoader__.load({
|
|
|
4984
5736
|
})
|
|
4985
5737
|
]
|
|
4986
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
|
+
}),
|
|
4987
5820
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4988
5821
|
style: card,
|
|
4989
5822
|
children: [
|
|
@@ -5554,14 +6387,36 @@ window.__ModuleLoader__.load({
|
|
|
5554
6387
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5555
6388
|
style: { opacity: .8 },
|
|
5556
6389
|
children: t("settings.agents.cwd")
|
|
5557
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5558
|
-
style:
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
onChange: (e) => {
|
|
5562
|
-
setCwd(e.target.value);
|
|
6390
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6391
|
+
style: {
|
|
6392
|
+
display: "flex",
|
|
6393
|
+
gap: 6
|
|
5563
6394
|
},
|
|
5564
|
-
"
|
|
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
|
+
})]
|
|
5565
6420
|
})]
|
|
5566
6421
|
}),
|
|
5567
6422
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
@@ -5689,15 +6544,377 @@ window.__ModuleLoader__.load({
|
|
|
5689
6544
|
});
|
|
5690
6545
|
}
|
|
5691
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
|
|
5692
6910
|
//#region src/client/AgentPane.tsx
|
|
5693
6911
|
/**
|
|
5694
6912
|
* Right pane for one NAMED seat agent: the owner talks to it directly here
|
|
5695
6913
|
* (composer → `agent.instruct`), watches its transcript (`agent.history`,
|
|
5696
6914
|
* same fold as the alter's — owner bubbles right, the agent's notes left,
|
|
5697
6915
|
* the group messages that woke it as compact cards, its group posts as send
|
|
5698
|
-
* lines) and reaches its settings (the sheet)
|
|
5699
|
-
*
|
|
5700
|
-
* debounced refetch.
|
|
6916
|
+
* lines) and reaches its settings (the sheet). Live: SSE `agent` frames for
|
|
6917
|
+
* this name trigger a debounced refetch.
|
|
5701
6918
|
*/
|
|
5702
6919
|
const FOLLOW_SLACK$2 = 48;
|
|
5703
6920
|
const HISTORY_LIMIT = 200;
|
|
@@ -5706,7 +6923,7 @@ window.__ModuleLoader__.load({
|
|
|
5706
6923
|
const d = new Date(ts);
|
|
5707
6924
|
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
|
|
5708
6925
|
}
|
|
5709
|
-
function AgentPane({ t, agent,
|
|
6926
|
+
function AgentPane({ t, agent, onRemoved }) {
|
|
5710
6927
|
const name = agent.name;
|
|
5711
6928
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
5712
6929
|
const [history, setHistory] = (0, react.useState)(void 0);
|
|
@@ -6003,13 +7220,13 @@ window.__ModuleLoader__.load({
|
|
|
6003
7220
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6004
7221
|
className: "sm-home-title",
|
|
6005
7222
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("agent.home.actions") })
|
|
6006
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7223
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6007
7224
|
style: {
|
|
6008
7225
|
display: "flex",
|
|
6009
7226
|
gap: 6,
|
|
6010
7227
|
flexWrap: "wrap"
|
|
6011
7228
|
},
|
|
6012
|
-
children:
|
|
7229
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
6013
7230
|
type: "button",
|
|
6014
7231
|
className: "sm-ghostbtn",
|
|
6015
7232
|
onClick: () => {
|
|
@@ -6020,18 +7237,7 @@ window.__ModuleLoader__.load({
|
|
|
6020
7237
|
" ",
|
|
6021
7238
|
t("agent.settings")
|
|
6022
7239
|
]
|
|
6023
|
-
})
|
|
6024
|
-
type: "button",
|
|
6025
|
-
className: "sm-ghostbtn",
|
|
6026
|
-
onClick: () => {
|
|
6027
|
-
onOpenSession(sessionId);
|
|
6028
|
-
},
|
|
6029
|
-
children: [
|
|
6030
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 }),
|
|
6031
|
-
" ",
|
|
6032
|
-
t("alter.openDsh")
|
|
6033
|
-
]
|
|
6034
|
-
}) : null]
|
|
7240
|
+
})
|
|
6035
7241
|
})]
|
|
6036
7242
|
})
|
|
6037
7243
|
]
|
|
@@ -6075,9 +7281,9 @@ window.__ModuleLoader__.load({
|
|
|
6075
7281
|
]
|
|
6076
7282
|
})]
|
|
6077
7283
|
}),
|
|
6078
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7284
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6079
7285
|
className: "sm-chat-head-actions",
|
|
6080
|
-
children:
|
|
7286
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6081
7287
|
label: t("agent.settings"),
|
|
6082
7288
|
side: "bottom",
|
|
6083
7289
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -6093,23 +7299,7 @@ window.__ModuleLoader__.load({
|
|
|
6093
7299
|
t("agent.settings")
|
|
6094
7300
|
]
|
|
6095
7301
|
})
|
|
6096
|
-
})
|
|
6097
|
-
label: t("alter.openDsh.hint"),
|
|
6098
|
-
side: "bottom",
|
|
6099
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
6100
|
-
type: "button",
|
|
6101
|
-
className: "sm-ghostbtn",
|
|
6102
|
-
onClick: () => {
|
|
6103
|
-
onOpenSession(sessionId);
|
|
6104
|
-
},
|
|
6105
|
-
"data-soulmirror-agent-open-dsh": true,
|
|
6106
|
-
children: [
|
|
6107
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 }),
|
|
6108
|
-
" ",
|
|
6109
|
-
t("alter.openDsh")
|
|
6110
|
-
]
|
|
6111
|
-
})
|
|
6112
|
-
}) : null]
|
|
7302
|
+
})
|
|
6113
7303
|
})
|
|
6114
7304
|
]
|
|
6115
7305
|
}),
|
|
@@ -6119,7 +7309,17 @@ window.__ModuleLoader__.load({
|
|
|
6119
7309
|
onChange: pageStore.setPaneTab,
|
|
6120
7310
|
t
|
|
6121
7311
|
}),
|
|
6122
|
-
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: [
|
|
6123
7323
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6124
7324
|
ref: scroller,
|
|
6125
7325
|
className: "sm-thread",
|
|
@@ -6248,12 +7448,17 @@ window.__ModuleLoader__.load({
|
|
|
6248
7448
|
default: return t("draft.reason.unknown-trigger");
|
|
6249
7449
|
}
|
|
6250
7450
|
}
|
|
6251
|
-
function DraftCard({ draft, t, showTarget, onGoFriend }) {
|
|
7451
|
+
function DraftCard({ draft, t, showTarget, onGoFriend, onGoGroup }) {
|
|
6252
7452
|
const busy = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot).deciding.includes(draft.id);
|
|
6253
7453
|
const [mode, setMode] = (0, react.useState)("idle");
|
|
6254
7454
|
const [text, setText] = (0, react.useState)(draft.body);
|
|
6255
7455
|
const [feedback, setFeedback] = (0, react.useState)("");
|
|
6256
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;
|
|
6257
7462
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6258
7463
|
className: "sm-draft",
|
|
6259
7464
|
"data-soulmirror-draft": draft.id,
|
|
@@ -6267,13 +7472,11 @@ window.__ModuleLoader__.load({
|
|
|
6267
7472
|
children: t("draft.tag")
|
|
6268
7473
|
}),
|
|
6269
7474
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: showTarget === true ? t("draft.title.to", { name: draft.name }) : t("draft.title") }),
|
|
6270
|
-
showTarget === true &&
|
|
7475
|
+
showTarget === true && openTarget !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6271
7476
|
type: "button",
|
|
6272
7477
|
className: "sm-linkbtn",
|
|
6273
|
-
onClick:
|
|
6274
|
-
|
|
6275
|
-
},
|
|
6276
|
-
children: t("draft.openThread")
|
|
7478
|
+
onClick: openTarget,
|
|
7479
|
+
children: draft.gid !== void 0 ? t("draft.openGroup") : t("draft.openThread")
|
|
6277
7480
|
}) : null,
|
|
6278
7481
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6279
7482
|
className: "sm-row-time",
|
|
@@ -6440,7 +7643,7 @@ window.__ModuleLoader__.load({
|
|
|
6440
7643
|
const d = new Date(ts);
|
|
6441
7644
|
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
|
|
6442
7645
|
}
|
|
6443
|
-
function AlterPane({ t,
|
|
7646
|
+
function AlterPane({ t, onGoFriend, onGoGroup, renderCards, scope }) {
|
|
6444
7647
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
6445
7648
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
6446
7649
|
const alter = page.alter;
|
|
@@ -6448,6 +7651,23 @@ window.__ModuleLoader__.load({
|
|
|
6448
7651
|
const drafts = net.inbox.drafts;
|
|
6449
7652
|
const running = alter.status === "running" || alter.chat.running || alter.instructing;
|
|
6450
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
|
+
}, []);
|
|
6451
7671
|
const scroller = (0, react.useRef)(null);
|
|
6452
7672
|
const textarea = (0, react.useRef)(null);
|
|
6453
7673
|
const following = (0, react.useRef)(true);
|
|
@@ -6464,7 +7684,7 @@ window.__ModuleLoader__.load({
|
|
|
6464
7684
|
if (el === null) return;
|
|
6465
7685
|
if (firstPaint.current && items.length > 0) {
|
|
6466
7686
|
firstPaint.current = false;
|
|
6467
|
-
el.scrollTop =
|
|
7687
|
+
el.scrollTop = el.scrollHeight;
|
|
6468
7688
|
return;
|
|
6469
7689
|
}
|
|
6470
7690
|
if (following.current) el.scrollTop = el.scrollHeight;
|
|
@@ -6572,31 +7792,33 @@ window.__ModuleLoader__.load({
|
|
|
6572
7792
|
})]
|
|
6573
7793
|
});
|
|
6574
7794
|
case "inbound": {
|
|
6575
|
-
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
|
+
};
|
|
6576
7801
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6577
7802
|
className: "sm-citem sm-wide",
|
|
6578
|
-
"data-soulmirror-alter-item": "inbound",
|
|
7803
|
+
"data-soulmirror-alter-item": group !== void 0 ? "group" : "inbound",
|
|
6579
7804
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6580
7805
|
className: "sm-inmail",
|
|
6581
7806
|
role: "button",
|
|
6582
7807
|
tabIndex: 0,
|
|
6583
|
-
onClick:
|
|
6584
|
-
onGoFriend(item.fp);
|
|
6585
|
-
},
|
|
7808
|
+
onClick: open,
|
|
6586
7809
|
onKeyDown: (e) => {
|
|
6587
|
-
if (e.key === "Enter")
|
|
7810
|
+
if (e.key === "Enter") open();
|
|
6588
7811
|
},
|
|
6589
7812
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6590
7813
|
className: "sm-inmail-head",
|
|
6591
7814
|
children: [
|
|
6592
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.item.inbound", { name: "" }) }),
|
|
6593
|
-
/* @__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 })] }),
|
|
6594
7816
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["· ", formatClock(item.ts)] }),
|
|
6595
7817
|
item.auto ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["· ", t("bubble.auto")] }) : null,
|
|
6596
7818
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6597
7819
|
style: { marginLeft: "auto" },
|
|
6598
7820
|
className: "sm-linkbtn",
|
|
6599
|
-
children: t("alter.item.view")
|
|
7821
|
+
children: group !== void 0 ? t("alter.item.viewGroup", { name }) : t("alter.item.view")
|
|
6600
7822
|
})
|
|
6601
7823
|
]
|
|
6602
7824
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -6729,110 +7951,88 @@ window.__ModuleLoader__.load({
|
|
|
6729
7951
|
"data-soulmirror-alter-home": true,
|
|
6730
7952
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6731
7953
|
className: "sm-home-inner",
|
|
6732
|
-
children: [
|
|
6733
|
-
|
|
6734
|
-
|
|
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
|
+
},
|
|
6735
7966
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6736
|
-
className: "sm-
|
|
6737
|
-
"
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
style: {
|
|
6741
|
-
display: "grid",
|
|
6742
|
-
gap: 2,
|
|
6743
|
-
minWidth: 0
|
|
6744
|
-
},
|
|
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",
|
|
6745
7971
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6746
|
-
className: "sm-
|
|
6747
|
-
|
|
6748
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
6749
|
-
className: "sm-home-id-sub",
|
|
6750
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6751
|
-
className: `sm-livedot${running ? " sm-busy" : ""}`,
|
|
6752
|
-
"aria-hidden": true
|
|
6753
|
-
}), /* @__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") })]
|
|
6754
|
-
})]
|
|
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") })]
|
|
6755
7975
|
})]
|
|
6756
|
-
})
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
className: "sm-home-title",
|
|
6762
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.home.profile") })
|
|
6763
|
-
}),
|
|
6764
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6765
|
-
className: "sm-home-line",
|
|
6766
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6767
|
-
className: "sm-home-line-key",
|
|
6768
|
-
children: t("alter.home.session")
|
|
6769
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6770
|
-
className: "sm-home-line-val",
|
|
6771
|
-
children: alter.sessionId ?? t("alter.home.none")
|
|
6772
|
-
})]
|
|
6773
|
-
}),
|
|
6774
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6775
|
-
className: "sm-home-line",
|
|
6776
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6777
|
-
className: "sm-home-line-key",
|
|
6778
|
-
children: t("alter.home.friends")
|
|
6779
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6780
|
-
className: "sm-home-line-val",
|
|
6781
|
-
children: friends.length
|
|
6782
|
-
})]
|
|
6783
|
-
}),
|
|
6784
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6785
|
-
className: "sm-home-line",
|
|
6786
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6787
|
-
className: "sm-home-line-key",
|
|
6788
|
-
children: t("alter.home.drafts")
|
|
6789
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6790
|
-
className: "sm-home-line-val",
|
|
6791
|
-
children: drafts.length
|
|
6792
|
-
})]
|
|
6793
|
-
}),
|
|
6794
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6795
|
-
className: "sm-home-line",
|
|
6796
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6797
|
-
className: "sm-home-line-key",
|
|
6798
|
-
children: t("alter.home.defaultTier")
|
|
6799
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6800
|
-
className: "sm-home-line-val",
|
|
6801
|
-
children: t(`tier.short.${net.state?.alter?.defaultTier ?? "draft"}`)
|
|
6802
|
-
})]
|
|
6803
|
-
}),
|
|
6804
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6805
|
-
className: "sm-home-line",
|
|
6806
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6807
|
-
className: "sm-home-line-key",
|
|
6808
|
-
children: t("alter.home.perHour")
|
|
6809
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6810
|
-
className: "sm-home-line-val",
|
|
6811
|
-
children: net.state?.alter?.autoReplyPerHour ?? 20
|
|
6812
|
-
})]
|
|
6813
|
-
})
|
|
6814
|
-
]
|
|
6815
|
-
}),
|
|
6816
|
-
alter.sessionId !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6817
|
-
className: "sm-home-card",
|
|
6818
|
-
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", {
|
|
6819
7981
|
className: "sm-home-title",
|
|
6820
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("alter.home.
|
|
6821
|
-
}),
|
|
6822
|
-
|
|
6823
|
-
className: "sm-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
"
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
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
|
+
})]
|
|
6836
8036
|
})
|
|
6837
8037
|
});
|
|
6838
8038
|
const cardProps = {
|
|
@@ -6840,10 +8040,7 @@ window.__ModuleLoader__.load({
|
|
|
6840
8040
|
sessionId: alter.sessionId,
|
|
6841
8041
|
status: alter.status
|
|
6842
8042
|
},
|
|
6843
|
-
scope
|
|
6844
|
-
openSession: () => {
|
|
6845
|
-
if (alter.sessionId !== void 0) onOpenSession(alter.sessionId);
|
|
6846
|
-
}
|
|
8043
|
+
scope
|
|
6847
8044
|
};
|
|
6848
8045
|
const alterSettings = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6849
8046
|
className: "sm-home",
|
|
@@ -6861,58 +8058,86 @@ window.__ModuleLoader__.load({
|
|
|
6861
8058
|
children: [
|
|
6862
8059
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
6863
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
|
+
},
|
|
6864
8095
|
children: [
|
|
6865
8096
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6866
|
-
|
|
6867
|
-
"
|
|
6868
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SoulMirrorIcon, { size: 18 })
|
|
8097
|
+
style: { opacity: .7 },
|
|
8098
|
+
children: t("alter.wallet")
|
|
6869
8099
|
}),
|
|
6870
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
8100
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6871
8101
|
style: {
|
|
8102
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
6872
8103
|
flex: 1,
|
|
6873
8104
|
minWidth: 0,
|
|
6874
|
-
|
|
8105
|
+
overflow: "hidden",
|
|
8106
|
+
textOverflow: "ellipsis",
|
|
8107
|
+
whiteSpace: "nowrap"
|
|
6875
8108
|
},
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6880
|
-
className: "sm-chat-head-sub",
|
|
6881
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6882
|
-
className: `sm-livedot${running ? " sm-busy" : ""}`,
|
|
6883
|
-
"aria-hidden": true
|
|
6884
|
-
}), alter.sessionId === void 0 ? t("alter.status.noSession") : running ? t("alter.status.running") : t("alter.status.idle")]
|
|
6885
|
-
})]
|
|
8109
|
+
title: wallet.address,
|
|
8110
|
+
"data-soulmirror-alter-wallet-address": true,
|
|
8111
|
+
children: wallet.address
|
|
6886
8112
|
}),
|
|
6887
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
t("alter.openDsh")
|
|
6903
|
-
]
|
|
6904
|
-
})
|
|
6905
|
-
}) : null
|
|
6906
|
-
})
|
|
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}` : ""
|
|
8119
|
+
}),
|
|
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
|
|
6907
8128
|
]
|
|
6908
|
-
}),
|
|
8129
|
+
}) : null,
|
|
6909
8130
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContentTabs, {
|
|
6910
8131
|
tabs,
|
|
6911
8132
|
active: paneTab,
|
|
6912
8133
|
onChange: pageStore.setPaneTab,
|
|
6913
8134
|
t
|
|
6914
8135
|
}),
|
|
6915
|
-
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: [
|
|
6916
8141
|
drafts.length > 0 && firstDraft !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6917
8142
|
className: "sm-pendbar",
|
|
6918
8143
|
"data-soulmirror-alter-pendbar": drafts.length,
|
|
@@ -6969,7 +8194,8 @@ window.__ModuleLoader__.load({
|
|
|
6969
8194
|
draft: d,
|
|
6970
8195
|
t,
|
|
6971
8196
|
showTarget: true,
|
|
6972
|
-
onGoFriend
|
|
8197
|
+
onGoFriend,
|
|
8198
|
+
onGoGroup
|
|
6973
8199
|
}, d.id)),
|
|
6974
8200
|
running ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6975
8201
|
className: "sm-citem sm-alter",
|
|
@@ -7032,6 +8258,36 @@ window.__ModuleLoader__.load({
|
|
|
7032
8258
|
});
|
|
7033
8259
|
}
|
|
7034
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
|
|
7035
8291
|
//#region src/client/group-templates.ts
|
|
7036
8292
|
const base = (id, patch) => ({
|
|
7037
8293
|
id,
|
|
@@ -7103,7 +8359,7 @@ window.__ModuleLoader__.load({
|
|
|
7103
8359
|
* The dialog owns the form state; the caller owns the actual creation
|
|
7104
8360
|
* (`onCreate`) and the busy flag.
|
|
7105
8361
|
*/
|
|
7106
|
-
function GroupCreateDialog({ t, friends, busy, onCreate, onClose }) {
|
|
8362
|
+
function GroupCreateDialog({ t, friends, busy, walletAddress, onCreate, onClose }) {
|
|
7107
8363
|
const std = GROUP_TEMPLATES[0].profile;
|
|
7108
8364
|
const [name, setName] = (0, react.useState)("");
|
|
7109
8365
|
const [sel, setSel] = (0, react.useState)({});
|
|
@@ -7114,6 +8370,7 @@ window.__ModuleLoader__.load({
|
|
|
7114
8370
|
speakAgents: std.speakAgents,
|
|
7115
8371
|
speakWho: std.speakWho ?? "all",
|
|
7116
8372
|
join: std.join ?? "invite",
|
|
8373
|
+
joinPrice: "",
|
|
7117
8374
|
agentWake: std.agentWake ?? "mention",
|
|
7118
8375
|
agentTier: std.agentTier ?? "draft",
|
|
7119
8376
|
rules: "",
|
|
@@ -7130,10 +8387,12 @@ window.__ModuleLoader__.load({
|
|
|
7130
8387
|
};
|
|
7131
8388
|
}, [onClose]);
|
|
7132
8389
|
const members = Object.entries(sel).filter(([, v]) => v).map(([k]) => k);
|
|
7133
|
-
const
|
|
8390
|
+
const paidIncomplete = adv.join === "paid" && (walletAddress === void 0 || adv.joinPrice.trim() === "");
|
|
8391
|
+
const ready = !busy && name.trim() !== "" && members.length > 0 && !paidIncomplete;
|
|
7134
8392
|
const submit = () => {
|
|
7135
8393
|
if (!ready) return;
|
|
7136
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() !== "";
|
|
7137
8396
|
const profile = templateProfile(tpl, {
|
|
7138
8397
|
speakHumans: adv.speakHumans,
|
|
7139
8398
|
speakAgents: adv.speakAgents,
|
|
@@ -7142,6 +8401,10 @@ window.__ModuleLoader__.load({
|
|
|
7142
8401
|
agentWake: adv.agentWake,
|
|
7143
8402
|
agentTier: adv.agentTier,
|
|
7144
8403
|
...adv.rules.trim() === "" ? {} : { rules: adv.rules },
|
|
8404
|
+
...paid ? {
|
|
8405
|
+
joinPrice: adv.joinPrice.trim(),
|
|
8406
|
+
joinAddr: walletAddress
|
|
8407
|
+
} : {},
|
|
7145
8408
|
...adv.isPublic ? { public: true } : {},
|
|
7146
8409
|
...tags.length === 0 ? {} : { tags }
|
|
7147
8410
|
});
|
|
@@ -7305,31 +8568,92 @@ window.__ModuleLoader__.load({
|
|
|
7305
8568
|
}),
|
|
7306
8569
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7307
8570
|
className: "sm-field",
|
|
7308
|
-
children: [
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
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
|
+
]
|
|
7332
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,
|
|
7333
8657
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7334
8658
|
className: "sm-field",
|
|
7335
8659
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.wake") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
@@ -7464,6 +8788,10 @@ window.__ModuleLoader__.load({
|
|
|
7464
8788
|
* (card URI + note) at the bottom. The selected row is highlighted; clicking
|
|
7465
8789
|
* a friend row selects it (the friend pane marks it read).
|
|
7466
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;
|
|
7467
8795
|
function useCopy() {
|
|
7468
8796
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
7469
8797
|
return [copied, (0, react.useCallback)((text) => {
|
|
@@ -7603,7 +8931,77 @@ window.__ModuleLoader__.load({
|
|
|
7603
8931
|
})]
|
|
7604
8932
|
}) });
|
|
7605
8933
|
}
|
|
7606
|
-
|
|
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 }) {
|
|
7607
9005
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
7608
9006
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
7609
9007
|
const { inbox } = net;
|
|
@@ -7617,10 +9015,26 @@ window.__ModuleLoader__.load({
|
|
|
7617
9015
|
const [note, setNote] = (0, react.useState)(void 0);
|
|
7618
9016
|
const [protocolOpen, setProtocolOpen] = (0, react.useState)(false);
|
|
7619
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]);
|
|
7620
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);
|
|
7621
9032
|
/** The WeChat-style "+" menu and the small dialog it opens. */
|
|
7622
9033
|
const [plusOpen, setPlusOpen] = (0, react.useState)(false);
|
|
7623
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);
|
|
7624
9038
|
const [dialog, setDialog] = (0, react.useState)(void 0);
|
|
7625
9039
|
(0, react.useEffect)(() => {
|
|
7626
9040
|
if (query.trim() === "") return;
|
|
@@ -7661,8 +9075,15 @@ window.__ModuleLoader__.load({
|
|
|
7661
9075
|
const nb = b.kind === "friend" ? b.f.name : b.g.name;
|
|
7662
9076
|
return na.localeCompare(nb);
|
|
7663
9077
|
});
|
|
7664
|
-
const
|
|
7665
|
-
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);
|
|
7666
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));
|
|
7667
9088
|
const contentHits = q === "" ? [] : (() => {
|
|
7668
9089
|
const out = [];
|
|
@@ -7729,11 +9150,65 @@ window.__ModuleLoader__.load({
|
|
|
7729
9150
|
const submitJoin = () => {
|
|
7730
9151
|
if (busy !== void 0 || joinUri.trim() === "" || identity === null) return;
|
|
7731
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
|
+
}
|
|
7732
9206
|
const { gid } = await api.groupApply(joinUri.trim());
|
|
7733
9207
|
setJoinUri("");
|
|
9208
|
+
setJoinCard(void 0);
|
|
7734
9209
|
setDialog(void 0);
|
|
7735
9210
|
if (gid !== "") {
|
|
7736
|
-
pageStore.setCol2Tab("
|
|
9211
|
+
pageStore.setCol2Tab("messages");
|
|
7737
9212
|
onSelect(groupKey(gid));
|
|
7738
9213
|
}
|
|
7739
9214
|
return t("group.join.applied");
|
|
@@ -8029,7 +9504,7 @@ window.__ModuleLoader__.load({
|
|
|
8029
9504
|
role: "menuitem",
|
|
8030
9505
|
onClick: () => {
|
|
8031
9506
|
setPlusOpen(false);
|
|
8032
|
-
pageStore.setCol2Tab("
|
|
9507
|
+
pageStore.setCol2Tab("messages");
|
|
8033
9508
|
setCreateOpen(true);
|
|
8034
9509
|
},
|
|
8035
9510
|
"data-soulmirror-plus-new-group": true,
|
|
@@ -8051,6 +9526,7 @@ window.__ModuleLoader__.load({
|
|
|
8051
9526
|
onClick: () => {
|
|
8052
9527
|
setPlusOpen(false);
|
|
8053
9528
|
setDialog("join");
|
|
9529
|
+
loadWallet();
|
|
8054
9530
|
},
|
|
8055
9531
|
"data-soulmirror-plus-join-group": true,
|
|
8056
9532
|
children: t("foot.joinGroup")
|
|
@@ -8063,11 +9539,7 @@ window.__ModuleLoader__.load({
|
|
|
8063
9539
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8064
9540
|
className: "sm-col2-tabs",
|
|
8065
9541
|
"data-soulmirror-col2-tabs": true,
|
|
8066
|
-
children: [
|
|
8067
|
-
"contacts",
|
|
8068
|
-
"agents",
|
|
8069
|
-
"groups"
|
|
8070
|
-
].map((tab) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9542
|
+
children: ["messages", "contacts"].map((tab) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8071
9543
|
type: "button",
|
|
8072
9544
|
className: `sm-col2-tab${col2Tab === tab ? " sm-active" : ""}`,
|
|
8073
9545
|
onClick: () => {
|
|
@@ -8082,7 +9554,7 @@ window.__ModuleLoader__.load({
|
|
|
8082
9554
|
className: "sm-list-body",
|
|
8083
9555
|
children: [
|
|
8084
9556
|
protocolOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProtocolEditor, { t }) : null,
|
|
8085
|
-
col2Tab === "
|
|
9557
|
+
col2Tab === "messages" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
8086
9558
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8087
9559
|
className: "sm-section",
|
|
8088
9560
|
children: t("col2.contacts.section")
|
|
@@ -8132,9 +9604,137 @@ window.__ModuleLoader__.load({
|
|
|
8132
9604
|
className: "sm-row-preview",
|
|
8133
9605
|
children: alterRunning ? t("alter.status.running") : drafts > 0 ? t("alter.row.drafts", { n: drafts }) : t("alter.row.hint")
|
|
8134
9606
|
})]
|
|
8135
|
-
})]
|
|
8136
|
-
}) })
|
|
9607
|
+
})]
|
|
9608
|
+
}) })
|
|
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")
|
|
8137
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: [
|
|
8138
9738
|
inbox.pending.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8139
9739
|
className: "sm-section",
|
|
8140
9740
|
children: [
|
|
@@ -8214,9 +9814,9 @@ window.__ModuleLoader__.load({
|
|
|
8214
9814
|
})] }) : null,
|
|
8215
9815
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8216
9816
|
className: "sm-section",
|
|
8217
|
-
children: t("
|
|
9817
|
+
children: t("inbox.friends")
|
|
8218
9818
|
}),
|
|
8219
|
-
|
|
9819
|
+
contactRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8220
9820
|
className: "sm-muted",
|
|
8221
9821
|
style: {
|
|
8222
9822
|
margin: 0,
|
|
@@ -8224,49 +9824,37 @@ window.__ModuleLoader__.load({
|
|
|
8224
9824
|
fontSize: 12
|
|
8225
9825
|
},
|
|
8226
9826
|
"data-soulmirror-page-empty-list": true,
|
|
8227
|
-
children: identity === null ? t("page.empty.noFriends.noIdentity") : q !== "" ? t("page.empty.noMatch", { query }) : t("
|
|
8228
|
-
}) : /* @__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", {
|
|
8229
9829
|
style: {
|
|
8230
9830
|
listStyle: "none",
|
|
8231
9831
|
margin: 0,
|
|
8232
9832
|
padding: 0
|
|
8233
9833
|
},
|
|
8234
|
-
"data-soulmirror-page-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
typing: inbox.typing[r.f.fp] === true || r.f.typing === true,
|
|
8239
|
-
apps: 0,
|
|
8240
|
-
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,
|
|
8241
9838
|
t,
|
|
8242
9839
|
onSelect: () => {
|
|
8243
|
-
|
|
9840
|
+
onSelectContact(f.fp);
|
|
8244
9841
|
}
|
|
8245
|
-
},
|
|
8246
|
-
})
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
display: "flex",
|
|
8253
|
-
alignItems: "center",
|
|
8254
|
-
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);
|
|
8255
9849
|
},
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
onClick: () => {
|
|
8263
|
-
setAgentSheetOpen(true);
|
|
8264
|
-
},
|
|
8265
|
-
"data-soulmirror-agents-add": true,
|
|
8266
|
-
children: ["+ ", t("settings.agents.add")]
|
|
8267
|
-
})]
|
|
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")
|
|
8268
9856
|
}),
|
|
8269
|
-
|
|
9857
|
+
groupContactRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8270
9858
|
className: "sm-muted",
|
|
8271
9859
|
style: {
|
|
8272
9860
|
margin: 0,
|
|
@@ -8274,95 +9862,33 @@ window.__ModuleLoader__.load({
|
|
|
8274
9862
|
fontSize: 12
|
|
8275
9863
|
},
|
|
8276
9864
|
"data-soulmirror-page-empty-list": true,
|
|
8277
|
-
children: t("col2.
|
|
8278
|
-
}) : /* @__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", {
|
|
8279
9867
|
style: {
|
|
8280
9868
|
listStyle: "none",
|
|
8281
9869
|
margin: 0,
|
|
8282
9870
|
padding: 0
|
|
8283
9871
|
},
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
className: "sm-avatar",
|
|
8300
|
-
"aria-hidden": true,
|
|
8301
|
-
children: "🤖"
|
|
8302
|
-
})
|
|
8303
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8304
|
-
className: "sm-row-body",
|
|
8305
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8306
|
-
className: "sm-row-title",
|
|
8307
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8308
|
-
className: "sm-row-name",
|
|
8309
|
-
children: [
|
|
8310
|
-
a.name,
|
|
8311
|
-
" ",
|
|
8312
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8313
|
-
className: `sm-livedot${a.status === "running" ? " sm-busy" : ""}`,
|
|
8314
|
-
"aria-hidden": true
|
|
8315
|
-
})
|
|
8316
|
-
]
|
|
8317
|
-
})
|
|
8318
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8319
|
-
className: "sm-row-preview",
|
|
8320
|
-
children: a.status === "running" ? t("settings.agents.status.running") : a.cwd ?? t("settings.agents.status.idle")
|
|
8321
|
-
})]
|
|
8322
|
-
})]
|
|
8323
|
-
}) }, a.name);
|
|
8324
|
-
})
|
|
8325
|
-
}),
|
|
8326
|
-
agentSheetOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentSettingsSheet, {
|
|
8327
|
-
t,
|
|
8328
|
-
onClose: () => {
|
|
8329
|
-
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);
|
|
8330
9887
|
},
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
] }),
|
|
8336
|
-
col2Tab === "groups" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8337
|
-
className: "sm-section",
|
|
8338
|
-
children: t("groups.section")
|
|
8339
|
-
}), groupRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8340
|
-
className: "sm-muted",
|
|
8341
|
-
style: {
|
|
8342
|
-
margin: 0,
|
|
8343
|
-
padding: "4px 10px 10px",
|
|
8344
|
-
fontSize: 12
|
|
8345
|
-
},
|
|
8346
|
-
"data-soulmirror-page-empty-list": true,
|
|
8347
|
-
children: q !== "" ? t("page.empty.noMatch", { query }) : t("col2.groups.empty")
|
|
8348
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
8349
|
-
style: {
|
|
8350
|
-
listStyle: "none",
|
|
8351
|
-
margin: 0,
|
|
8352
|
-
padding: 0
|
|
8353
|
-
},
|
|
8354
|
-
"data-soulmirror-page-groups": true,
|
|
8355
|
-
children: groupRows.map((r) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChatRow, {
|
|
8356
|
-
row: r,
|
|
8357
|
-
typing: false,
|
|
8358
|
-
apps: inbox.groupApps[r.g.gid] ?? 0,
|
|
8359
|
-
selected: selected === r.rowKey,
|
|
8360
|
-
t,
|
|
8361
|
-
onSelect: () => {
|
|
8362
|
-
onSelect(r.rowKey);
|
|
8363
|
-
}
|
|
8364
|
-
}, r.rowKey))
|
|
8365
|
-
})] })
|
|
9888
|
+
"data-soulmirror-contacts-groups-expand": true,
|
|
9889
|
+
children: groupsExpandedNow ? t("agents.collapse") : t("agents.expand", { n: groupContactRows.length - CONTACT_COLLAPSE })
|
|
9890
|
+
}) : null] })
|
|
9891
|
+
] })
|
|
8366
9892
|
]
|
|
8367
9893
|
}),
|
|
8368
9894
|
note !== void 0 || net.error !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -8386,6 +9912,7 @@ window.__ModuleLoader__.load({
|
|
|
8386
9912
|
t,
|
|
8387
9913
|
friends: inbox.friends,
|
|
8388
9914
|
busy: busy !== void 0,
|
|
9915
|
+
...walletAddress === void 0 ? {} : { walletAddress },
|
|
8389
9916
|
onCreate: createGroup,
|
|
8390
9917
|
onClose: () => {
|
|
8391
9918
|
setCreateOpen(false);
|
|
@@ -8506,6 +10033,8 @@ window.__ModuleLoader__.load({
|
|
|
8506
10033
|
autoFocus: true,
|
|
8507
10034
|
onChange: (e) => {
|
|
8508
10035
|
setJoinUri(e.target.value);
|
|
10036
|
+
setJoinCard(void 0);
|
|
10037
|
+
setJoinTx("");
|
|
8509
10038
|
},
|
|
8510
10039
|
onKeyDown: (e) => {
|
|
8511
10040
|
if (e.key === "Enter" && !e.nativeEvent.isComposing) submitJoin();
|
|
@@ -8513,22 +10042,122 @@ window.__ModuleLoader__.load({
|
|
|
8513
10042
|
"data-soulmirror-group-join-uri": true
|
|
8514
10043
|
})]
|
|
8515
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,
|
|
8516
10143
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8517
10144
|
className: "sm-modal-foot",
|
|
8518
10145
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8519
10146
|
variant: "outline",
|
|
8520
10147
|
size: "sm",
|
|
8521
10148
|
onClick: () => {
|
|
8522
|
-
|
|
10149
|
+
if (payConfirming) setPayConfirming(false);
|
|
10150
|
+
else setDialog(void 0);
|
|
8523
10151
|
},
|
|
8524
|
-
|
|
10152
|
+
"data-soulmirror-group-join-back": true,
|
|
10153
|
+
children: payConfirming ? t("group.home.edit.cancel") : t("inbox.close")
|
|
8525
10154
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8526
|
-
variant: "
|
|
10155
|
+
variant: "primary",
|
|
8527
10156
|
size: "sm",
|
|
8528
|
-
disabled: busy !== void 0 || joinUri.trim() === "",
|
|
10157
|
+
disabled: busy !== void 0 || joinUri.trim() === "" || joinCard?.price !== void 0 && walletAddress === void 0 && joinTx.trim() === "",
|
|
8529
10158
|
onClick: submitJoin,
|
|
8530
10159
|
"data-soulmirror-group-join-apply": true,
|
|
8531
|
-
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")
|
|
8532
10161
|
})]
|
|
8533
10162
|
})
|
|
8534
10163
|
]
|
|
@@ -8899,7 +10528,7 @@ window.__ModuleLoader__.load({
|
|
|
8899
10528
|
variant: "primary",
|
|
8900
10529
|
size: "sm",
|
|
8901
10530
|
onClick: onGoAlter,
|
|
8902
|
-
children: t("friend.
|
|
10531
|
+
children: t("friend.home.sendMessage")
|
|
8903
10532
|
})
|
|
8904
10533
|
]
|
|
8905
10534
|
})]
|
|
@@ -8910,6 +10539,7 @@ window.__ModuleLoader__.load({
|
|
|
8910
10539
|
tier: friend.tier,
|
|
8911
10540
|
tierExplicit: friend.tierExplicit === true,
|
|
8912
10541
|
protocol: friend.protocol,
|
|
10542
|
+
muted: friend.muted === true,
|
|
8913
10543
|
defaultTier: alterConfig?.defaultTier ?? "draft",
|
|
8914
10544
|
perHour: alterConfig?.autoReplyPerHour ?? 20,
|
|
8915
10545
|
t,
|
|
@@ -8984,7 +10614,17 @@ window.__ModuleLoader__.load({
|
|
|
8984
10614
|
onChange: pageStore.setPaneTab,
|
|
8985
10615
|
t
|
|
8986
10616
|
}),
|
|
8987
|
-
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: [
|
|
8988
10628
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8989
10629
|
className: "sm-banner",
|
|
8990
10630
|
role: "note",
|
|
@@ -9159,6 +10799,7 @@ window.__ModuleLoader__.load({
|
|
|
9159
10799
|
tier: friend.tier,
|
|
9160
10800
|
tierExplicit: friend.tierExplicit === true,
|
|
9161
10801
|
protocol: friend.protocol,
|
|
10802
|
+
muted: friend.muted === true,
|
|
9162
10803
|
defaultTier: alterConfig?.defaultTier ?? "draft",
|
|
9163
10804
|
perHour: alterConfig?.autoReplyPerHour ?? 20,
|
|
9164
10805
|
t,
|
|
@@ -9321,6 +10962,8 @@ window.__ModuleLoader__.load({
|
|
|
9321
10962
|
*/
|
|
9322
10963
|
/** Roster info survives pane switches, so revisiting a group paints names instantly. */
|
|
9323
10964
|
const infoCache = /* @__PURE__ */ new Map();
|
|
10965
|
+
/** 很久没来群(未读 >= 此阈值)进群时,触发一次群记忆提炼(避免每条消息都总结)。 */
|
|
10966
|
+
const GROUP_MEMORY_MIN_UNREAD = 20;
|
|
9324
10967
|
const templateLabel = (t, id) => {
|
|
9325
10968
|
switch (id) {
|
|
9326
10969
|
case "standard": return t("template.standard");
|
|
@@ -9331,7 +10974,7 @@ window.__ModuleLoader__.load({
|
|
|
9331
10974
|
default: return id ?? "";
|
|
9332
10975
|
}
|
|
9333
10976
|
};
|
|
9334
|
-
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");
|
|
9335
10978
|
const wakeLabel = (t, wake) => wake === "always" ? t("group.form.wake.always") : wake === "never" ? t("group.form.wake.never") : t("group.form.wake.mention");
|
|
9336
10979
|
const tierLabel = (t, tier) => tier === "notify" ? t("tier.short.notify") : tier === "auto" ? t("tier.short.auto") : t("tier.short.draft");
|
|
9337
10980
|
const whoLabel = (t, who) => who === "owner" ? t("group.form.speakWho.owner") : who === "admins" ? t("group.form.speakWho.admins") : t("group.form.speakWho.all");
|
|
@@ -9349,6 +10992,12 @@ window.__ModuleLoader__.load({
|
|
|
9349
10992
|
const [inviteFp, setInviteFp] = (0, react.useState)("");
|
|
9350
10993
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
9351
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
|
+
}, []);
|
|
9352
11001
|
const [edit, setEdit] = (0, react.useState)({
|
|
9353
11002
|
speakHumans: true,
|
|
9354
11003
|
speakAgents: true,
|
|
@@ -9356,6 +11005,7 @@ window.__ModuleLoader__.load({
|
|
|
9356
11005
|
join: "invite",
|
|
9357
11006
|
agentWake: "mention",
|
|
9358
11007
|
agentTier: "draft",
|
|
11008
|
+
joinPrice: "",
|
|
9359
11009
|
rules: "",
|
|
9360
11010
|
isPublic: false,
|
|
9361
11011
|
tags: ""
|
|
@@ -9416,6 +11066,10 @@ window.__ModuleLoader__.load({
|
|
|
9416
11066
|
visible,
|
|
9417
11067
|
thread.entries.length
|
|
9418
11068
|
]);
|
|
11069
|
+
(0, react.useEffect)(() => {
|
|
11070
|
+
if (group.unread < GROUP_MEMORY_MIN_UNREAD) return;
|
|
11071
|
+
api.memorySummarize(gid).catch(() => {});
|
|
11072
|
+
}, [gid]);
|
|
9419
11073
|
const run = async (key, action) => {
|
|
9420
11074
|
setBusy(key);
|
|
9421
11075
|
setError(void 0);
|
|
@@ -9478,7 +11132,8 @@ window.__ModuleLoader__.load({
|
|
|
9478
11132
|
speakHumans: profile?.speakHumans ?? true,
|
|
9479
11133
|
speakAgents: profile?.speakAgents ?? true,
|
|
9480
11134
|
speakWho: profile?.speakWho ?? "all",
|
|
9481
|
-
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 ?? "",
|
|
9482
11137
|
agentWake: profile?.agentWake ?? "mention",
|
|
9483
11138
|
agentTier: profile?.agentTier ?? "draft",
|
|
9484
11139
|
rules: profile?.rules ?? "",
|
|
@@ -9489,6 +11144,14 @@ window.__ModuleLoader__.load({
|
|
|
9489
11144
|
};
|
|
9490
11145
|
const saveProfile = () => {
|
|
9491
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
|
+
}
|
|
9492
11155
|
run("profile.save", async () => {
|
|
9493
11156
|
await api.groupSetProfile(gid, {
|
|
9494
11157
|
...profile ?? {},
|
|
@@ -9499,6 +11162,10 @@ window.__ModuleLoader__.load({
|
|
|
9499
11162
|
agentWake: edit.agentWake,
|
|
9500
11163
|
agentTier: edit.agentTier,
|
|
9501
11164
|
rules: edit.rules,
|
|
11165
|
+
...edit.join === "paid" && edit.joinPrice.trim() !== "" && walletAddress !== void 0 ? {
|
|
11166
|
+
joinPrice: edit.joinPrice.trim(),
|
|
11167
|
+
joinAddr: walletAddress
|
|
11168
|
+
} : {},
|
|
9502
11169
|
public: edit.isPublic,
|
|
9503
11170
|
tags
|
|
9504
11171
|
});
|
|
@@ -9518,7 +11185,7 @@ window.__ModuleLoader__.load({
|
|
|
9518
11185
|
};
|
|
9519
11186
|
const chips = profile === void 0 ? [] : [
|
|
9520
11187
|
templateLabel(t, profile.template),
|
|
9521
|
-
joinLabel(t, profile.join),
|
|
11188
|
+
joinLabel(t, profile.join === "paid" ? "paid" : profile.join, profile.join === "paid" ? true : paidJoinFromRules(profile.rules) !== void 0),
|
|
9522
11189
|
whoLabel(t, profile.speakWho),
|
|
9523
11190
|
`${t("group.form.wake")} · ${wakeLabel(t, profile.agentWake)}`,
|
|
9524
11191
|
`${t("group.form.tier")} · ${tierLabel(t, profile.agentTier)}`,
|
|
@@ -9592,7 +11259,7 @@ window.__ModuleLoader__.load({
|
|
|
9592
11259
|
"data-soulmirror-group-profile-edit": true,
|
|
9593
11260
|
children: t("group.home.edit")
|
|
9594
11261
|
}) : null,
|
|
9595
|
-
|
|
11262
|
+
relay !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9596
11263
|
type: "button",
|
|
9597
11264
|
className: "sm-ghostbtn",
|
|
9598
11265
|
onClick: copyUri,
|
|
@@ -9669,31 +11336,71 @@ window.__ModuleLoader__.load({
|
|
|
9669
11336
|
}),
|
|
9670
11337
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
9671
11338
|
className: "sm-field",
|
|
9672
|
-
children: [
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
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
|
+
]
|
|
9696
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,
|
|
9697
11404
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
9698
11405
|
className: "sm-field",
|
|
9699
11406
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("group.form.wake") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
@@ -9827,10 +11534,10 @@ window.__ModuleLoader__.load({
|
|
|
9827
11534
|
className: "sm-statepill",
|
|
9828
11535
|
children: c
|
|
9829
11536
|
}, `${c}-${i}`))
|
|
9830
|
-
}), 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", {
|
|
9831
11538
|
className: "sm-home-rules",
|
|
9832
11539
|
"data-soulmirror-group-rules": true,
|
|
9833
|
-
children: profile.rules
|
|
11540
|
+
children: rulesWithoutPaidJoin(profile.rules)
|
|
9834
11541
|
}) : null] })]
|
|
9835
11542
|
}),
|
|
9836
11543
|
pins.length > 0 || canAdmin ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -10555,7 +12262,7 @@ window.__ModuleLoader__.load({
|
|
|
10555
12262
|
className: "sm-home-card",
|
|
10556
12263
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10557
12264
|
className: "sm-home-title",
|
|
10558
|
-
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", {
|
|
10559
12266
|
type: "button",
|
|
10560
12267
|
className: "sm-ghostbtn",
|
|
10561
12268
|
onClick: copyUri,
|
|
@@ -10886,7 +12593,17 @@ window.__ModuleLoader__.load({
|
|
|
10886
12593
|
...roomOwner,
|
|
10887
12594
|
t
|
|
10888
12595
|
})] })
|
|
10889
|
-
}) : 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
|
|
10890
12607
|
]
|
|
10891
12608
|
});
|
|
10892
12609
|
}
|
|
@@ -10931,7 +12648,7 @@ window.__ModuleLoader__.load({
|
|
|
10931
12648
|
node = parent;
|
|
10932
12649
|
}
|
|
10933
12650
|
}
|
|
10934
|
-
function SoulmirrorPage({
|
|
12651
|
+
function SoulmirrorPage({ scope, t, renderSlot }) {
|
|
10935
12652
|
const page = (0, react.useSyncExternalStore)(pageStore.subscribe, pageStore.getSnapshot);
|
|
10936
12653
|
const net = (0, react.useSyncExternalStore)(networkStore.subscribe, networkStore.getSnapshot);
|
|
10937
12654
|
const subscribeScope = (0, react.useCallback)((listener) => scope.subscribe(listener), [scope]);
|
|
@@ -10992,6 +12709,10 @@ window.__ModuleLoader__.load({
|
|
|
10992
12709
|
if (!target.isConnected) return;
|
|
10993
12710
|
if (rootEl.contains(target)) return;
|
|
10994
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;
|
|
10995
12716
|
pageStore.close();
|
|
10996
12717
|
};
|
|
10997
12718
|
document.addEventListener("mousedown", onDown);
|
|
@@ -11027,9 +12748,12 @@ window.__ModuleLoader__.load({
|
|
|
11027
12748
|
const goFriend = (fp) => {
|
|
11028
12749
|
pageStore.select(fp);
|
|
11029
12750
|
};
|
|
11030
|
-
const
|
|
11031
|
-
|
|
11032
|
-
|
|
12751
|
+
const goGroup = (gid) => {
|
|
12752
|
+
pageStore.select(groupKey(gid));
|
|
12753
|
+
};
|
|
12754
|
+
const openContact = (fp) => {
|
|
12755
|
+
pageStore.select(fp);
|
|
12756
|
+
pageStore.setPaneTab("home");
|
|
11033
12757
|
};
|
|
11034
12758
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11035
12759
|
ref: root,
|
|
@@ -11045,6 +12769,7 @@ window.__ModuleLoader__.load({
|
|
|
11045
12769
|
onSelect: (key) => {
|
|
11046
12770
|
pageStore.select(key);
|
|
11047
12771
|
},
|
|
12772
|
+
onSelectContact: openContact,
|
|
11048
12773
|
onAccepted: (fp) => {
|
|
11049
12774
|
pageStore.select(fp);
|
|
11050
12775
|
},
|
|
@@ -11066,12 +12791,11 @@ window.__ModuleLoader__.load({
|
|
|
11066
12791
|
}) : seatAgent !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentPane, {
|
|
11067
12792
|
t,
|
|
11068
12793
|
agent: seatAgent,
|
|
11069
|
-
onOpenSession: openAlterSession,
|
|
11070
12794
|
onRemoved: goAlter
|
|
11071
12795
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlterPane, {
|
|
11072
12796
|
t,
|
|
11073
|
-
onOpenSession: openAlterSession,
|
|
11074
12797
|
onGoFriend: goFriend,
|
|
12798
|
+
onGoGroup: goGroup,
|
|
11075
12799
|
renderCards: renderSlot,
|
|
11076
12800
|
scope
|
|
11077
12801
|
})]
|
|
@@ -11162,6 +12886,18 @@ window.__ModuleLoader__.load({
|
|
|
11162
12886
|
*/
|
|
11163
12887
|
const STYLE_ID = "soulmirror-styles";
|
|
11164
12888
|
const CSS = `
|
|
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
|
+
|
|
11165
12901
|
/* Icon-only update button at the right end of the SoulMirror foot row:
|
|
11166
12902
|
invisible until a release is known, small circled arrow, tooltip carries
|
|
11167
12903
|
the words. Sits beside the entry (the row is a flex line). */
|
|
@@ -11332,7 +13068,7 @@ body[data-ds-dark-theme] { color-scheme: dark; }
|
|
|
11332
13068
|
.sm-pendbar b { color: var(--dsw-alias-state-warn-primary); }
|
|
11333
13069
|
.sm-pendbar .sm-linkbtn { margin-left: auto; }
|
|
11334
13070
|
.sm-thread { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 20px; display: flex; flex-direction: column; }
|
|
11335
|
-
.sm-thread-inner {
|
|
13071
|
+
.sm-thread-inner { display: flex; flex-direction: column; gap: 4px; }
|
|
11336
13072
|
.sm-day { align-self: center; margin: 10px 0 6px; padding: 1px 10px; border-radius: 10px; font-size: 11px;
|
|
11337
13073
|
color: var(--dsw-alias-label-tertiary); background: var(--dsw-alias-interactive-bg-hover); }
|
|
11338
13074
|
.sm-msg { display: flex; flex-direction: column; max-width: 72%; }
|
|
@@ -11576,7 +13312,8 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11576
13312
|
"sessions",
|
|
11577
13313
|
"settingsScope",
|
|
11578
13314
|
"commandUi",
|
|
11579
|
-
"theme"
|
|
13315
|
+
"theme",
|
|
13316
|
+
"workspaces"
|
|
11580
13317
|
];
|
|
11581
13318
|
/** Whether a session cwd is the SoulMirror workspace (`<home>/a2a`, e.g. `~/.soulnet/a2a`). */
|
|
11582
13319
|
function isSoulmirrorCwd(cwd) {
|
|
@@ -11590,14 +13327,12 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11590
13327
|
en
|
|
11591
13328
|
}), "soulmirror: dictionaries");
|
|
11592
13329
|
const t = ctx.locale.bind(NS);
|
|
13330
|
+
setDirectoryPicker(() => ctx.workspaces.pickDirectory());
|
|
11593
13331
|
ctx.effect(() => {
|
|
11594
13332
|
ensureStyles();
|
|
11595
13333
|
return removeStyles;
|
|
11596
13334
|
}, "soulmirror: inbox styles");
|
|
11597
13335
|
installBranding(ctx);
|
|
11598
|
-
const openSession = (id) => {
|
|
11599
|
-
ctx.sessions.open(id);
|
|
11600
|
-
};
|
|
11601
13336
|
ctx.conversationEvents.register(a2aRelayDefinition);
|
|
11602
13337
|
ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({
|
|
11603
13338
|
name: "conversation.chat.node",
|
|
@@ -11630,10 +13365,7 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11630
13365
|
};
|
|
11631
13366
|
});
|
|
11632
13367
|
const scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
|
|
11633
|
-
const pageInjected = () => ({
|
|
11634
|
-
openSession,
|
|
11635
|
-
scope
|
|
11636
|
-
});
|
|
13368
|
+
const pageInjected = () => ({ scope });
|
|
11637
13369
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
11638
13370
|
name: "shell.overlay",
|
|
11639
13371
|
id: "soulmirror-page",
|
|
@@ -11681,10 +13413,7 @@ body[data-ds-dark-theme] .sm-page-root {
|
|
|
11681
13413
|
clearInterval(timer);
|
|
11682
13414
|
};
|
|
11683
13415
|
});
|
|
11684
|
-
const settingsInjected = () => ({
|
|
11685
|
-
openSession,
|
|
11686
|
-
scope
|
|
11687
|
-
});
|
|
13416
|
+
const settingsInjected = () => ({ scope });
|
|
11688
13417
|
ctx.slots.inject("settings.section", () => {
|
|
11689
13418
|
const make = () => ctx.slots.register({
|
|
11690
13419
|
name: "settings.section",
|