Merge branch 'master' into f/directory-search

# Conflicts:
#	.github/workflows/desktop-linux.yml
#	apps/ios/SimpleX.xcodeproj/project.pbxproj
#	apps/multiplatform/product/gaps.md
#	apps/multiplatform/spec/README.md
#	apps/multiplatform/spec/client/navigation.md
#	scripts/ci/desktop-linux/README.md
#	scripts/ci/desktop-linux/claude-test.sh
#	scripts/ci/ios-sim/README.md
#	scripts/ci/ios-sim/backend.sh
#	src/Simplex/Chat/Library/Commands.hs
This commit is contained in:
spacedandy-agents-simplex committed 2026-10-19 10:24:36 +00:00
commit 547c8ac18b
274 files changed
+19604 -2670

No files matched your search

-9
View File
@@ -56,15 +56,6 @@ ruff check && pyright && pytest tests/
Wire types under `src/simplex_chat/types/_*.py` are generated. Regenerate with `cabal test simplex-chat-test --test-options='--match Python'`.
## Release
Manual for now. Bump `_version.py:__version__`, build a wheel, upload to PyPI:
```bash
uv build --wheel
uv publish --token "$PYPI_TOKEN"
```
## License
[AGPL-3.0](./LICENSE)
@@ -1,16 +1,16 @@
"""Package version and the simplex-chat-libs release it loads.
Written by scripts/ci/packages_release.py: the release PR bumps the version
Written by scripts/ci/packages_release.py prepare: it bumps the version
and pins new library releases with the SHA-256 of their assets.
"""
__version__ = "7.1.0b6" # PEP 440 — read by hatchling for wheel metadata
LIBS_RELEASE = "core-7.1.0.11" # simplex-chat-libs release tag
__version__ = "7.1.0b6.post1" # PEP 440 — read by hatchling for wheel metadata
LIBS_RELEASE = "core-7.1.0.12" # simplex-chat-libs release tag
LIBS_SHA256 = {
"simplex-chat-libs-linux-aarch64.zip": "d66aa1b30b9fa20225dad8ef75a9c605961e1c0adde2ba0283e2fcac4e15d260",
"simplex-chat-libs-linux-x86_64-postgres.zip": "925b3166f969b12082ff8ee659e5f2a9933fe40120deb80c9aa3002a5ba6c803",
"simplex-chat-libs-linux-x86_64.zip": "dabad0824e8813ea4a084fbf37e1ba4cf6dcea9cd8ccadc521fec200f246208a",
"simplex-chat-libs-macos-aarch64.zip": "aa74608b149fff7508a47eaac4284dcc6d189c6ed8b7c18428df9158bc176a61",
"simplex-chat-libs-macos-x86_64.zip": "a0e21457e1077be7f71b46c1c27452945b2cee2b6c50efb0004412ce5b7042ec",
"simplex-chat-libs-windows-x86_64.zip": "c01dad574daa101a1cbfd31ddbf2b3d0d986a4a42f97d789d2f878b2050b2b4b",
"simplex-chat-libs-linux-aarch64.zip": "924b8e14eaba5e309fa584c4bfe598421cf64983d63790c1c45247f592f60055",
"simplex-chat-libs-linux-x86_64-postgres.zip": "323f908b45dde751d6082f8885d07d81fba8a5ab8b2df7d3b8ab3a87e56299e5",
"simplex-chat-libs-linux-x86_64.zip": "995409e963db408bcf896361b669944484f845b6744fefe479aebb0ca2e7c5cd",
"simplex-chat-libs-macos-aarch64.zip": "64464aa48b996e5a96b4aa651bc57bc69e412d3c3804b589c67bd9dc52faddbf",
"simplex-chat-libs-macos-x86_64.zip": "94664f96ff7a2cd5a419096e7e843928faa31cb3addb8869fa1e4b5a0d0b3629",
"simplex-chat-libs-windows-x86_64.zip": "2e10844e5c119921139c373ee2971341aceef7dc4198429d3be6b1570a009d15",
}
@@ -188,6 +188,9 @@ class BadgeProof(TypedDict):
class BadgeRedeemError_invalidCode(TypedDict):
type: Literal["invalidCode"]
class BadgeRedeemError_invalidReceipt(TypedDict):
type: Literal["invalidReceipt"]
class BadgeRedeemError_serviceNotConfigured(TypedDict):
type: Literal["serviceNotConfigured"]
@@ -210,6 +213,7 @@ class BadgeRedeemError_credentialNotVerified(TypedDict):
BadgeRedeemError = (
BadgeRedeemError_invalidCode
| BadgeRedeemError_invalidReceipt
| BadgeRedeemError_serviceNotConfigured
| BadgeRedeemError_badgeActive
| BadgeRedeemError_serviceError
@@ -218,14 +222,85 @@ BadgeRedeemError = (
| BadgeRedeemError_credentialNotVerified
)
BadgeRedeemError_Tag = Literal["invalidCode", "serviceNotConfigured", "badgeActive", "serviceError", "invalidResponse", "unknownKeyIndex", "credentialNotVerified"]
BadgeRedeemError_Tag = Literal["invalidCode", "invalidReceipt", "serviceNotConfigured", "badgeActive", "serviceError", "invalidResponse", "unknownKeyIndex", "credentialNotVerified"]
BadgeServiceErrorCode = Literal["bad_request", "unsupported_version", "unknown_purchase_key", "unknown_offer_id", "offer_disabled", "offer_mismatch", "product_unavailable", "payment_not_entitled", "payment_pending", "provider_unavailable", "rate_limited", "code_invalid", "code_used", "code_expired", "receipt_invalid", "receipt_used", "internal"]
BadgeServiceErrorCode = Literal["bad_request", "unsupported_version", "unknown_purchase_key", "unknown_offer_id", "offer_disabled", "offer_mismatch", "product_unavailable", "payment_not_entitled", "payment_pending", "provider_unavailable", "provider_not_configured", "rate_limited", "code_invalid", "code_used", "code_expired", "receipt_invalid", "receipt_used", "test_purchase", "internal"]
BadgeStatus = Literal["active", "expired", "expiredOld", "failed", "unknownKey"]
BadgeType = Literal["supporter", "legend", "investor"]
class BlockToken_lineBreak(TypedDict):
type: Literal["lineBreak"]
class BlockToken_softBreak(TypedDict):
type: Literal["softBreak"]
class BlockToken_hardBreak(TypedDict):
type: Literal["hardBreak"]
class BlockToken_paragraphBreak(TypedDict):
type: Literal["paragraphBreak"]
lineBreaks: int # int
class BlockToken_indent(TypedDict):
type: Literal["indent"]
class BlockToken_headingMark(TypedDict):
type: Literal["headingMark"]
level: int # int
class BlockToken_headingClose(TypedDict):
type: Literal["headingClose"]
class BlockToken_headingUnderline(TypedDict):
type: Literal["headingUnderline"]
level: int # int
class BlockToken_listMark(TypedDict):
type: Literal["listMark"]
number: NotRequired[str]
class BlockToken_quoteMark(TypedDict):
type: Literal["quoteMark"]
class BlockToken_fenceMark(TypedDict):
type: Literal["fenceMark"]
language: NotRequired[str]
class BlockToken_rowMark(TypedDict):
type: Literal["rowMark"]
class BlockToken_cellMark(TypedDict):
type: Literal["cellMark"]
class BlockToken_delimiterRow(TypedDict):
type: Literal["delimiterRow"]
columns: list["TableAlign"]
class BlockToken_ruleMark(TypedDict):
type: Literal["ruleMark"]
BlockToken = (
BlockToken_lineBreak
| BlockToken_softBreak
| BlockToken_hardBreak
| BlockToken_paragraphBreak
| BlockToken_indent
| BlockToken_headingMark
| BlockToken_headingClose
| BlockToken_headingUnderline
| BlockToken_listMark
| BlockToken_quoteMark
| BlockToken_fenceMark
| BlockToken_rowMark
| BlockToken_cellMark
| BlockToken_delimiterRow
| BlockToken_ruleMark
)
BlockToken_Tag = Literal["lineBreak", "softBreak", "hardBreak", "paragraphBreak", "indent", "headingMark", "headingClose", "headingUnderline", "listMark", "quoteMark", "fenceMark", "rowMark", "cellMark", "delimiterRow", "ruleMark"]
class BlockingInfo(TypedDict):
reason: "BlockingReason"
notice: NotRequired["ClientNotice"]
@@ -688,6 +763,7 @@ class CIQuote(TypedDict):
sentAt: str # ISO-8601 timestamp
content: "MsgContent"
formattedText: NotRequired[list["FormattedText"]]
markdownBlocks: NotRequired[list["MarkdownBlock"]] # non-empty
class CIReaction(TypedDict):
chatDir: "CIDirection"
@@ -1220,6 +1296,7 @@ class ChatItem(TypedDict):
content: "CIContent"
mentions: dict[str, "CIMention"]
formattedText: NotRequired[list["FormattedText"]]
markdownBlocks: NotRequired[list["MarkdownBlock"]] # non-empty
quotedItem: NotRequired["CIQuote"]
reactions: list["CIReactionCount"]
file: NotRequired["CIFile"]
@@ -1243,7 +1320,7 @@ ChatListQuery = ChatListQuery_filters | ChatListQuery_search
ChatListQuery_Tag = Literal["filters", "search"]
ChatPeerType = Literal["human", "bot", "business"]
ChatPeerType = Literal["human", "bot", "business", "agent"]
# Used in API commands. Chat scope can only be passed with groups.
@@ -1791,8 +1868,11 @@ class FileTransferMeta(TypedDict):
FileType = Literal["normal", "roster"]
# The format markup is a token of block Markdown syntax; its text is the syntax. The format escape is the backslash of a backslash escape. Bold singleStar: written with single stars.
class Format_bold(TypedDict):
type: Literal["bold"]
singleStar: bool
class Format_italic(TypedDict):
type: Literal["italic"]
@@ -1846,6 +1926,13 @@ class Format_email(TypedDict):
class Format_phone(TypedDict):
type: Literal["phone"]
class Format_escape(TypedDict):
type: Literal["escape"]
class Format_markup(TypedDict):
type: Literal["markup"]
token: "BlockToken"
Format = (
Format_bold
| Format_italic
@@ -1862,9 +1949,11 @@ Format = (
| Format_mention
| Format_email
| Format_phone
| Format_escape
| Format_markup
)
Format_Tag = Literal["bold", "italic", "strikeThrough", "snippet", "secret", "small", "colored", "uri", "hyperLink", "simplexLink", "simplexName", "command", "mention", "email", "phone"]
Format_Tag = Literal["bold", "italic", "strikeThrough", "snippet", "secret", "small", "colored", "uri", "hyperLink", "simplexLink", "simplexName", "command", "mention", "email", "phone", "escape", "markup"]
class FormattedText(TypedDict):
format: NotRequired["Format"]
@@ -2187,6 +2276,11 @@ class LinkPreview(TypedDict):
image: str
content: NotRequired["LinkContent"]
class ListEntry(TypedDict):
number: NotRequired[str]
content: "SegmentRange"
items: list["ListEntry"]
class LocalBadge(TypedDict):
badge: "BadgeInfo"
status: "BadgeStatus"
@@ -2206,6 +2300,50 @@ class LocalProfile(TypedDict):
contactDomain: NotRequired["SimplexDomainClaim"]
contactDomainVerified: NotRequired[bool]
class MarkdownBlock_paragraph(TypedDict):
type: Literal["paragraph"]
content: "SegmentRange"
class MarkdownBlock_heading(TypedDict):
type: Literal["heading"]
level: int # int
content: "SegmentRange"
class MarkdownBlock_codeBlock(TypedDict):
type: Literal["codeBlock"]
language: NotRequired[str]
content: "SegmentRange"
class MarkdownBlock_quote(TypedDict):
type: Literal["quote"]
content: "SegmentRange"
class MarkdownBlock_list(TypedDict):
type: Literal["list"]
items: list["ListEntry"] # non-empty
class MarkdownBlock_table(TypedDict):
type: Literal["table"]
columns: list["TableAlign"] # non-empty
header: list["SegmentRange"]
rows: list[list["SegmentRange"]]
class MarkdownBlock_rule(TypedDict):
type: Literal["rule"]
mark: "SegmentRange"
MarkdownBlock = (
MarkdownBlock_paragraph
| MarkdownBlock_heading
| MarkdownBlock_codeBlock
| MarkdownBlock_quote
| MarkdownBlock_list
| MarkdownBlock_table
| MarkdownBlock_rule
)
MarkdownBlock_Tag = Literal["paragraph", "heading", "codeBlock", "quote", "list", "table", "rule"]
MemberCriteria = Literal["all"]
# Connection link sent in a message - only short links are allowed.
@@ -2933,6 +3071,11 @@ class SecurityCode(TypedDict):
securityCode: str
verifiedAt: str # ISO-8601 timestamp
SegmentRange = TypedDict("SegmentRange", {
"from": int, # int
"to": int, # int
})
class SimplePreference(TypedDict):
allow: "FeatureAllowed"
@@ -3569,6 +3712,8 @@ class SupportGroupPreference(TypedDict):
SwitchPhase = Literal["started", "confirmed", "secured", "completed"]
TableAlign = Literal["none", "left", "center", "right"]
class TimedMessagesGroupPreference(TypedDict):
enable: "GroupFeatureEnabled"
ttl: NotRequired[int] # int