happy-coder 0.6.1 → 0.6.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/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +2 -0
- package/dist/lib.d.mts +2 -0
- package/dist/lib.mjs +1 -1
- package/dist/{types-iMUxaPkI.cjs → types-BDtHM1DY.cjs} +65 -25
- package/dist/{types-DKVMGtcN.mjs → types-Dz5kZrVh.mjs} +65 -25
- package/package.json +1 -1
- package/scripts/claude_local_launcher.cjs +3 -0
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
|
-
var types$1 = require('./types-
|
|
4
|
+
var types$1 = require('./types-BDtHM1DY.cjs');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
6
|
var node_child_process = require('node:child_process');
|
|
7
7
|
var node_path = require('node:path');
|
|
@@ -2262,7 +2262,7 @@ async function loop(opts) {
|
|
|
2262
2262
|
}
|
|
2263
2263
|
|
|
2264
2264
|
var name = "happy-coder";
|
|
2265
|
-
var version = "0.6.
|
|
2265
|
+
var version = "0.6.3";
|
|
2266
2266
|
var description = "Claude Code session sharing CLI";
|
|
2267
2267
|
var author = "Kirill Dubovitskiy";
|
|
2268
2268
|
var license = "MIT";
|
|
@@ -3089,7 +3089,7 @@ async function start(credentials, options = {}) {
|
|
|
3089
3089
|
types$1.logger.infoDeveloper(`Logs: ${logPath}`);
|
|
3090
3090
|
session.updateAgentState((currentState) => ({
|
|
3091
3091
|
...currentState,
|
|
3092
|
-
controlledByUser: options.startingMode
|
|
3092
|
+
controlledByUser: options.startingMode !== "remote"
|
|
3093
3093
|
}));
|
|
3094
3094
|
const caffeinateStarted = startCaffeinate();
|
|
3095
3095
|
if (caffeinateStarted) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { l as logger, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as encodeBase64, A as ApiClient, g as encodeBase64Url, h as decodeBase64, j as encrypt, b as initializeConfiguration, i as initLoggerWithGlobalConfiguration } from './types-
|
|
2
|
+
import { l as logger, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as encodeBase64, A as ApiClient, g as encodeBase64Url, h as decodeBase64, j as encrypt, b as initializeConfiguration, i as initLoggerWithGlobalConfiguration } from './types-Dz5kZrVh.mjs';
|
|
3
3
|
import { randomUUID, randomBytes } from 'node:crypto';
|
|
4
4
|
import { spawn, execSync } from 'node:child_process';
|
|
5
5
|
import { resolve, join, dirname as dirname$1 } from 'node:path';
|
|
@@ -2241,7 +2241,7 @@ async function loop(opts) {
|
|
|
2241
2241
|
}
|
|
2242
2242
|
|
|
2243
2243
|
var name = "happy-coder";
|
|
2244
|
-
var version = "0.6.
|
|
2244
|
+
var version = "0.6.3";
|
|
2245
2245
|
var description = "Claude Code session sharing CLI";
|
|
2246
2246
|
var author = "Kirill Dubovitskiy";
|
|
2247
2247
|
var license = "MIT";
|
|
@@ -3068,7 +3068,7 @@ async function start(credentials, options = {}) {
|
|
|
3068
3068
|
logger.infoDeveloper(`Logs: ${logPath}`);
|
|
3069
3069
|
session.updateAgentState((currentState) => ({
|
|
3070
3070
|
...currentState,
|
|
3071
|
-
controlledByUser: options.startingMode
|
|
3071
|
+
controlledByUser: options.startingMode !== "remote"
|
|
3072
3072
|
}));
|
|
3073
3073
|
const caffeinateStarted = startCaffeinate();
|
|
3074
3074
|
if (caffeinateStarted) {
|
package/dist/lib.cjs
CHANGED
package/dist/lib.d.cts
CHANGED
|
@@ -449,6 +449,8 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
449
449
|
private pendingMessages;
|
|
450
450
|
private pendingMessageCallback;
|
|
451
451
|
private rpcHandlers;
|
|
452
|
+
private agentStateLock;
|
|
453
|
+
private metadataLock;
|
|
452
454
|
constructor(token: string, secret: Uint8Array, session: Session);
|
|
453
455
|
onUserMessage(callback: (data: UserMessage) => void): void;
|
|
454
456
|
/**
|
package/dist/lib.d.mts
CHANGED
|
@@ -449,6 +449,8 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
449
449
|
private pendingMessages;
|
|
450
450
|
private pendingMessageCallback;
|
|
451
451
|
private rpcHandlers;
|
|
452
|
+
private agentStateLock;
|
|
453
|
+
private metadataLock;
|
|
452
454
|
constructor(token: string, secret: Uint8Array, session: Session);
|
|
453
455
|
onUserMessage(callback: (data: UserMessage) => void): void;
|
|
454
456
|
/**
|
package/dist/lib.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, i as initLoggerWithGlobalConfiguration, b as initializeConfiguration, l as logger } from './types-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, i as initLoggerWithGlobalConfiguration, b as initializeConfiguration, l as logger } from './types-Dz5kZrVh.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'fs';
|
|
@@ -358,6 +358,40 @@ function createBackoff(opts) {
|
|
|
358
358
|
}
|
|
359
359
|
let backoff = createBackoff();
|
|
360
360
|
|
|
361
|
+
class AsyncLock {
|
|
362
|
+
permits = 1;
|
|
363
|
+
promiseResolverQueue = [];
|
|
364
|
+
async inLock(func) {
|
|
365
|
+
try {
|
|
366
|
+
await this.lock();
|
|
367
|
+
return await func();
|
|
368
|
+
} finally {
|
|
369
|
+
this.unlock();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async lock() {
|
|
373
|
+
if (this.permits > 0) {
|
|
374
|
+
this.permits = this.permits - 1;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
await new Promise((resolve) => this.promiseResolverQueue.push(resolve));
|
|
378
|
+
}
|
|
379
|
+
unlock() {
|
|
380
|
+
this.permits += 1;
|
|
381
|
+
if (this.permits > 1 && this.promiseResolverQueue.length > 0) {
|
|
382
|
+
throw new Error("this.permits should never be > 0 when there is someone waiting.");
|
|
383
|
+
} else if (this.permits === 1 && this.promiseResolverQueue.length > 0) {
|
|
384
|
+
this.permits -= 1;
|
|
385
|
+
const nextResolver = this.promiseResolverQueue.shift();
|
|
386
|
+
if (nextResolver) {
|
|
387
|
+
setTimeout(() => {
|
|
388
|
+
nextResolver(true);
|
|
389
|
+
}, 0);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
361
395
|
class ApiSessionClient extends node_events.EventEmitter {
|
|
362
396
|
token;
|
|
363
397
|
secret;
|
|
@@ -370,6 +404,8 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
370
404
|
pendingMessages = [];
|
|
371
405
|
pendingMessageCallback = null;
|
|
372
406
|
rpcHandlers = /* @__PURE__ */ new Map();
|
|
407
|
+
agentStateLock = new AsyncLock();
|
|
408
|
+
metadataLock = new AsyncLock();
|
|
373
409
|
constructor(token, secret, session) {
|
|
374
410
|
super();
|
|
375
411
|
this.token = token;
|
|
@@ -589,19 +625,21 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
589
625
|
* @param handler - Handler function that returns the updated metadata
|
|
590
626
|
*/
|
|
591
627
|
updateMetadata(handler) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
this.metadataVersion = answer.version;
|
|
598
|
-
} else if (answer.result === "version-mismatch") {
|
|
599
|
-
if (answer.version > this.metadataVersion) {
|
|
600
|
-
this.metadataVersion = answer.version;
|
|
628
|
+
this.metadataLock.inLock(async () => {
|
|
629
|
+
await backoff(async () => {
|
|
630
|
+
let updated = handler(this.metadata);
|
|
631
|
+
const answer = await this.socket.emitWithAck("update-metadata", { sid: this.sessionId, expectedVersion: this.metadataVersion, metadata: encodeBase64(encrypt(updated, this.secret)) });
|
|
632
|
+
if (answer.result === "success") {
|
|
601
633
|
this.metadata = decrypt(decodeBase64(answer.metadata), this.secret);
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
634
|
+
this.metadataVersion = answer.version;
|
|
635
|
+
} else if (answer.result === "version-mismatch") {
|
|
636
|
+
if (answer.version > this.metadataVersion) {
|
|
637
|
+
this.metadataVersion = answer.version;
|
|
638
|
+
this.metadata = decrypt(decodeBase64(answer.metadata), this.secret);
|
|
639
|
+
}
|
|
640
|
+
throw new Error("Metadata version mismatch");
|
|
641
|
+
} else if (answer.result === "error") ;
|
|
642
|
+
});
|
|
605
643
|
});
|
|
606
644
|
}
|
|
607
645
|
/**
|
|
@@ -610,20 +648,22 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
610
648
|
*/
|
|
611
649
|
updateAgentState(handler) {
|
|
612
650
|
exports.logger.debugLargeJson("Updating agent state", this.agentState);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
this.agentStateVersion = answer.version;
|
|
619
|
-
exports.logger.debug("Agent state updated", this.agentState);
|
|
620
|
-
} else if (answer.result === "version-mismatch") {
|
|
621
|
-
if (answer.version > this.agentStateVersion) {
|
|
622
|
-
this.agentStateVersion = answer.version;
|
|
651
|
+
this.agentStateLock.inLock(async () => {
|
|
652
|
+
await backoff(async () => {
|
|
653
|
+
let updated = handler(this.agentState || {});
|
|
654
|
+
const answer = await this.socket.emitWithAck("update-state", { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? encodeBase64(encrypt(updated, this.secret)) : null });
|
|
655
|
+
if (answer.result === "success") {
|
|
623
656
|
this.agentState = answer.agentState ? decrypt(decodeBase64(answer.agentState), this.secret) : null;
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
657
|
+
this.agentStateVersion = answer.version;
|
|
658
|
+
exports.logger.debug("Agent state updated", this.agentState);
|
|
659
|
+
} else if (answer.result === "version-mismatch") {
|
|
660
|
+
if (answer.version > this.agentStateVersion) {
|
|
661
|
+
this.agentStateVersion = answer.version;
|
|
662
|
+
this.agentState = answer.agentState ? decrypt(decodeBase64(answer.agentState), this.secret) : null;
|
|
663
|
+
}
|
|
664
|
+
throw new Error("Agent state version mismatch");
|
|
665
|
+
} else if (answer.result === "error") ;
|
|
666
|
+
});
|
|
627
667
|
});
|
|
628
668
|
}
|
|
629
669
|
/**
|
|
@@ -356,6 +356,40 @@ function createBackoff(opts) {
|
|
|
356
356
|
}
|
|
357
357
|
let backoff = createBackoff();
|
|
358
358
|
|
|
359
|
+
class AsyncLock {
|
|
360
|
+
permits = 1;
|
|
361
|
+
promiseResolverQueue = [];
|
|
362
|
+
async inLock(func) {
|
|
363
|
+
try {
|
|
364
|
+
await this.lock();
|
|
365
|
+
return await func();
|
|
366
|
+
} finally {
|
|
367
|
+
this.unlock();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
async lock() {
|
|
371
|
+
if (this.permits > 0) {
|
|
372
|
+
this.permits = this.permits - 1;
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
await new Promise((resolve) => this.promiseResolverQueue.push(resolve));
|
|
376
|
+
}
|
|
377
|
+
unlock() {
|
|
378
|
+
this.permits += 1;
|
|
379
|
+
if (this.permits > 1 && this.promiseResolverQueue.length > 0) {
|
|
380
|
+
throw new Error("this.permits should never be > 0 when there is someone waiting.");
|
|
381
|
+
} else if (this.permits === 1 && this.promiseResolverQueue.length > 0) {
|
|
382
|
+
this.permits -= 1;
|
|
383
|
+
const nextResolver = this.promiseResolverQueue.shift();
|
|
384
|
+
if (nextResolver) {
|
|
385
|
+
setTimeout(() => {
|
|
386
|
+
nextResolver(true);
|
|
387
|
+
}, 0);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
359
393
|
class ApiSessionClient extends EventEmitter {
|
|
360
394
|
token;
|
|
361
395
|
secret;
|
|
@@ -368,6 +402,8 @@ class ApiSessionClient extends EventEmitter {
|
|
|
368
402
|
pendingMessages = [];
|
|
369
403
|
pendingMessageCallback = null;
|
|
370
404
|
rpcHandlers = /* @__PURE__ */ new Map();
|
|
405
|
+
agentStateLock = new AsyncLock();
|
|
406
|
+
metadataLock = new AsyncLock();
|
|
371
407
|
constructor(token, secret, session) {
|
|
372
408
|
super();
|
|
373
409
|
this.token = token;
|
|
@@ -587,19 +623,21 @@ class ApiSessionClient extends EventEmitter {
|
|
|
587
623
|
* @param handler - Handler function that returns the updated metadata
|
|
588
624
|
*/
|
|
589
625
|
updateMetadata(handler) {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
this.metadataVersion = answer.version;
|
|
596
|
-
} else if (answer.result === "version-mismatch") {
|
|
597
|
-
if (answer.version > this.metadataVersion) {
|
|
598
|
-
this.metadataVersion = answer.version;
|
|
626
|
+
this.metadataLock.inLock(async () => {
|
|
627
|
+
await backoff(async () => {
|
|
628
|
+
let updated = handler(this.metadata);
|
|
629
|
+
const answer = await this.socket.emitWithAck("update-metadata", { sid: this.sessionId, expectedVersion: this.metadataVersion, metadata: encodeBase64(encrypt(updated, this.secret)) });
|
|
630
|
+
if (answer.result === "success") {
|
|
599
631
|
this.metadata = decrypt(decodeBase64(answer.metadata), this.secret);
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
632
|
+
this.metadataVersion = answer.version;
|
|
633
|
+
} else if (answer.result === "version-mismatch") {
|
|
634
|
+
if (answer.version > this.metadataVersion) {
|
|
635
|
+
this.metadataVersion = answer.version;
|
|
636
|
+
this.metadata = decrypt(decodeBase64(answer.metadata), this.secret);
|
|
637
|
+
}
|
|
638
|
+
throw new Error("Metadata version mismatch");
|
|
639
|
+
} else if (answer.result === "error") ;
|
|
640
|
+
});
|
|
603
641
|
});
|
|
604
642
|
}
|
|
605
643
|
/**
|
|
@@ -608,20 +646,22 @@ class ApiSessionClient extends EventEmitter {
|
|
|
608
646
|
*/
|
|
609
647
|
updateAgentState(handler) {
|
|
610
648
|
logger.debugLargeJson("Updating agent state", this.agentState);
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
this.agentStateVersion = answer.version;
|
|
617
|
-
logger.debug("Agent state updated", this.agentState);
|
|
618
|
-
} else if (answer.result === "version-mismatch") {
|
|
619
|
-
if (answer.version > this.agentStateVersion) {
|
|
620
|
-
this.agentStateVersion = answer.version;
|
|
649
|
+
this.agentStateLock.inLock(async () => {
|
|
650
|
+
await backoff(async () => {
|
|
651
|
+
let updated = handler(this.agentState || {});
|
|
652
|
+
const answer = await this.socket.emitWithAck("update-state", { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? encodeBase64(encrypt(updated, this.secret)) : null });
|
|
653
|
+
if (answer.result === "success") {
|
|
621
654
|
this.agentState = answer.agentState ? decrypt(decodeBase64(answer.agentState), this.secret) : null;
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
655
|
+
this.agentStateVersion = answer.version;
|
|
656
|
+
logger.debug("Agent state updated", this.agentState);
|
|
657
|
+
} else if (answer.result === "version-mismatch") {
|
|
658
|
+
if (answer.version > this.agentStateVersion) {
|
|
659
|
+
this.agentStateVersion = answer.version;
|
|
660
|
+
this.agentState = answer.agentState ? decrypt(decodeBase64(answer.agentState), this.secret) : null;
|
|
661
|
+
}
|
|
662
|
+
throw new Error("Agent state version mismatch");
|
|
663
|
+
} else if (answer.result === "error") ;
|
|
664
|
+
});
|
|
625
665
|
});
|
|
626
666
|
}
|
|
627
667
|
/**
|
package/package.json
CHANGED