bajaclaw 0.17.0 → 0.17.2

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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ██╔══██╗██╔══██║██ ██║██╔══██║ ██║ ██║ ██╔══██║██║███╗██║
8
8
  ██████╔╝██║ ██║╚█████╔╝██║ ██║ ╚██████╗███████╗██║ ██║╚███╔███╔╝
9
9
  ╚═════╝ ╚═╝ ╚═╝ ╚════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚══╝╚══╝
10
- autonomous agents on your terms · MIT · v0.17.0
10
+ autonomous agents on your terms · MIT · v0.17.2
11
11
  ```
12
12
 
13
13
  ## What BajaClaw is
@@ -17,7 +17,7 @@
17
17
  // attachments. Inbound attachments are noted in the body as
18
18
  // `[attachment]` markers; agents still see them and can ask the user
19
19
  // to forward through another channel.
20
- import { spawnSync } from "node:child_process";
20
+ import { spawnSync, spawn } from "node:child_process";
21
21
  import { existsSync, readFileSync, writeFileSync, renameSync, openSync, closeSync, statSync } from "node:fs";
22
22
  import { homedir } from "node:os";
23
23
  import { dirname, join } from "node:path";
@@ -168,6 +168,65 @@ export function sendTypingIndicator(handle, typing, log) {
168
168
  log?.warn("gateway.imessage.typing-fail", { verb, handle: norm, status: r.status, err: err.slice(0, 200) });
169
169
  return { ok: false, exitCode: r.status ?? -1, error: err };
170
170
  }
171
+ function startTypingHelperProcess(log) {
172
+ if (process.platform !== "darwin")
173
+ return null;
174
+ const helperPath = resolveTypingHelperPath();
175
+ if (!helperPath)
176
+ return null;
177
+ let proc = null;
178
+ let helperStopped = false;
179
+ let retried = false;
180
+ function launchHelper() {
181
+ // helperPath is checked non-null at the top of startTypingHelperProcess.
182
+ const child = spawn(helperPath, ["serve"], { stdio: ["pipe", "pipe", "pipe"] });
183
+ proc = child;
184
+ child.stderr?.on("data", (d) => {
185
+ const msg = d.toString().trim();
186
+ if (msg)
187
+ log.warn("gateway.imessage.helper-stderr", { msg: msg.slice(0, 200) });
188
+ });
189
+ child.stdout?.on("data", (d) => {
190
+ const lines = d.toString().trim().split(/\r?\n/);
191
+ for (const line of lines) {
192
+ if (line.startsWith("err ")) {
193
+ log.warn("gateway.imessage.helper-err", { msg: line.slice(4, 200) });
194
+ }
195
+ }
196
+ });
197
+ child.on("error", (e) => {
198
+ log.warn("gateway.imessage.helper-spawn-error", { error: e.message });
199
+ });
200
+ child.on("exit", (code) => {
201
+ if (!helperStopped && !retried) {
202
+ retried = true;
203
+ log.info("gateway.imessage.helper-respawn", { code });
204
+ launchHelper();
205
+ }
206
+ });
207
+ }
208
+ launchHelper();
209
+ return {
210
+ send: (cmd) => {
211
+ try {
212
+ proc?.stdin?.write(cmd + "\n");
213
+ }
214
+ catch { /* typing is best-effort */ }
215
+ },
216
+ stop: () => {
217
+ helperStopped = true;
218
+ try {
219
+ proc?.stdin?.write("quit\n");
220
+ }
221
+ catch { /* ignore */ }
222
+ // Give it 1s to exit cleanly, then SIGTERM.
223
+ setTimeout(() => { try {
224
+ proc?.kill("SIGTERM");
225
+ }
226
+ catch { /* ignore */ } }, 1000);
227
+ },
228
+ };
229
+ }
171
230
  // The inbound query. ROWID is monotonic and indexed, so "everything
172
231
  // after the last one we saw" is an O(log n) lookup plus a sequential
173
232
  // scan over only the new rows. Joins to handle.id for the sender
@@ -279,6 +338,7 @@ export async function startIMessage(profile, config, log, deps) {
279
338
  }
280
339
  const allowlist = (config.allowlist ?? []).map((h) => normalizeHandle(String(h)));
281
340
  const useAllowlist = allowlist.length > 0;
341
+ const typingHelper = startTypingHelperProcess(log);
282
342
  let stopped = false;
283
343
  let timer = null;
284
344
  const tick = async () => {
@@ -324,44 +384,33 @@ export async function startIMessage(profile, config, log, deps) {
324
384
  await sendViaAppleScript(String(chatId), text, log);
325
385
  },
326
386
  startTyping: (chatId) => {
327
- // Native typing helper (helpers/bajaclaw-imessage-helper) speaks
328
- // to IMCore directly to set the "..." indicator. AppleScript
329
- // can't do this; our Obj-C helper calls setLocalUserIsTyping:
330
- // on IMChat via the private framework.
331
- //
332
- // IMCore's typing flag auto-expires after ~60s on the receiver
333
- // side (matches Messages.app's own heartbeat). We refresh every
334
- // 30s to keep it lit until the cycle finishes. Each refresh is
335
- // a sub-100ms spawn; cost is negligible.
336
- //
337
- // Graceful degradation: if the helper isn't installed or fails
338
- // (missing TCC permission, no existing chat, Apple changed the
339
- // private API), we log once and proceed silently - the adapter
340
- // never blocks a reply because of a typing failure.
341
- const handle = String(chatId);
342
- const first = sendTypingIndicator(handle, true, log);
343
- if (!first.ok) {
344
- // Return a no-op stop fn; caller side doesn't care about the
345
- // distinction as long as the method shape is preserved.
387
+ if (!typingHelper)
346
388
  return () => { };
347
- }
348
- const timer = setInterval(() => {
349
- const r = sendTypingIndicator(handle, true, log);
350
- // If a refresh fails, stop trying - something changed
351
- // (chat deleted, permission revoked). Next cycle will retry.
352
- if (!r.ok)
353
- clearInterval(timer);
354
- }, 30_000);
389
+ const handle = normalizeHandle(String(chatId));
390
+ let indicatorStopped = false;
391
+ const sendStart = () => typingHelper.send(`start ${handle}`);
392
+ sendStart();
393
+ // iMessage "..." indicator stays on until the sender replies or
394
+ // ~60s elapse. Refresh every 30s to keep it alive across long
395
+ // cycles. Also retry at 10s in case the first call raced against
396
+ // the helper's registry population (imagent may take a few seconds
397
+ // to push chat state after the listener is registered).
398
+ const initialRetry = setTimeout(() => { if (!indicatorStopped)
399
+ sendStart(); }, 10_000);
400
+ const refreshTimer = setInterval(() => { if (!indicatorStopped)
401
+ sendStart(); }, 30_000);
355
402
  return () => {
356
- clearInterval(timer);
357
- // Fire-and-forget stop; don't block reply routing on it.
358
- sendTypingIndicator(handle, false, log);
403
+ indicatorStopped = true;
404
+ clearTimeout(initialRetry);
405
+ clearInterval(refreshTimer);
406
+ typingHelper.send(`stop ${handle}`);
359
407
  };
360
408
  },
361
409
  stop: async () => {
362
410
  stopped = true;
363
411
  if (timer)
364
412
  clearTimeout(timer);
413
+ typingHelper?.stop();
365
414
  try {
366
415
  db.close();
367
416
  }
@@ -1 +1 @@
1
- {"version":3,"file":"imessage.js","sourceRoot":"","sources":["../../src/channels/imessage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"imessage.js","sourceRoot":"","sources":["../../src/channels/imessage.ts"],"names":[],"mappings":"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"}
Binary file
@@ -1,76 +1,399 @@
1
1
  // bajaclaw-imessage-helper
2
2
  // ------------------------
3
- // Narrow Objective-C helper that calls Apple's private IMCore framework
4
- // to toggle the "typing..." indicator on an iMessage thread. AppleScript
5
- // doesn't expose setLocalUserIsTyping: and there's no public path to it;
6
- // this binary dlopens IMCore, looks up IMChatRegistry, finds the chat,
7
- // and invokes the selector via NSInvocation.
3
+ // Long-running Obj-C helper that keeps a live connection to Apple's
4
+ // imagent via IMDaemonController, maintains the IMChatRegistry cache
5
+ // in-process, and toggles the "..." typing indicator on iMessage
6
+ // threads via the private IMCore framework.
8
7
  //
9
- // Usage:
10
- // bajaclaw-imessage-helper start <handle-or-guid>
11
- // bajaclaw-imessage-helper stop <handle-or-guid>
8
+ // Why long-running: imagent pushes chat state asynchronously to any
9
+ // process that has registered as an IMDaemonListener. A short-lived
10
+ // one-shot helper exits before that state arrives, so the registry
11
+ // always looks empty. Keeping one helper per daemon lifetime lets us
12
+ // amortize the startup cost and always have a populated registry.
12
13
  //
13
- // Handle can be a phone number (E.164) or email. GUID can be the full
14
- // chat guid (e.g. "iMessage;-;+15551234567") - we try both forms.
14
+ // Protocol: the helper reads newline-delimited commands from stdin
15
+ // and writes newline-delimited responses to stdout.
15
16
  //
16
- // Exit codes:
17
- // 0 typing toggled
18
- // 1 bad args
19
- // 2 IMCore failed to load (framework path changed or TCC denied)
20
- // 3 IMChatRegistry class not found (IMCore is loaded but symbol missing)
21
- // 4 no chat found for the given handle (user must text first)
22
- // 5 setLocalUserIsTyping: selector missing on IMChat
23
- // 6 invocation failed (rare; caught and logged)
17
+ // start <handle-or-guid> -> "ok" | "err <reason>"
18
+ // stop <handle-or-guid> -> "ok" | "err <reason>"
19
+ // ping -> "ok"
20
+ // quit -> exits 0
24
21
  //
25
- // Graceful-failure contract: any non-zero exit from this binary is
26
- // treated as "typing unavailable" by the caller (src/channels/imessage.ts).
27
- // The iMessage adapter never fails a send because of typing; it just
28
- // skips the indicator and proceeds with the reply.
22
+ // Arg-style legacy mode is also supported so existing callers and
23
+ // unit tests keep working: invoking with `<verb> <handle>` as argv
24
+ // performs a single toggle and exits. In that mode we wait up to
25
+ // 5s for the registry to populate (shorter than the long-running
26
+ // path would need, because a single ask can give up).
27
+ //
28
+ // Graceful-failure contract: any non-zero exit or "err <reason>"
29
+ // line means "typing unavailable for this call". The Node adapter
30
+ // never fails a send because of typing.
29
31
  #import <Foundation/Foundation.h>
30
32
  #import <dlfcn.h>
31
33
 
32
34
  // Reverse-engineered private class declarations. Apple does not ship
33
- // these headers; the symbols have been stable across macOS 10.14-15.
34
- // If Apple renames any of these on a future macOS, this helper will
35
- // fail with a clear exit code and the caller will skip typing.
35
+ // these headers; symbols have been stable across macOS 10.14-15.
36
+ @interface IMDaemonController : NSObject
37
+ + (instancetype)sharedInstance;
38
+ - (BOOL)connectToDaemon;
39
+ - (BOOL)blockUntilConnected;
40
+ - (id)listener;
41
+ @end
42
+
36
43
  @interface IMChatRegistry : NSObject
37
44
  + (instancetype)sharedInstance;
38
45
  - (id)existingChatWithChatIdentifier:(NSString *)identifier;
39
- - (id)existingChatForIMHandleID:(NSString *)handle;
46
+ - (id)existingChatWithGUID:(NSString *)guid;
47
+ - (id)_existingChatWithGUID:(NSString *)guid;
48
+ - (NSArray *)allExistingChats;
40
49
  @end
41
50
 
42
51
  @interface IMChat : NSObject
43
52
  - (void)setLocalUserIsTyping:(BOOL)typing;
44
53
  - (NSString *)guid;
54
+ - (NSString *)chatIdentifier;
55
+ @end
56
+
57
+ // Listener class. Registered with imagent so it pushes chat state
58
+ // to this process. Without this registration, IMChatRegistry stays
59
+ // empty even after a successful connectToDaemon + blockUntilConnected.
60
+ //
61
+ // Key insight from BlueBubbles: imagent only delivers chat state to
62
+ // processes registered via [[daemon listener] addHandler:] with an
63
+ // appropriate capabilities bitmask.
64
+ @interface BajaCrawListener : NSObject
45
65
  @end
46
66
 
47
67
  static NSString * const IMCORE_PATH = @"/System/Library/PrivateFrameworks/IMCore.framework/IMCore";
68
+ static BOOL gVerbose = NO;
69
+ // Set to YES by listener callbacks once imagent has pushed at least
70
+ // the initial chat state. Used as an early-exit signal in waitForChats.
71
+ static BOOL gReady = NO;
72
+ // Kept alive for process lifetime; ARC retains through this global.
73
+ static id gListenerInstance = nil;
74
+
75
+ static void logDebug(NSString *fmt, ...) {
76
+ if (!gVerbose) return;
77
+ va_list args;
78
+ va_start(args, fmt);
79
+ NSString *s = [[NSString alloc] initWithFormat:fmt arguments:args];
80
+ va_end(args);
81
+ fprintf(stderr, "DEBUG: %s\n", [s UTF8String]);
82
+ }
83
+
84
+ @implementation BajaCrawListener
85
+
86
+ // imagent calls setupComplete: / setupCompleted: when the connection
87
+ // handshake finishes. Either name can appear depending on macOS version.
88
+ - (void)setupComplete:(id)arg {
89
+ logDebug(@"setupComplete:");
90
+ gReady = YES;
91
+ }
92
+ - (void)setupCompleted:(id)arg {
93
+ logDebug(@"setupCompleted:");
94
+ gReady = YES;
95
+ }
96
+ - (void)didConnectToIMAgent:(id)arg {
97
+ logDebug(@"didConnectToIMAgent:");
98
+ gReady = YES;
99
+ }
100
+
101
+ // imagent calls these when chat state becomes available.
102
+ - (void)chatLoaded:(id)arg1 chatProperties:(id)arg2 {
103
+ logDebug(@"chatLoaded:chatProperties:");
104
+ gReady = YES;
105
+ }
106
+ - (void)chatsDidChange:(id)arg1 {
107
+ logDebug(@"chatsDidChange:");
108
+ gReady = YES;
109
+ }
110
+ - (void)chatsLoaded:(id)arg1 {
111
+ logDebug(@"chatsLoaded:");
112
+ gReady = YES;
113
+ }
114
+
115
+ // No-op stubs for other common imagent callbacks.
116
+ - (void)messageReceived:(id)arg1 { }
117
+ - (void)account:(id)arg1 updatedSettings:(id)arg2 { }
118
+ - (void)account:(id)arg1 status:(id)arg2 { }
119
+ - (void)account:(id)arg1 loginStatusChanged:(id)arg2 { }
120
+ - (void)didDisconnectFromIMAgent:(id)arg1 { }
121
+
122
+ // imagent queries capabilities to decide which events to push.
123
+ // Return all bits so we receive chat list and setup events.
124
+ - (unsigned long long)capabilities {
125
+ return 0xFFFFFFFFFFFFFFFFULL;
126
+ }
127
+
128
+ // Safe fallback: imagent sends many selectors we haven't declared.
129
+ // Without methodSignatureForSelector: + forwardInvocation:, any
130
+ // unknown selector would crash with "unrecognized selector".
131
+ - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
132
+ NSMethodSignature *sig = [super methodSignatureForSelector:sel];
133
+ if (!sig) {
134
+ // Generic void(id) signature covers the vast majority of
135
+ // imagent callbacks that deliver a single object argument.
136
+ sig = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
137
+ }
138
+ return sig;
139
+ }
140
+ - (void)forwardInvocation:(NSInvocation *)inv {
141
+ NSString *selName = NSStringFromSelector([inv selector]);
142
+ logDebug(@"unhandled imagent callback: %@", selName);
143
+ // Treat any "chat"/"setup"/"chats" prefixed callback as a ready
144
+ // signal - imagent may rename these methods across macOS versions.
145
+ if ([selName hasPrefix:@"chat"]
146
+ || [selName hasPrefix:@"setup"]
147
+ || [selName hasPrefix:@"chats"]
148
+ || [selName hasPrefix:@"didConnect"]) {
149
+ gReady = YES;
150
+ }
151
+ }
152
+
153
+ @end
154
+
155
+ static BOOL loadIMCore(void) {
156
+ void *h = dlopen([IMCORE_PATH UTF8String], RTLD_NOW);
157
+ if (!h) {
158
+ fprintf(stderr, "ERROR: failed to load IMCore: %s\n", dlerror());
159
+ return NO;
160
+ }
161
+ return YES;
162
+ }
163
+
164
+ static BOOL connectDaemon(void) {
165
+ Class daemonClass = NSClassFromString(@"IMDaemonController");
166
+ if (!daemonClass) return NO;
167
+ id daemon = [daemonClass performSelector:@selector(sharedInstance)];
168
+ if (!daemon) return NO;
169
+
170
+ // Create the listener before connecting so it is ready when imagent
171
+ // delivers the initial connection callbacks.
172
+ gListenerInstance = [[BajaCrawListener alloc] init];
173
+
174
+ if ([daemon respondsToSelector:@selector(connectToDaemon)]) {
175
+ [daemon performSelector:@selector(connectToDaemon)];
176
+ }
177
+ if ([daemon respondsToSelector:@selector(blockUntilConnected)]) {
178
+ [daemon performSelector:@selector(blockUntilConnected)];
179
+ }
180
+
181
+ // Register as a listener. imagent will begin pushing chat state
182
+ // once the handler is added with appropriate capabilities.
183
+ // Primary path: [[daemon listener] addHandler:]
184
+ id daemonListener = [daemon respondsToSelector:@selector(listener)]
185
+ ? [daemon performSelector:@selector(listener)] : nil;
186
+
187
+ SEL addHandlerSel = NSSelectorFromString(@"addHandler:");
188
+ if (daemonListener && [daemonListener respondsToSelector:addHandlerSel]) {
189
+ // Dynamic selector: ARC warns about potential leak but gListenerInstance
190
+ // is a strong global so there is no actual leak.
191
+ #pragma clang diagnostic push
192
+ #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
193
+ [daemonListener performSelector:addHandlerSel withObject:gListenerInstance];
194
+ #pragma clang diagnostic pop
195
+ logDebug(@"listener registered via [daemonListener addHandler:]");
196
+ } else {
197
+ // Fallback: some macOS versions expose addListener: on the daemon itself.
198
+ SEL addListenerSel = NSSelectorFromString(@"addListener:");
199
+ if ([daemon respondsToSelector:addListenerSel]) {
200
+ #pragma clang diagnostic push
201
+ #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
202
+ [daemon performSelector:addListenerSel withObject:gListenerInstance];
203
+ #pragma clang diagnostic pop
204
+ logDebug(@"listener registered via [daemon addListener:]");
205
+ } else {
206
+ logDebug(@"WARNING: no listener registration API found - chat list may not load");
207
+ }
208
+ }
209
+
210
+ return YES;
211
+ }
48
212
 
49
- static id findChat(id registry, NSString *target) {
50
- // Try the most specific form first - a full chat identifier like
51
- // "iMessage;-;+15551234567". If that fails, try the bare handle
52
- // (which may work against some older registry lookup paths).
53
- NSString *identifier = [NSString stringWithFormat:@"iMessage;-;%@", target];
54
- id chat = [registry performSelector:@selector(existingChatWithChatIdentifier:) withObject:identifier];
55
- if (chat) return chat;
56
-
57
- chat = [registry performSelector:@selector(existingChatWithChatIdentifier:) withObject:target];
58
- if (chat) return chat;
59
-
60
- // Last resort: lookup by handle directly (not all macOS versions
61
- // expose this selector; guarded by respondsToSelector:).
62
- SEL handleSel = @selector(existingChatForIMHandleID:);
63
- if ([registry respondsToSelector:handleSel]) {
64
- chat = [registry performSelector:handleSel withObject:target];
213
+ // Wait up to `seconds` for the registry to report at least one chat.
214
+ // Now also watches gReady (set by listener callbacks) as an early exit.
215
+ // Returns the chat count when it gives up (may be 0 on timeout).
216
+ static NSUInteger waitForChats(NSTimeInterval seconds) {
217
+ NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:seconds];
218
+ NSUInteger last = 0;
219
+ while ([[NSDate date] compare:deadline] == NSOrderedAscending) {
220
+ @autoreleasepool {
221
+ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
222
+ Class rc = NSClassFromString(@"IMChatRegistry");
223
+ id reg = [rc performSelector:@selector(sharedInstance)];
224
+ id chats = [reg performSelector:@selector(allExistingChats)];
225
+ if ([chats isKindOfClass:[NSArray class]]) {
226
+ last = [(NSArray *)chats count];
227
+ if (last > 0) return last;
228
+ }
229
+ // gReady means the listener received a chat-state callback.
230
+ // Give the registry one extra tick to settle, then return
231
+ // whatever we have (even if count is still 0 - some macOS
232
+ // versions populate via chatIdentifier lookup only).
233
+ if (gReady) {
234
+ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.3]];
235
+ id chats2 = [reg performSelector:@selector(allExistingChats)];
236
+ if ([chats2 isKindOfClass:[NSArray class]]) {
237
+ last = [(NSArray *)chats2 count];
238
+ }
239
+ return last;
240
+ }
241
+ }
242
+ }
243
+ return last;
244
+ }
245
+
246
+ static id findChat(NSString *target) {
247
+ Class rc = NSClassFromString(@"IMChatRegistry");
248
+ id registry = [rc performSelector:@selector(sharedInstance)];
249
+
250
+ NSArray<NSString *> *guids = @[
251
+ [NSString stringWithFormat:@"any;-;%@", target],
252
+ [NSString stringWithFormat:@"iMessage;-;%@", target],
253
+ [NSString stringWithFormat:@"SMS;-;%@", target],
254
+ ];
255
+
256
+ // Strategy 1: enumerate allExistingChats and match by
257
+ // chatIdentifier or guid tail. Works once imagent has pushed state.
258
+ if ([registry respondsToSelector:@selector(allExistingChats)]) {
259
+ id allChats = [registry performSelector:@selector(allExistingChats)];
260
+ if ([allChats isKindOfClass:[NSArray class]]) {
261
+ logDebug(@"allExistingChats -> %lu chats", (unsigned long)[(NSArray *)allChats count]);
262
+ for (id chat in (NSArray *)allChats) {
263
+ NSString *cid = [chat respondsToSelector:@selector(chatIdentifier)]
264
+ ? [chat performSelector:@selector(chatIdentifier)] : nil;
265
+ NSString *cguid = [chat respondsToSelector:@selector(guid)]
266
+ ? [chat performSelector:@selector(guid)] : nil;
267
+ if ([cid isEqualToString:target]) return chat;
268
+ if (cguid) {
269
+ for (NSString *g in guids) if ([cguid isEqualToString:g]) return chat;
270
+ if ([cguid hasSuffix:[NSString stringWithFormat:@";-;%@", target]]) return chat;
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+ // Strategy 2: direct GUID lookup on the registry.
277
+ for (NSString *guid in guids) {
278
+ id chat = [registry performSelector:@selector(existingChatWithChatIdentifier:) withObject:guid];
65
279
  if (chat) return chat;
280
+ if ([registry respondsToSelector:@selector(_existingChatWithGUID:)]) {
281
+ chat = [registry performSelector:@selector(_existingChatWithGUID:) withObject:guid];
282
+ if (chat) return chat;
283
+ }
284
+ }
285
+
286
+ // Strategy 3: bare handle.
287
+ return [registry performSelector:@selector(existingChatWithChatIdentifier:) withObject:target];
288
+ }
289
+
290
+ // Perform typing toggle; return nil on success or an error string.
291
+ static NSString *toggleTyping(NSString *target, BOOL typing) {
292
+ id chat = findChat(target);
293
+ if (!chat) return @"no existing chat (user must text first)";
294
+ SEL sel = @selector(setLocalUserIsTyping:);
295
+ NSMethodSignature *sig = [chat methodSignatureForSelector:sel];
296
+ if (!sig) return @"setLocalUserIsTyping: not available";
297
+ NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig];
298
+ [inv setTarget:chat];
299
+ [inv setSelector:sel];
300
+ [inv setArgument:&typing atIndex:2];
301
+ @try {
302
+ [inv invoke];
303
+ } @catch (NSException *e) {
304
+ return [NSString stringWithFormat:@"invoke threw: %@", [e reason]];
66
305
  }
67
306
  return nil;
68
307
  }
69
308
 
309
+ // Long-running stdin loop. Reads commands on a GCD background thread
310
+ // so the main thread can keep spinning NSRunLoop, which is required
311
+ // for imagent to deliver callbacks to gListenerInstance.
312
+ //
313
+ // Commands are dispatched back to the main thread for toggleTyping
314
+ // because IMCore is not thread-safe.
315
+ static int runDaemonLoop(void) {
316
+ logDebug(@"entering daemon loop");
317
+ setvbuf(stdout, NULL, _IOLBF, 0);
318
+
319
+ __block volatile BOOL done = NO;
320
+
321
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
322
+ char *buf = NULL;
323
+ size_t bufSize = 0;
324
+ ssize_t len;
325
+ while (!done && (len = getline(&buf, &bufSize, stdin)) != -1) {
326
+ @autoreleasepool {
327
+ while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r')) { buf[--len] = '\0'; }
328
+ if (len == 0) continue;
329
+ NSString *line = [NSString stringWithUTF8String:buf];
330
+ NSArray<NSString *> *parts = [line componentsSeparatedByString:@" "];
331
+ NSString *cmd = parts.count > 0 ? parts[0] : @"";
332
+ NSString *arg = parts.count > 1
333
+ ? [[parts subarrayWithRange:NSMakeRange(1, parts.count - 1)] componentsJoinedByString:@" "]
334
+ : @"";
335
+
336
+ if ([cmd isEqualToString:@"ping"]) {
337
+ printf("ok\n");
338
+ } else if ([cmd isEqualToString:@"quit"]) {
339
+ printf("ok\n");
340
+ done = YES;
341
+ break;
342
+ } else if ([cmd isEqualToString:@"start"] || [cmd isEqualToString:@"stop"]) {
343
+ BOOL typing = [cmd isEqualToString:@"start"];
344
+ __block NSString *err = nil;
345
+ // Dispatch to main thread: IMCore callbacks and toggleTyping
346
+ // must run on the same thread as the runloop.
347
+ dispatch_sync(dispatch_get_main_queue(), ^{
348
+ err = toggleTyping(arg, typing);
349
+ });
350
+ if (err) {
351
+ printf("err %s\n", [err UTF8String]);
352
+ } else {
353
+ printf("ok\n");
354
+ }
355
+ } else {
356
+ printf("err unknown command\n");
357
+ }
358
+ }
359
+ }
360
+ free(buf);
361
+ done = YES;
362
+ dispatch_async(dispatch_get_main_queue(), ^{
363
+ CFRunLoopStop(CFRunLoopGetMain());
364
+ });
365
+ });
366
+
367
+ // Spin the main runloop indefinitely. This is what keeps imagent
368
+ // able to fire callbacks on gListenerInstance. Without this, the
369
+ // listener is registered but never invoked.
370
+ while (!done) {
371
+ @autoreleasepool {
372
+ [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
373
+ }
374
+ }
375
+ return 0;
376
+ }
377
+
70
378
  int main(int argc, char *argv[]) {
71
379
  @autoreleasepool {
380
+ gVerbose = getenv("BAJACLAW_HELPER_DEBUG") != NULL;
381
+
382
+ if (!loadIMCore()) return 2;
383
+ if (!connectDaemon()) {
384
+ fprintf(stderr, "ERROR: IMDaemonController not available\n");
385
+ return 3;
386
+ }
387
+
388
+ // Two modes:
389
+ // argv form (legacy): helper <start|stop> <handle>
390
+ // daemon form: helper serve (reads stdin)
391
+ if (argc >= 2 && strcmp(argv[1], "serve") == 0) {
392
+ return runDaemonLoop();
393
+ }
394
+
72
395
  if (argc < 3) {
73
- fprintf(stderr, "usage: %s <start|stop> <handle-or-guid>\n", argv[0]);
396
+ fprintf(stderr, "usage: %s <start|stop|serve> [handle]\n", argv[0]);
74
397
  return 1;
75
398
  }
76
399
 
@@ -79,57 +402,23 @@ int main(int argc, char *argv[]) {
79
402
  if (strcmp(cmd, "start") == 0) typing = YES;
80
403
  else if (strcmp(cmd, "stop") == 0) typing = NO;
81
404
  else {
82
- fprintf(stderr, "usage: %s <start|stop> <handle-or-guid>\n", argv[0]);
405
+ fprintf(stderr, "usage: %s <start|stop|serve> [handle]\n", argv[0]);
83
406
  return 1;
84
407
  }
85
408
 
86
409
  NSString *target = [NSString stringWithUTF8String:argv[2]];
87
410
 
88
- // dlopen the private framework. Without this, NSClassFromString
89
- // won't find IMChatRegistry because the framework isn't loaded
90
- // by default in a vanilla Foundation process.
91
- void *h = dlopen([IMCORE_PATH UTF8String], RTLD_NOW);
92
- if (!h) {
93
- fprintf(stderr, "ERROR: failed to load IMCore: %s\n", dlerror());
94
- return 2;
95
- }
96
-
97
- Class regClass = NSClassFromString(@"IMChatRegistry");
98
- if (!regClass) {
99
- fprintf(stderr, "ERROR: IMChatRegistry class not found (IMCore loaded but symbol missing)\n");
100
- return 3;
101
- }
102
-
103
- id registry = [regClass performSelector:@selector(sharedInstance)];
104
- if (!registry) {
105
- fprintf(stderr, "ERROR: [IMChatRegistry sharedInstance] returned nil\n");
106
- return 3;
107
- }
411
+ // One-shot mode: wait up to 5s for registry. The listener registered
412
+ // in connectDaemon() will receive callbacks while the runloop spins
413
+ // inside waitForChats(), which now exits early when gReady is set.
414
+ waitForChats(5.0);
108
415
 
109
- id chat = findChat(registry, target);
110
- if (!chat) {
111
- fprintf(stderr, "ERROR: no existing chat for '%s' - user must text first\n", argv[2]);
416
+ NSString *err = toggleTyping(target, typing);
417
+ if (err) {
418
+ fprintf(stderr, "ERROR: %s\n", [err UTF8String]);
112
419
  return 4;
113
420
  }
114
421
 
115
- SEL sel = @selector(setLocalUserIsTyping:);
116
- NSMethodSignature *sig = [chat methodSignatureForSelector:sel];
117
- if (!sig) {
118
- fprintf(stderr, "ERROR: setLocalUserIsTyping: not available on IMChat\n");
119
- return 5;
120
- }
121
-
122
- NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig];
123
- [inv setTarget:chat];
124
- [inv setSelector:sel];
125
- [inv setArgument:&typing atIndex:2];
126
- @try {
127
- [inv invoke];
128
- } @catch (NSException *e) {
129
- fprintf(stderr, "ERROR: invoke threw: %s\n", [[e reason] UTF8String] ?: "unknown");
130
- return 6;
131
- }
132
-
133
422
  fprintf(stdout, "ok\n");
134
423
  return 0;
135
424
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bajaclaw",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "description": "BajaClaw - autonomous agents on your terms",
5
5
  "type": "module",
6
6
  "bajaclaw": {