@naarang/ccc 1.2.0-beta.9 → 1.2.0
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 +5 -0
- package/dist/claude/manager.js +1 -1
- package/dist/claude/project-setup.js +1 -1
- package/dist/claude/session-manager.js +1 -1
- package/dist/claude/session-message-parser.js +1 -1
- package/dist/claude/session.js +1 -1
- package/dist/claude/stream-parser.js +1 -1
- package/dist/expo/client.js +1 -0
- package/dist/hooks/permissions_hook.js +95 -26
- package/dist/index.js +1 -1
- package/dist/mdns/service.js +1 -1
- package/dist/mqtt/client.js +1 -1
- package/dist/mqtt-broker.js +1 -1
- package/dist/ngrok/manager.js +1 -1
- package/dist/notifications/handlers.js +1 -1
- package/dist/notifications/index.js +1 -1
- package/dist/notifications/manager.js +1 -1
- package/dist/notifications/preferences-manager.js +1 -1
- package/dist/notifications/preferences-storage.js +1 -1
- package/dist/notifications/receipt-checker.js +1 -0
- package/dist/notifications/sender.js +1 -1
- package/dist/notifications/storage.js +1 -1
- package/dist/notifications/types.js +1 -1
- package/dist/proxy/router.js +1 -1
- package/dist/qr/generator.js +1 -1
- package/dist/terminal/server.js +1 -1
- package/dist/types/index.js +1 -1
- package/dist/utils/auto-update.js +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/utils/sentry_instrument.js +1 -0
- package/dist/utils/version.js +1 -1
- package/package.json +4 -2
- package/dist/firebase/admin.js +0 -1
|
@@ -326,10 +326,13 @@ async function requestPermission(hookInput, projectId) {
|
|
|
326
326
|
const client = mqtt.connect(connectUrl, connectOptions);
|
|
327
327
|
let resolved = false;
|
|
328
328
|
let timeoutHandle = null;
|
|
329
|
+
let ackTimeoutHandle = null;
|
|
330
|
+
let ackReceived = false;
|
|
329
331
|
|
|
330
332
|
// Topics for communication
|
|
331
333
|
const requestTopic = `permissions/${projectId}/request`;
|
|
332
334
|
const responseTopic = `permissions/${projectId}/response`;
|
|
335
|
+
const ackTopic = `permissions/${projectId}/ack`;
|
|
333
336
|
|
|
334
337
|
/**
|
|
335
338
|
* Cleanup and resolve/reject helper
|
|
@@ -342,6 +345,10 @@ async function requestPermission(hookInput, projectId) {
|
|
|
342
345
|
clearTimeout(timeoutHandle);
|
|
343
346
|
}
|
|
344
347
|
|
|
348
|
+
if (ackTimeoutHandle) {
|
|
349
|
+
clearTimeout(ackTimeoutHandle);
|
|
350
|
+
}
|
|
351
|
+
|
|
345
352
|
// Clean disconnect
|
|
346
353
|
client.end(true, {}, () => {
|
|
347
354
|
callback();
|
|
@@ -363,46 +370,108 @@ async function requestPermission(hookInput, projectId) {
|
|
|
363
370
|
client.on('connect', () => {
|
|
364
371
|
log('Connected to MQTT broker');
|
|
365
372
|
|
|
366
|
-
// Subscribe to
|
|
367
|
-
client.subscribe(
|
|
373
|
+
// Subscribe to ACK topic first
|
|
374
|
+
client.subscribe(ackTopic, { qos: MQTT_CONFIG.qos }, (err) => {
|
|
368
375
|
if (err) {
|
|
369
|
-
log('Failed to subscribe to
|
|
376
|
+
log('Failed to subscribe to ACK topic', { error: err.message });
|
|
370
377
|
cleanup(() => {
|
|
371
|
-
reject(new Error(`Failed to subscribe: ${err.message}`));
|
|
378
|
+
reject(new Error(`Failed to subscribe to ACK: ${err.message}`));
|
|
372
379
|
});
|
|
373
380
|
return;
|
|
374
381
|
}
|
|
375
382
|
|
|
376
|
-
log('Subscribed to
|
|
377
|
-
|
|
378
|
-
// Publish permission request
|
|
379
|
-
const permissionRequest = {
|
|
380
|
-
tool_name,
|
|
381
|
-
tool_input,
|
|
382
|
-
session_id,
|
|
383
|
-
cwd,
|
|
384
|
-
timestamp: Date.now(),
|
|
385
|
-
project_id: projectId,
|
|
386
|
-
};
|
|
383
|
+
log('Subscribed to ACK topic', { topic: ackTopic });
|
|
387
384
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
client.publish(requestTopic, payload, { qos: MQTT_CONFIG.qos, retain: false }, (err) => {
|
|
385
|
+
// Subscribe to response topic
|
|
386
|
+
client.subscribe(responseTopic, { qos: MQTT_CONFIG.qos }, (err) => {
|
|
391
387
|
if (err) {
|
|
392
|
-
log('Failed to
|
|
388
|
+
log('Failed to subscribe to response topic', { error: err.message });
|
|
393
389
|
cleanup(() => {
|
|
394
|
-
reject(new Error(`Failed to
|
|
390
|
+
reject(new Error(`Failed to subscribe: ${err.message}`));
|
|
395
391
|
});
|
|
396
392
|
return;
|
|
397
393
|
}
|
|
398
394
|
|
|
399
|
-
log('
|
|
395
|
+
log('Subscribed to response topic', { topic: responseTopic });
|
|
396
|
+
|
|
397
|
+
// Publish permission request
|
|
398
|
+
const permissionRequest = {
|
|
399
|
+
tool_name,
|
|
400
|
+
tool_input,
|
|
401
|
+
session_id,
|
|
402
|
+
cwd,
|
|
403
|
+
timestamp: Date.now(),
|
|
404
|
+
project_id: projectId,
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
const payload = JSON.stringify(permissionRequest);
|
|
408
|
+
|
|
409
|
+
client.publish(requestTopic, payload, { qos: MQTT_CONFIG.qos, retain: false }, (err) => {
|
|
410
|
+
if (err) {
|
|
411
|
+
log('Failed to publish permission request', { error: err.message });
|
|
412
|
+
cleanup(() => {
|
|
413
|
+
reject(new Error(`Failed to publish: ${err.message}`));
|
|
414
|
+
});
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
log('Published permission request', { topic: requestTopic });
|
|
419
|
+
|
|
420
|
+
// Send notification to all devices
|
|
421
|
+
const notificationTopic = `notifications/${projectId}/permission`;
|
|
422
|
+
const notificationPayload = JSON.stringify({
|
|
423
|
+
type: 'permission_request',
|
|
424
|
+
tool_name,
|
|
425
|
+
tool_input,
|
|
426
|
+
timestamp: Date.now(),
|
|
427
|
+
project_id: projectId,
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
client.publish(notificationTopic, notificationPayload, { qos: MQTT_CONFIG.qos }, (notifErr) => {
|
|
431
|
+
if (notifErr) {
|
|
432
|
+
log('Failed to publish notification', { error: notifErr.message });
|
|
433
|
+
// Don't fail the whole request if notification fails
|
|
434
|
+
} else {
|
|
435
|
+
log('Published permission notification', { topic: notificationTopic });
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// Set ACK timeout (2 seconds)
|
|
440
|
+
ackTimeoutHandle = setTimeout(() => {
|
|
441
|
+
if (!ackReceived) {
|
|
442
|
+
log('ACK not received within 2 seconds - user likely not on mobile app');
|
|
443
|
+
cleanup(() => {
|
|
444
|
+
// Exit without response - Claude will continue without permission
|
|
445
|
+
process.exit(0);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}, 5000);
|
|
449
|
+
});
|
|
400
450
|
});
|
|
401
451
|
});
|
|
402
452
|
});
|
|
403
453
|
|
|
404
|
-
// Handle incoming messages (response from frontend)
|
|
454
|
+
// Handle incoming messages (ACK and response from frontend)
|
|
405
455
|
client.on('message', (topic, payload) => {
|
|
456
|
+
// Handle ACK
|
|
457
|
+
if (topic === ackTopic) {
|
|
458
|
+
try {
|
|
459
|
+
const ack = JSON.parse(payload.toString());
|
|
460
|
+
log('Received ACK from mobile app', ack);
|
|
461
|
+
ackReceived = true;
|
|
462
|
+
|
|
463
|
+
// Clear ACK timeout since we received it
|
|
464
|
+
if (ackTimeoutHandle) {
|
|
465
|
+
clearTimeout(ackTimeoutHandle);
|
|
466
|
+
ackTimeoutHandle = null;
|
|
467
|
+
}
|
|
468
|
+
} catch (error) {
|
|
469
|
+
log('Failed to parse ACK', { error: error.message });
|
|
470
|
+
}
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Handle response
|
|
406
475
|
if (topic !== responseTopic) return;
|
|
407
476
|
|
|
408
477
|
try {
|
|
@@ -552,11 +621,11 @@ async function main() {
|
|
|
552
621
|
// Get project ID from session mapping file
|
|
553
622
|
let projectId = getProjectIdFromSession(hookInput.session_id);
|
|
554
623
|
|
|
555
|
-
//
|
|
556
|
-
//
|
|
624
|
+
// If no project ID found, we can't route the permission request via MQTT
|
|
625
|
+
// This could happen if the session was started from CLI without backend
|
|
626
|
+
// In this case, exit without blocking (allow the operation)
|
|
557
627
|
if (!projectId) {
|
|
558
|
-
log('Session not found in sessions.json -
|
|
559
|
-
log('Passing through to use Claude Code\'s native permission system');
|
|
628
|
+
log('Session not found in sessions.json - allowing operation without permission check');
|
|
560
629
|
process.exit(0);
|
|
561
630
|
}
|
|
562
631
|
|