@hraness/ghostget 0.18.0 → 0.18.3
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/CHANGELOG.md +315 -0
- package/README.md +7 -7
- package/dist/apple-photos-client.js +2 -1
- package/dist/beeper-client.js +2 -1
- package/dist/client.js +1 -0
- package/dist/imessage-direct-install-2gm3kge7.js +324 -0
- package/dist/index-01eeae9e.js +5 -0
- package/dist/index-2ymnp8xv.js +145 -0
- package/dist/{index-9wca02er.js → index-cnbz0gws.js} +1 -1
- package/dist/index-en5hycxp.js +175 -0
- package/dist/index-n4szk3nw.js +50 -0
- package/dist/index-yq6maz71.js +1105 -0
- package/dist/index-z1w83f81.js +4 -0
- package/dist/index.js +4 -47
- package/dist/messaging-automation-api.js +21 -0
- package/dist/messaging-automation-j4274hvc.js +609 -0
- package/dist/messaging-native-install-8w1j36ah.js +16 -0
- package/dist/messaging.js +1 -0
- package/dist/omni-client.js +1 -0
- package/dist/whatsapp-automation-runtime-hgh1e9rm.js +845 -0
- package/dist/whatsapp-client.js +1 -0
- package/docs/control-panel.md +2 -2
- package/docs/imessage-direct-provider.md +31 -7
- package/docs/messaging-automation.md +103 -0
- package/package.json +22 -2
- package/skills/ghostget/references/control-panel.md +1 -1
- package/skills/ghostget/references/install.md +5 -5
- package/skills/ghostget/references/linkedin-adapter.md +215 -13
- package/skills/ghostget/references/platform-patterns.md +1 -1
- package/src/args.ts +18 -5
- package/src/assets/adapters/imessage/wrench-web-adapter.json +126 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.json +1 -1
- package/src/assets/adapters/whatsapp/wrench-web-adapter.json +144 -0
- package/src/assets/messaging-runtime/NOTICE.txt +2580 -0
- package/src/assets/messaging-runtime/imsg-darwin-arm64.gz +0 -0
- package/src/assets/messaging-runtime/phone-number-info.plist.gz +0 -0
- package/src/assets/messaging-runtime/phone-number-metadata.json.gz +0 -0
- package/src/assets/messaging-runtime/phone-number-privacy.plist.gz +0 -0
- package/src/assets/messaging-runtime/wacli-darwin-arm64.gz +0 -0
- package/src/beeper-client-types.ts +1 -1
- package/src/ghostget.ts +16 -4
- package/src/messaging-automation-api.ts +12 -0
- package/src/messaging-automation-descriptors.ts +29 -0
- package/src/messaging-automation-factory.ts +148 -0
- package/src/messaging-automation-server.ts +183 -0
- package/src/messaging-automation-types.ts +155 -0
- package/src/messaging-automation-validation.ts +110 -0
- package/src/messaging-automation.ts +356 -0
- package/src/plugins/imessage-direct/plugin.ts +12 -1
- package/src/plugins/imessage-direct/vendor/0003-feat-rpc-add-no-fetch-rich-cards.patch +276 -0
- package/src/plugins/imessage-direct/vendor/provenance.json +84 -10
- package/src/plugins/linkedin-web/plugin.ts +1 -1
- package/src/plugins/whatsapp-linked-device/plugin.ts +7 -2
- package/src/plugins/whatsapp-linked-device/vendor/0001-ghostget-private-messaging.patch +1093 -0
- package/src/plugins/whatsapp-linked-device/vendor/README.md +39 -0
- package/src/plugins/whatsapp-linked-device/vendor/provenance.json +45 -0
- package/src/provider-plugin.ts +14 -0
- package/src/providers/imessage-automation.ts +250 -0
- package/src/providers/imessage-direct-install.ts +7 -0
- package/src/providers/imessage-direct-runtime.ts +32 -2
- package/src/providers/imessage-direct.ts +13 -3
- package/src/providers/linkedin-contact-failure.ts +21 -0
- package/src/providers/linkedin-contact-platform.ts +8 -1
- package/src/providers/linkedin-contact-program.ts +31 -6
- package/src/providers/linkedin-web-contact.ts +1072 -51
- package/src/providers/linkedin-web-profile-browser.ts +659 -45
- package/src/providers/linkedin-web-runtime.ts +1 -0
- package/src/providers/linkedin-web.ts +46 -2
- package/src/providers/messaging-native-artifacts.ts +38 -0
- package/src/providers/messaging-native-install.ts +75 -0
- package/src/providers/whatsapp-automation-runtime.ts +240 -0
- package/src/providers/whatsapp-automation.ts +153 -0
- package/src/usage.ts +3 -1
- package/src/version.ts +1 -1
- package/src/web-session-contract-definitions.ts +1 -1
- package/tsconfig.json +3 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
From 520b82ab025c1d4d57333b552aa65c9ae3fdb5fd Mon Sep 17 00:00:00 2001
|
|
2
|
+
From: 0thernet <ben@substrate.run>
|
|
3
|
+
Date: Fri, 11 Sep 2026 18:46:37 -0400
|
|
4
|
+
Subject: [PATCH] feat(rpc): add native rich cards without metadata fetching
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
.../RPCServer+BridgeMessageHandlers.swift | 12 +++++-
|
|
8
|
+
Sources/imsg/RichLinkPreparer.swift | 13 +++++++
|
|
9
|
+
.../RPCBridgeMessageHandlersTests.swift | 37 +++++++++++++++++++
|
|
10
|
+
.../RPCSendRichLinkValidationTests.swift | 4 ++
|
|
11
|
+
Tests/imsgTests/RPCServerTests.swift | 21 +++++++----
|
|
12
|
+
Tests/imsgTests/RichLinkPreparerTests.swift | 28 ++++++++++++++
|
|
13
|
+
docs/rpc.md | 2 +-
|
|
14
|
+
scripts/patch-deps.sh | 17 +++++++++
|
|
15
|
+
8 files changed, 123 insertions(+), 11 deletions(-)
|
|
16
|
+
|
|
17
|
+
diff --git a/Sources/imsg/RPCServer+BridgeMessageHandlers.swift b/Sources/imsg/RPCServer+BridgeMessageHandlers.swift
|
|
18
|
+
index b097b9d..9ea023c 100644
|
|
19
|
+
--- a/Sources/imsg/RPCServer+BridgeMessageHandlers.swift
|
|
20
|
+
+++ b/Sources/imsg/RPCServer+BridgeMessageHandlers.swift
|
|
21
|
+
@@ -9,7 +9,7 @@ extension RPCServer {
|
|
22
|
+
RPCParameterKeys.partIndex,
|
|
23
|
+
[
|
|
24
|
+
"text", "message", "file", "path", "url", "dd_scan", "ddScan", "effect_id",
|
|
25
|
+
- "effectId", "effect", "subject", "text_formatting", "textFormatting",
|
|
26
|
+
+ "effectId", "effect", "subject", "text_formatting", "textFormatting", "fetch_metadata",
|
|
27
|
+
]
|
|
28
|
+
)
|
|
29
|
+
let params = try RPCParameters(params, method: "send.rich", supportedKeys: supportedKeys)
|
|
30
|
+
@@ -17,6 +17,9 @@ extension RPCServer {
|
|
31
|
+
try await handleSendRichLink(params: params, id: id)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
+ if params.contains("fetch_metadata") {
|
|
35
|
+
+ throw RPCError.invalidParams("fetch_metadata requires url")
|
|
36
|
+
+ }
|
|
37
|
+
let text = try params.string("text", aliases: ["message"]) ?? ""
|
|
38
|
+
let file = try params.string("file", aliases: ["path"]) ?? ""
|
|
39
|
+
if params.contains("file") || params.contains("path") {
|
|
40
|
+
@@ -112,6 +115,7 @@ extension RPCServer {
|
|
41
|
+
guard let rawURL = try params.string("url") else {
|
|
42
|
+
throw RPCError.invalidParams("url is required")
|
|
43
|
+
}
|
|
44
|
+
+ let fetchMetadata = try params.boolean("fetch_metadata") ?? true
|
|
45
|
+
|
|
46
|
+
let database = try await databaseResources.require()
|
|
47
|
+
let chatInfo = try await strictRichLinkChatInfo(params, database: database)
|
|
48
|
+
@@ -125,7 +129,11 @@ extension RPCServer {
|
|
49
|
+
|
|
50
|
+
let prepared: PreparedRichLinkPreview
|
|
51
|
+
do {
|
|
52
|
+
- prepared = try await prepareRichLink(rawURL)
|
|
53
|
+
+ if fetchMetadata {
|
|
54
|
+
+ prepared = try await prepareRichLink(rawURL)
|
|
55
|
+
+ } else {
|
|
56
|
+
+ prepared = try await RichLinkPreparer.prepare(rawURL, fetchMetadata: false)
|
|
57
|
+
+ }
|
|
58
|
+
} catch let error as RichLinkPreparationError {
|
|
59
|
+
throw RPCError.invalidParams(error.localizedDescription)
|
|
60
|
+
}
|
|
61
|
+
diff --git a/Sources/imsg/RichLinkPreparer.swift b/Sources/imsg/RichLinkPreparer.swift
|
|
62
|
+
index a861229..06e95db 100644
|
|
63
|
+
--- a/Sources/imsg/RichLinkPreparer.swift
|
|
64
|
+
+++ b/Sources/imsg/RichLinkPreparer.swift
|
|
65
|
+
@@ -110,6 +110,7 @@ enum RichLinkPreparer {
|
|
66
|
+
|
|
67
|
+
static func prepare(
|
|
68
|
+
_ rawURL: String,
|
|
69
|
+
+ fetchMetadata: Bool = true,
|
|
70
|
+
timeout: Duration = defaultTimeout,
|
|
71
|
+
loadMetadata: @escaping MetadataLoader = { url in
|
|
72
|
+
try await RichLinkPreparer.loadMetadata(url)
|
|
73
|
+
@@ -119,6 +120,18 @@ enum RichLinkPreparer {
|
|
74
|
+
}
|
|
75
|
+
) async throws -> PreparedRichLinkPreview {
|
|
76
|
+
let originalURL = try validatedURL(rawURL)
|
|
77
|
+
+ try Task.checkCancellation()
|
|
78
|
+
+ if !fetchMetadata {
|
|
79
|
+
+ // The owner may need a native card without giving a URL authority to
|
|
80
|
+
+ // perform network requests. Do not construct a metadata provider, load
|
|
81
|
+
+ // subresources, or stage an image in this mode.
|
|
82
|
+
+ return PreparedRichLinkPreview(
|
|
83
|
+
+ originalURL: originalURL.absoluteString,
|
|
84
|
+
+ resolvedURL: originalURL.absoluteString,
|
|
85
|
+
+ title: sanitizedTitle(nil, fallback: originalURL.host ?? originalURL.absoluteString),
|
|
86
|
+
+ image: nil
|
|
87
|
+
+ )
|
|
88
|
+
+ }
|
|
89
|
+
let fetched: RichLinkFetchedMetadata?
|
|
90
|
+
do {
|
|
91
|
+
fetched = try await fetchWithDeadline(
|
|
92
|
+
diff --git a/Tests/imsgTests/RPCBridgeMessageHandlersTests.swift b/Tests/imsgTests/RPCBridgeMessageHandlersTests.swift
|
|
93
|
+
index 8340399..bed9184 100644
|
|
94
|
+
--- a/Tests/imsgTests/RPCBridgeMessageHandlersTests.swift
|
|
95
|
+
+++ b/Tests/imsgTests/RPCBridgeMessageHandlersTests.swift
|
|
96
|
+
@@ -489,6 +489,43 @@ func rpcSendRichURLRejectsBridgeWithoutPreviewSupportBeforePreparation() async t
|
|
97
|
+
#expect((error?["data"] as? String)?.contains("does not support rich links") == true)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
+@Test
|
|
101
|
+
+func rpcSendRichNoFetchBuildsNativeCardWithoutMetadataPreparation() async throws {
|
|
102
|
+
+ let store = try CommandTestDatabase.makeStoreForRPC()
|
|
103
|
+
+ let output = TestRPCOutput()
|
|
104
|
+
+ var capturedAction: BridgeAction?
|
|
105
|
+
+ var capturedParams: [String: Any] = [:]
|
|
106
|
+
+ var metadataPrepared = false
|
|
107
|
+
+ let server = RPCServer(
|
|
108
|
+
+ store: store,
|
|
109
|
+
+ verbose: false,
|
|
110
|
+
+ output: output,
|
|
111
|
+
+ invokeBridge: { action, params in
|
|
112
|
+
+ if action == .status { return rpcRichLinkCapableStatus() }
|
|
113
|
+
+ capturedAction = action
|
|
114
|
+
+ capturedParams = params
|
|
115
|
+
+ return ["messageGuid": "synthetic-rich-link-guid"]
|
|
116
|
+
+ },
|
|
117
|
+
+ prepareRichLink: { _ in
|
|
118
|
+
+ metadataPrepared = true
|
|
119
|
+
+ return rpcPreparedRichLinkFixture
|
|
120
|
+
+ }
|
|
121
|
+
+ )
|
|
122
|
+
+ await server.handleLineForTesting(
|
|
123
|
+
+ #"{"jsonrpc":"2.0","id":"no-fetch","method":"send.rich","params":{"chat_id":1,"url":"https://example.com/path","fetch_metadata":false}}"#
|
|
124
|
+
+ )
|
|
125
|
+
+ #expect(metadataPrepared == false)
|
|
126
|
+
+ #expect(capturedAction == .sendRichLink)
|
|
127
|
+
+ #expect(capturedParams["message"] as? String == "https://example.com/path")
|
|
128
|
+
+ let preview = capturedParams["richLinkPreview"] as? [String: Any]
|
|
129
|
+
+ #expect(preview?["originalURL"] as? String == "https://example.com/path")
|
|
130
|
+
+ #expect(preview?["resolvedURL"] as? String == "https://example.com/path")
|
|
131
|
+
+ #expect(preview?["title"] as? String == "example.com")
|
|
132
|
+
+ #expect(preview?["image"] == nil)
|
|
133
|
+
+ let result = output.responses.first?["result"] as? [String: Any]
|
|
134
|
+
+ #expect(result?["message_id"] as? String == "synthetic-rich-link-guid")
|
|
135
|
+
+}
|
|
136
|
+
+
|
|
137
|
+
@Test
|
|
138
|
+
func rpcSendRichURLPrefersIMessageChatForSharedIdentifier() async throws {
|
|
139
|
+
let store = try CommandTestDatabase.makeStoreForRPCWithSharedIdentifier()
|
|
140
|
+
diff --git a/Tests/imsgTests/RPCSendRichLinkValidationTests.swift b/Tests/imsgTests/RPCSendRichLinkValidationTests.swift
|
|
141
|
+
index 7e2f329..21fdf77 100644
|
|
142
|
+
--- a/Tests/imsgTests/RPCSendRichLinkValidationTests.swift
|
|
143
|
+
+++ b/Tests/imsgTests/RPCSendRichLinkValidationTests.swift
|
|
144
|
+
@@ -14,6 +14,10 @@ private let rpcValidationRichLinkFixture = PreparedRichLinkPreview(
|
|
145
|
+
func rpcSendRichURLRejectsInvalidTypesAndModifiersBeforePreparation() async throws {
|
|
146
|
+
let store = try CommandTestDatabase.makeStoreForRPC()
|
|
147
|
+
let requests = [
|
|
148
|
+
+ #"{"chat_id":1,"url":"https://imsg.sh","fetch_metadata":null}"#,
|
|
149
|
+
+ #"{"chat_id":1,"url":"https://imsg.sh","fetch_metadata":"false"}"#,
|
|
150
|
+
+ #"{"chat_id":1,"url":"https://imsg.sh","fetch_metadata":0}"#,
|
|
151
|
+
+ #"{"chat_id":1,"text":"synthetic","fetch_metadata":false}"#,
|
|
152
|
+
#"{"chat_id":1,"url":42}"#,
|
|
153
|
+
#"{"chat_id":null,"url":"https://imsg.sh"}"#,
|
|
154
|
+
#"{"chat_id":true,"url":"https://imsg.sh"}"#,
|
|
155
|
+
diff --git a/Tests/imsgTests/RPCServerTests.swift b/Tests/imsgTests/RPCServerTests.swift
|
|
156
|
+
index de1ba0b..68d7859 100644
|
|
157
|
+
--- a/Tests/imsgTests/RPCServerTests.swift
|
|
158
|
+
+++ b/Tests/imsgTests/RPCServerTests.swift
|
|
159
|
+
@@ -53,12 +53,15 @@ func rpcChatsGetReturnsOneExactChatPayload() async throws {
|
|
160
|
+
await server.handleLineForTesting(line)
|
|
161
|
+
|
|
162
|
+
#expect(output.responses.count == 1)
|
|
163
|
+
- let result = output.responses[0]["result"] as? [String: Any]
|
|
164
|
+
- let chat = result?["chat"] as? [String: Any]
|
|
165
|
+
- #expect(int64Value(chat?["id"]) == 1)
|
|
166
|
+
- #expect(chat?["guid"] as? String == "iMessage;+;chat123")
|
|
167
|
+
- #expect(chat?["service"] as? String == "iMessage")
|
|
168
|
+
- #expect(chat?["contact_name"] as? String == "Family")
|
|
169
|
+
+ let response = try #require(output.responses.first)
|
|
170
|
+
+ let result = try #require(response["result"] as? [String: Any])
|
|
171
|
+
+ let chat = try #require(result["chat"] as? [String: Any])
|
|
172
|
+
+ #expect(int64Value(chat["id"]) == 1)
|
|
173
|
+
+ #expect(chat["guid"] as? String == "iMessage;+;chat123")
|
|
174
|
+
+ #expect(chat["service"] as? String == "iMessage")
|
|
175
|
+
+ #expect(chat["display_name"] as? String == "Group Chat")
|
|
176
|
+
+ #expect(chat["is_group"] as? Bool == true)
|
|
177
|
+
+ #expect(chat["contact_name"] == nil)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@Test
|
|
181
|
+
@@ -70,8 +73,10 @@ func rpcChatsGetRejectsAnUnknownChatRow() async throws {
|
|
182
|
+
let line = #"{"jsonrpc":"2.0","id":"missing","method":"chats.get","params":{"chat_id":999}}"#
|
|
183
|
+
await server.handleLineForTesting(line)
|
|
184
|
+
|
|
185
|
+
- #expect(output.responses.count == 1)
|
|
186
|
+
- let error = output.responses[0]["error"] as? [String: Any]
|
|
187
|
+
+ #expect(output.responses.isEmpty)
|
|
188
|
+
+ #expect(output.errors.count == 1)
|
|
189
|
+
+ let response = try #require(output.errors.first)
|
|
190
|
+
+ let error = response["error"] as? [String: Any]
|
|
191
|
+
#expect(int64Value(error?["code"]) == -32602)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
diff --git a/Tests/imsgTests/RichLinkPreparerTests.swift b/Tests/imsgTests/RichLinkPreparerTests.swift
|
|
195
|
+
index e20bed3..6bde945 100644
|
|
196
|
+
--- a/Tests/imsgTests/RichLinkPreparerTests.swift
|
|
197
|
+
+++ b/Tests/imsgTests/RichLinkPreparerTests.swift
|
|
198
|
+
@@ -21,6 +21,34 @@ private final class RichLinkTestBox<Value>: @unchecked Sendable {
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
+@Test
|
|
203
|
+
+func richLinkPreparerNoFetchNeverLoadsOrStagesResources() async throws {
|
|
204
|
+
+ for rawURL in [
|
|
205
|
+
+ "https://example.com/path", "https://127.0.0.1/private", "https://[::1]/", "https://localhost/",
|
|
206
|
+
+ ] {
|
|
207
|
+
+ let loaded = RichLinkTestBox(false)
|
|
208
|
+
+ let staged = RichLinkTestBox(false)
|
|
209
|
+
+ let prepared = try await RichLinkPreparer.prepare(
|
|
210
|
+
+ rawURL,
|
|
211
|
+
+ fetchMetadata: false,
|
|
212
|
+
+ loadMetadata: { _ in
|
|
213
|
+
+ loaded.withValue { $0 = true }
|
|
214
|
+
+ throw CocoaError(.fileReadUnknown)
|
|
215
|
+
+ },
|
|
216
|
+
+ stageImage: { _ in
|
|
217
|
+
+ staged.withValue { $0 = true }
|
|
218
|
+
+ throw CocoaError(.fileWriteUnknown)
|
|
219
|
+
+ }
|
|
220
|
+
+ )
|
|
221
|
+
+ #expect(prepared.originalURL == rawURL)
|
|
222
|
+
+ #expect(prepared.resolvedURL == rawURL)
|
|
223
|
+
+ #expect(!prepared.title.isEmpty)
|
|
224
|
+
+ #expect(prepared.image == nil)
|
|
225
|
+
+ #expect(loaded.withValue { $0 } == false)
|
|
226
|
+
+ #expect(staged.withValue { $0 } == false)
|
|
227
|
+
+ }
|
|
228
|
+
+}
|
|
229
|
+
+
|
|
230
|
+
@Test
|
|
231
|
+
func richLinkPreparerRejectsUnsafeURLs() async {
|
|
232
|
+
let tooLong = "https://example.com/" + String(repeating: "a", count: 8 * 1024)
|
|
233
|
+
diff --git a/docs/rpc.md b/docs/rpc.md
|
|
234
|
+
index c788989..a46bd3e 100644
|
|
235
|
+
--- a/docs/rpc.md
|
|
236
|
+
+++ b/docs/rpc.md
|
|
237
|
+
@@ -584,7 +584,7 @@ database even with an explicit GUID. Strictly verified `send.rich` file/path
|
|
238
|
+
mode and `send.multipart` also require it. Rich-link mode requires a stored
|
|
239
|
+
existing iMessage chat; ordinary `send.rich` text does not.
|
|
240
|
+
|
|
241
|
+
-- `send.rich` sends text with optional `effect`, `subject`, `reply_to`, `part_index`, `dd_scan`, and `text_formatting`. It also accepts `file` or `path` and securely stages the file before sending it through the attachment bridge while preserving those same caption/effect/subject/reply/part/formatting semantics. Attachment capability is checked before staging or publishing the send. Alternatively, pass only one chat target plus an HTTP(S) `url` to send an Apple URL-preview balloon. URL mode is iMessage-only and rejects text, file, and other send modifiers; metadata or image lookup failure falls back to a metadata-only card, never a plain-message send.
|
|
242
|
+
+- `send.rich` sends text with optional `effect`, `subject`, `reply_to`, `part_index`, `dd_scan`, and `text_formatting`. It also accepts `file` or `path` and securely stages the file before sending it through the attachment bridge while preserving those same caption/effect/subject/reply/part/formatting semantics. Attachment capability is checked before staging or publishing the send. Alternatively, pass only one chat target plus an HTTP(S) `url` to send an Apple URL-preview balloon. URL mode is iMessage-only and rejects text, file, and other send modifiers; metadata or image lookup failure falls back to a metadata-only card, never a plain-message send. Optional `fetch_metadata: false` builds that native card directly from the URL and host title, without invoking LinkPresentation metadata/image fetching or staging an image. The default remains `true`. This flag requires URL mode and must be a JSON boolean.
|
|
243
|
+
- `send.attachment` sends `file` or `path`, with optional `audio` / `is_audio` / `as_voice`. Pass `reply_to` (or `replyTo`, `reply_to_guid`, or `message_guid`) to reply to an existing message. An optional non-negative integer `part_index` / `partIndex` selects that message's part and is invalid without a reply target.
|
|
244
|
+
- `send.multipart` sends 1–20 text parts. `parts` is a required array of objects containing a non-empty `text` string and optional `text_formatting` array. Top-level `effect` / `effect_id` and `subject` match `imsg send-multipart`. File, attachment, and mention parts are rejected before bridge dispatch.
|
|
245
|
+
- `tapback` sends or removes a reaction. Params: `message_id` or `message_guid`, plus `reaction` / `kind` / `emoji`, optional `remove`.
|
|
246
|
+
diff --git a/scripts/patch-deps.sh b/scripts/patch-deps.sh
|
|
247
|
+
index 556e58f..670cade 100755
|
|
248
|
+
--- a/scripts/patch-deps.sh
|
|
249
|
+
+++ b/scripts/patch-deps.sh
|
|
250
|
+
@@ -63,6 +63,23 @@ elif "resolvingSymlinksInPath()" not in text:
|
|
251
|
+
print(f"Error: PhoneNumberKit bundle URL list no longer contains the expected insertion point: {path}", file=sys.stderr)
|
|
252
|
+
raise SystemExit(1)
|
|
253
|
+
|
|
254
|
+
+# SwiftPM's generated Bundle.module accessor contains an absolute build path.
|
|
255
|
+
+# Release executables must use the shipped bundle, never a developer checkout.
|
|
256
|
+
+fallback = "#if SWIFT_PACKAGE\n return Bundle.module\n #else"
|
|
257
|
+
+release_fallback = """#if SWIFT_PACKAGE
|
|
258
|
+
+ #if DEBUG
|
|
259
|
+
+ return Bundle.module
|
|
260
|
+
+ #else
|
|
261
|
+
+ fatalError("PhoneNumberKit resource bundle is missing")
|
|
262
|
+
+ #endif
|
|
263
|
+
+ #else"""
|
|
264
|
+
+if fallback in text:
|
|
265
|
+
+ text = text.replace(fallback, release_fallback)
|
|
266
|
+
+ updated = True
|
|
267
|
+
+elif release_fallback not in text:
|
|
268
|
+
+ print(f"Error: PhoneNumberKit bundle fallback no longer matches the reviewed source: {path}", file=sys.stderr)
|
|
269
|
+
+ raise SystemExit(1)
|
|
270
|
+
+
|
|
271
|
+
if updated:
|
|
272
|
+
path.write_text(text)
|
|
273
|
+
PY
|
|
274
|
+
--
|
|
275
|
+
2.50.1 (Apple Git-155)
|
|
276
|
+
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"baseCommit": "25beb76c902b0acf2dd7ae392f1b0792f6813240"
|
|
7
7
|
},
|
|
8
8
|
"reviewedPatchStack": {
|
|
9
|
-
"tipCommit": "
|
|
9
|
+
"tipCommit": "520b82ab025c1d4d57333b552aa65c9ae3fdb5fd",
|
|
10
10
|
"patches": [
|
|
11
11
|
{
|
|
12
12
|
"file": "0001-fix-keep-AppleScript-send-payloads-out-of-child-argv.patch",
|
|
@@ -37,31 +37,79 @@
|
|
|
37
37
|
"Sources/imsg/RPCServer.swift",
|
|
38
38
|
"Tests/imsgTests/RPCServerTests.swift"
|
|
39
39
|
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"file": "0003-feat-rpc-add-no-fetch-rich-cards.patch",
|
|
43
|
+
"commit": "520b82ab025c1d4d57333b552aa65c9ae3fdb5fd",
|
|
44
|
+
"sha256": "c2346afca4dd0f9721c235db4f692d6a2d6dece36481e074d94b5ce78f2e019b",
|
|
45
|
+
"purpose": "Native URL cards without helper metadata/image fetching, safe exact-chat fixtures, and release-only adjacent resource lookup without a build-path fallback.",
|
|
46
|
+
"changedFiles": [
|
|
47
|
+
"Sources/imsg/RPCServer+BridgeMessageHandlers.swift",
|
|
48
|
+
"Sources/imsg/RichLinkPreparer.swift",
|
|
49
|
+
"Tests/imsgTests/RPCBridgeMessageHandlersTests.swift",
|
|
50
|
+
"Tests/imsgTests/RPCSendRichLinkValidationTests.swift",
|
|
51
|
+
"Tests/imsgTests/RPCServerTests.swift",
|
|
52
|
+
"Tests/imsgTests/RichLinkPreparerTests.swift",
|
|
53
|
+
"docs/rpc.md",
|
|
54
|
+
"scripts/patch-deps.sh"
|
|
55
|
+
]
|
|
40
56
|
}
|
|
41
57
|
]
|
|
42
58
|
},
|
|
43
59
|
"artifact": {
|
|
44
60
|
"platform": "darwin",
|
|
45
61
|
"arch": "arm64",
|
|
46
|
-
"executableSha256": "
|
|
62
|
+
"executableSha256": "46c4c73c81c7db2d516c2d467c66aff03c73de196996d646bc8afce0ea85cff6",
|
|
47
63
|
"reportedVersion": "0.14.1",
|
|
48
64
|
"build": {
|
|
49
65
|
"swift": "Apple Swift 6.3.3 (swiftlang-6.3.3.1.3 clang-2100.1.1.101)",
|
|
50
|
-
"sdk": "
|
|
66
|
+
"sdk": "MacOSX26.5.sdk",
|
|
51
67
|
"command": [
|
|
52
|
-
"env",
|
|
53
|
-
"SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX15.4.sdk",
|
|
54
|
-
"CLANG_MODULE_CACHE_PATH=<private-build-cache>",
|
|
55
|
-
"SWIFTPM_MODULECACHE_OVERRIDE=<private-build-cache>",
|
|
56
68
|
"swift",
|
|
57
69
|
"build",
|
|
70
|
+
"--jobs",
|
|
71
|
+
"4",
|
|
58
72
|
"--disable-sandbox",
|
|
73
|
+
"--cache-path",
|
|
74
|
+
".swiftpm-cache",
|
|
75
|
+
"--config-path",
|
|
76
|
+
".swiftpm-config",
|
|
77
|
+
"--security-path",
|
|
78
|
+
".swiftpm-security",
|
|
79
|
+
"--disable-automatic-resolution",
|
|
59
80
|
"-c",
|
|
60
81
|
"release",
|
|
61
82
|
"--product",
|
|
62
|
-
"imsg"
|
|
83
|
+
"imsg",
|
|
84
|
+
"-Xlinker",
|
|
85
|
+
"-S"
|
|
86
|
+
],
|
|
87
|
+
"preparation": [
|
|
88
|
+
"scripts/generate-version.sh",
|
|
89
|
+
"swift package --force-resolved-versions resolve",
|
|
90
|
+
"scripts/patch-deps.sh"
|
|
91
|
+
],
|
|
92
|
+
"linking": "Apple linker omits STABS/DWARF at link time before its default content-derived UUID and ad-hoc signature; no post-link byte rewriting.",
|
|
93
|
+
"dependencyPatches": [
|
|
94
|
+
"Pinned upstream patch-deps.sh retains PhoneNumberKit command-line/symlink bundle lookup and SQLite resource preparation.",
|
|
95
|
+
"Third reviewed patch keeps the generated Bundle.module fallback only in DEBUG; release builds require the adjacent shipped bundle and otherwise fail explicitly."
|
|
63
96
|
]
|
|
64
|
-
}
|
|
97
|
+
},
|
|
98
|
+
"executableBytes": 4525960,
|
|
99
|
+
"compression": "gzip",
|
|
100
|
+
"validation": {
|
|
101
|
+
"targetedSwiftTests": 35,
|
|
102
|
+
"signedBytesIdentical": true,
|
|
103
|
+
"strictAdHocSignatureVerification": true,
|
|
104
|
+
"userAndWorkspacePathsAbsent": true,
|
|
105
|
+
"installedLayoutVersion": "0.14.1",
|
|
106
|
+
"installedReleasePhoneNumberKitResourceParse": true,
|
|
107
|
+
"liveAccountOrSendQualification": false,
|
|
108
|
+
"releaseBuilds": 2,
|
|
109
|
+
"cleanRebuilds": 1
|
|
110
|
+
},
|
|
111
|
+
"compressedSha256": "12861bdb93779405f7cc4cb4a47fc1d6ea3bf2fc8cec5ed69f2197ce96804532",
|
|
112
|
+
"compressedBytes": 1490956
|
|
65
113
|
},
|
|
66
114
|
"reviewBoundary": {
|
|
67
115
|
"liveSendPerformed": false,
|
|
@@ -75,6 +123,32 @@
|
|
|
75
123
|
"service": "iMessage",
|
|
76
124
|
"transport": "applescript",
|
|
77
125
|
"smsFallback": false,
|
|
78
|
-
"exactRouteLookup": "chats.get(chat_id) returns one exact current chat projection and rejects an unknown row"
|
|
126
|
+
"exactRouteLookup": "chats.get(chat_id) returns one exact current chat projection and rejects an unknown row",
|
|
127
|
+
"noFetchNativeCards": "Owner automation requests send.rich fetch_metadata=false; helper metadata/image loading is bypassed while native rich-card dispatch remains. Messages/recipient network behavior is outside this helper claim.",
|
|
128
|
+
"nativeRichBridge": "Requires an already-working compatible injected bridge; upstream setup requires disabled SIP. Installation and tests change no security setting or Messages process."
|
|
129
|
+
},
|
|
130
|
+
"bundledResources": {
|
|
131
|
+
"repository": "https://github.com/marmelroy/PhoneNumberKit",
|
|
132
|
+
"version": "5.0.6",
|
|
133
|
+
"commit": "e18a029dbada1d8eb32e3f81a4eb72eba539ff75",
|
|
134
|
+
"files": [
|
|
135
|
+
{
|
|
136
|
+
"source": "Sources/PhoneNumberKit/Resources/PhoneNumberMetadata.json",
|
|
137
|
+
"installed": "PhoneNumberKit_PhoneNumberKit.bundle/Contents/Resources/PhoneNumberMetadata.json",
|
|
138
|
+
"sha256": "cbfe80ee5ee9901f46893a4d2c353d5eb513a21e62529ee5dfaa4e94b4460d83"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"source": "Sources/PhoneNumberKit/PrivacyInfo.xcprivacy",
|
|
142
|
+
"installed": "PhoneNumberKit_PhoneNumberKit.bundle/Contents/Resources/PrivacyInfo.xcprivacy",
|
|
143
|
+
"sha256": "561040f7a52952f75d02d4b6758382ff48c563d6f25c84a09f1a655f6dc60ff8"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"source": "Ghostget-generated macOS resource bundle metadata",
|
|
147
|
+
"installed": "PhoneNumberKit_PhoneNumberKit.bundle/Contents/Info.plist",
|
|
148
|
+
"sha256": "161f6c4a3ceaee9ab2ce30e33c80e605a11e196c53e9791f87341e01bf80d7e9"
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
"notices": "src/assets/messaging-runtime/NOTICE.txt",
|
|
152
|
+
"installActivatesProvider": false
|
|
79
153
|
}
|
|
80
154
|
}
|
|
@@ -189,7 +189,7 @@ function linkedinArticleDraftV2Dispatches(
|
|
|
189
189
|
|
|
190
190
|
const currentOperations = webSessionContractOperations(
|
|
191
191
|
Object.values(linkedinContracts),
|
|
192
|
-
"
|
|
192
|
+
"e7b252e0332557f3e8cc764800ada4972ca093d9974e2b876a904588523f441c",
|
|
193
193
|
{
|
|
194
194
|
"posts.publish": [2],
|
|
195
195
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { automationOperationDefinitions } from "../../messaging-automation-descriptors";
|
|
1
2
|
import {
|
|
2
3
|
defineProviderPlugin,
|
|
3
4
|
lazyWebSessionRuntime,
|
|
@@ -26,6 +27,10 @@ export const whatsappLinkedDevicePlugin = defineProviderPlugin({
|
|
|
26
27
|
displayName: "WhatsApp Linked Device",
|
|
27
28
|
sourceKind: "built-in",
|
|
28
29
|
implementationSources: webImplementationSources(import.meta.url, [
|
|
30
|
+
["native/wacli-darwin-arm64.gz", "../../assets/messaging-runtime/wacli-darwin-arm64.gz"],
|
|
31
|
+
["native/NOTICE.txt", "../../assets/messaging-runtime/NOTICE.txt"],
|
|
32
|
+
["vendor/private-messaging.patch", "./vendor/0001-ghostget-private-messaging.patch"],
|
|
33
|
+
["vendor/provenance.json", "./vendor/provenance.json"],
|
|
29
34
|
["kernel/auth.ts", "../../auth.ts"],
|
|
30
35
|
["kernel/state-helper.bunfig.toml", "../../state-helper.bunfig.toml"],
|
|
31
36
|
["kernel/storage.ts", "../../storage.ts"],
|
|
@@ -48,7 +53,7 @@ export const whatsappLinkedDevicePlugin = defineProviderPlugin({
|
|
|
48
53
|
origin: "https://web.whatsapp.com",
|
|
49
54
|
protectedHostnameFamilies: ["whatsapp.com"],
|
|
50
55
|
authKinds: linkedDeviceAuthKinds,
|
|
51
|
-
operations: webSessionContractOperations(
|
|
56
|
+
operations: [...webSessionContractOperations(
|
|
52
57
|
Object.values(whatsappContracts),
|
|
53
58
|
"a5c32c0b7c210fd98aee086455b2fde1151c7cf1806fd2e0f6c3e269d10ac13f",
|
|
54
59
|
{ "contacts.list": [1] },
|
|
@@ -68,7 +73,7 @@ export const whatsappLinkedDevicePlugin = defineProviderPlugin({
|
|
|
68
73
|
materialize: materializeWhatsAppMessagingRead,
|
|
69
74
|
},
|
|
70
75
|
},
|
|
71
|
-
),
|
|
76
|
+
), ...automationOperationDefinitions("whatsapp")],
|
|
72
77
|
subject: {
|
|
73
78
|
format: "whatsapp:pn:<phone> or whatsapp:lid:<linked-id>",
|
|
74
79
|
matches: (value) => /^whatsapp:(?:pn:[0-9]{5,20}|lid:[0-9]{5,32})$/u.test(value),
|