@kmmao/happy-agent 0.7.0 → 0.7.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/dist/index.cjs +3785 -3298
- package/dist/index.d.cts +72 -30
- package/dist/index.d.mts +72 -30
- package/dist/index.mjs +3785 -3298
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -45,6 +45,27 @@ declare const MachineMetadataSchema: z.ZodObject<{
|
|
|
45
45
|
happyLibDir: z.ZodString;
|
|
46
46
|
}, z.core.$strip>;
|
|
47
47
|
type MachineMetadata = z.infer<typeof MachineMetadataSchema>;
|
|
48
|
+
declare const TailscaleInfoSchema: z.ZodObject<{
|
|
49
|
+
status: z.ZodEnum<{
|
|
50
|
+
connected: "connected";
|
|
51
|
+
disconnected: "disconnected";
|
|
52
|
+
"not-installed": "not-installed";
|
|
53
|
+
}>;
|
|
54
|
+
ipv4: z.ZodOptional<z.ZodString>;
|
|
55
|
+
ipv6: z.ZodOptional<z.ZodString>;
|
|
56
|
+
hostname: z.ZodOptional<z.ZodString>;
|
|
57
|
+
tailnetName: z.ZodOptional<z.ZodString>;
|
|
58
|
+
version: z.ZodOptional<z.ZodString>;
|
|
59
|
+
serves: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
60
|
+
port: z.ZodNumber;
|
|
61
|
+
path: z.ZodOptional<z.ZodString>;
|
|
62
|
+
protocol: z.ZodString;
|
|
63
|
+
target: z.ZodString;
|
|
64
|
+
funnel: z.ZodBoolean;
|
|
65
|
+
hostname: z.ZodString;
|
|
66
|
+
}, z.core.$strip>>>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
type TailscaleInfo = z.infer<typeof TailscaleInfoSchema>;
|
|
48
69
|
declare const TunnelEntrySchema: z.ZodObject<{
|
|
49
70
|
provider: z.ZodString;
|
|
50
71
|
localPort: z.ZodNumber;
|
|
@@ -384,8 +405,8 @@ declare const ResolvedRuntimeProfileSchema: z$1.ZodObject<{
|
|
|
384
405
|
}, z$1.core.$strip>>>;
|
|
385
406
|
modelMappings: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodString>>;
|
|
386
407
|
defaultSessionType: z$1.ZodOptional<z$1.ZodEnum<{
|
|
387
|
-
simple: "simple";
|
|
388
408
|
worktree: "worktree";
|
|
409
|
+
simple: "simple";
|
|
389
410
|
}>>;
|
|
390
411
|
defaultPermissionMode: z$1.ZodOptional<z$1.ZodEnum<{
|
|
391
412
|
default: "default";
|
|
@@ -508,10 +529,46 @@ declare function getOrCreateMachine(config: Config, creds: Credentials, metadata
|
|
|
508
529
|
*/
|
|
509
530
|
declare function listMachines(config: Config, creds: Credentials): Promise<RawMachine[]>;
|
|
510
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Outcome of a decrypt attempt.
|
|
534
|
+
*
|
|
535
|
+
* The low-level {@link decrypt} returns `unknown | null`, fusing "could not
|
|
536
|
+
* decrypt" (wrong key, tampered bytes, wrong variant, non-JSON plaintext)
|
|
537
|
+
* with a value that legitimately decrypted to something falsy.
|
|
538
|
+
* `DecryptResult` splits those apart: `{ ok: false }` is an authentication or
|
|
539
|
+
* parse failure, while `{ ok: true, value }` carries the recovered plaintext.
|
|
540
|
+
* Callers branch on `ok` instead of guessing from a collapsed `null`.
|
|
541
|
+
*/
|
|
542
|
+
type DecryptResult = {
|
|
543
|
+
ok: true;
|
|
544
|
+
value: any;
|
|
545
|
+
} | {
|
|
546
|
+
ok: false;
|
|
547
|
+
};
|
|
548
|
+
/**
|
|
549
|
+
* A Cipher binds one AccessKey + encryption variant into a small interface.
|
|
550
|
+
*
|
|
551
|
+
* It is the single seam every transport client encrypts/decrypts through:
|
|
552
|
+
* hand it a value and get a wire-ready base64 string, or hand it a base64
|
|
553
|
+
* wire string and get a {@link DecryptResult}. The variant choice (legacy
|
|
554
|
+
* NaCl secretbox vs AES-256-GCM dataKey) and the base64 framing live behind
|
|
555
|
+
* this interface, so call sites never thread `(key, variant)` or call
|
|
556
|
+
* `encode`/`decodeBase64` themselves — a wrong-variant or wrong-key bug can
|
|
557
|
+
* only originate at the one `createCipher` call, not at the dozens of places
|
|
558
|
+
* that used to repeat the pattern.
|
|
559
|
+
*/
|
|
560
|
+
interface Cipher {
|
|
561
|
+
/** Encrypt a JSON-serializable value, returning a base64 wire string. */
|
|
562
|
+
encrypt(data: any): string;
|
|
563
|
+
/** Decode + decrypt a base64 wire string. Never throws. */
|
|
564
|
+
decrypt(data: string): DecryptResult;
|
|
565
|
+
}
|
|
566
|
+
|
|
511
567
|
/**
|
|
512
568
|
* Common RPC types and interfaces for both session and machine clients.
|
|
513
569
|
* Mirrors happy-cli/src/api/rpc/types.ts
|
|
514
570
|
*/
|
|
571
|
+
|
|
515
572
|
/**
|
|
516
573
|
* Generic RPC handler function type
|
|
517
574
|
*/
|
|
@@ -528,8 +585,7 @@ interface RpcRequest {
|
|
|
528
585
|
*/
|
|
529
586
|
interface RpcHandlerConfig {
|
|
530
587
|
scopePrefix: string;
|
|
531
|
-
|
|
532
|
-
encryptionVariant: "legacy" | "dataKey";
|
|
588
|
+
cipher: Cipher;
|
|
533
589
|
logger?: (message: string, data?: unknown) => void;
|
|
534
590
|
}
|
|
535
591
|
|
|
@@ -544,8 +600,7 @@ interface RpcHandlerConfig {
|
|
|
544
600
|
declare class RpcHandlerManager {
|
|
545
601
|
private handlers;
|
|
546
602
|
private readonly scopePrefix;
|
|
547
|
-
private readonly
|
|
548
|
-
private readonly encryptionVariant;
|
|
603
|
+
private readonly cipher;
|
|
549
604
|
private readonly logger;
|
|
550
605
|
private socket;
|
|
551
606
|
private reregisterInterval;
|
|
@@ -556,7 +611,18 @@ declare class RpcHandlerManager {
|
|
|
556
611
|
*/
|
|
557
612
|
registerHandler<TRequest = any, TResponse = any>(method: string, handler: RpcHandler<TRequest, TResponse>): void;
|
|
558
613
|
/**
|
|
559
|
-
*
|
|
614
|
+
* Route a decrypted RPC call to its handler. This is the plaintext core of
|
|
615
|
+
* the manager: it knows nothing about the wire (no base64, no cipher), so it
|
|
616
|
+
* is TOTAL — an unknown method or a throwing handler both resolve to an
|
|
617
|
+
* `{ error }` value rather than rejecting. That makes it the test surface for
|
|
618
|
+
* routing behaviour, exercised without any crypto setup.
|
|
619
|
+
*/
|
|
620
|
+
dispatch(method: string, params: unknown): Promise<unknown>;
|
|
621
|
+
/**
|
|
622
|
+
* Handle an incoming wire RPC request: decrypt params, dispatch in plaintext,
|
|
623
|
+
* encrypt the result. The Cipher is the only encryption seam; on a decrypt
|
|
624
|
+
* failure the handler is still dispatched with `null` params (preserving the
|
|
625
|
+
* previous behaviour where a corrupt payload decrypted to `null`).
|
|
560
626
|
*/
|
|
561
627
|
handleRequest(request: RpcRequest): Promise<string>;
|
|
562
628
|
onSocketConnect(socket: Socket): void;
|
|
@@ -640,30 +706,6 @@ declare class SessionClient extends EventEmitter {
|
|
|
640
706
|
private setupSocketListeners;
|
|
641
707
|
}
|
|
642
708
|
|
|
643
|
-
/**
|
|
644
|
-
* Tailscale detection utility for happy-agent.
|
|
645
|
-
*
|
|
646
|
-
* Adapted from happy-cli/src/utils/tailscale.ts — keep in sync.
|
|
647
|
-
*/
|
|
648
|
-
type TailscaleStatus = "connected" | "disconnected" | "not-installed";
|
|
649
|
-
type TailscaleServeEntry = {
|
|
650
|
-
port: number;
|
|
651
|
-
path: string;
|
|
652
|
-
protocol: string;
|
|
653
|
-
target: string;
|
|
654
|
-
funnel: boolean;
|
|
655
|
-
hostname: string;
|
|
656
|
-
};
|
|
657
|
-
type TailscaleInfo = {
|
|
658
|
-
status: TailscaleStatus;
|
|
659
|
-
ipv4?: string;
|
|
660
|
-
ipv6?: string;
|
|
661
|
-
hostname?: string;
|
|
662
|
-
tailnetName?: string;
|
|
663
|
-
version?: string;
|
|
664
|
-
serves?: TailscaleServeEntry[];
|
|
665
|
-
};
|
|
666
|
-
|
|
667
709
|
/**
|
|
668
710
|
* Tunnel Provider abstraction — unified interface for all tunnel backends.
|
|
669
711
|
*
|
package/dist/index.d.mts
CHANGED
|
@@ -45,6 +45,27 @@ declare const MachineMetadataSchema: z.ZodObject<{
|
|
|
45
45
|
happyLibDir: z.ZodString;
|
|
46
46
|
}, z.core.$strip>;
|
|
47
47
|
type MachineMetadata = z.infer<typeof MachineMetadataSchema>;
|
|
48
|
+
declare const TailscaleInfoSchema: z.ZodObject<{
|
|
49
|
+
status: z.ZodEnum<{
|
|
50
|
+
connected: "connected";
|
|
51
|
+
disconnected: "disconnected";
|
|
52
|
+
"not-installed": "not-installed";
|
|
53
|
+
}>;
|
|
54
|
+
ipv4: z.ZodOptional<z.ZodString>;
|
|
55
|
+
ipv6: z.ZodOptional<z.ZodString>;
|
|
56
|
+
hostname: z.ZodOptional<z.ZodString>;
|
|
57
|
+
tailnetName: z.ZodOptional<z.ZodString>;
|
|
58
|
+
version: z.ZodOptional<z.ZodString>;
|
|
59
|
+
serves: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
60
|
+
port: z.ZodNumber;
|
|
61
|
+
path: z.ZodOptional<z.ZodString>;
|
|
62
|
+
protocol: z.ZodString;
|
|
63
|
+
target: z.ZodString;
|
|
64
|
+
funnel: z.ZodBoolean;
|
|
65
|
+
hostname: z.ZodString;
|
|
66
|
+
}, z.core.$strip>>>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
type TailscaleInfo = z.infer<typeof TailscaleInfoSchema>;
|
|
48
69
|
declare const TunnelEntrySchema: z.ZodObject<{
|
|
49
70
|
provider: z.ZodString;
|
|
50
71
|
localPort: z.ZodNumber;
|
|
@@ -384,8 +405,8 @@ declare const ResolvedRuntimeProfileSchema: z$1.ZodObject<{
|
|
|
384
405
|
}, z$1.core.$strip>>>;
|
|
385
406
|
modelMappings: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodString>>;
|
|
386
407
|
defaultSessionType: z$1.ZodOptional<z$1.ZodEnum<{
|
|
387
|
-
simple: "simple";
|
|
388
408
|
worktree: "worktree";
|
|
409
|
+
simple: "simple";
|
|
389
410
|
}>>;
|
|
390
411
|
defaultPermissionMode: z$1.ZodOptional<z$1.ZodEnum<{
|
|
391
412
|
default: "default";
|
|
@@ -508,10 +529,46 @@ declare function getOrCreateMachine(config: Config, creds: Credentials, metadata
|
|
|
508
529
|
*/
|
|
509
530
|
declare function listMachines(config: Config, creds: Credentials): Promise<RawMachine[]>;
|
|
510
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Outcome of a decrypt attempt.
|
|
534
|
+
*
|
|
535
|
+
* The low-level {@link decrypt} returns `unknown | null`, fusing "could not
|
|
536
|
+
* decrypt" (wrong key, tampered bytes, wrong variant, non-JSON plaintext)
|
|
537
|
+
* with a value that legitimately decrypted to something falsy.
|
|
538
|
+
* `DecryptResult` splits those apart: `{ ok: false }` is an authentication or
|
|
539
|
+
* parse failure, while `{ ok: true, value }` carries the recovered plaintext.
|
|
540
|
+
* Callers branch on `ok` instead of guessing from a collapsed `null`.
|
|
541
|
+
*/
|
|
542
|
+
type DecryptResult = {
|
|
543
|
+
ok: true;
|
|
544
|
+
value: any;
|
|
545
|
+
} | {
|
|
546
|
+
ok: false;
|
|
547
|
+
};
|
|
548
|
+
/**
|
|
549
|
+
* A Cipher binds one AccessKey + encryption variant into a small interface.
|
|
550
|
+
*
|
|
551
|
+
* It is the single seam every transport client encrypts/decrypts through:
|
|
552
|
+
* hand it a value and get a wire-ready base64 string, or hand it a base64
|
|
553
|
+
* wire string and get a {@link DecryptResult}. The variant choice (legacy
|
|
554
|
+
* NaCl secretbox vs AES-256-GCM dataKey) and the base64 framing live behind
|
|
555
|
+
* this interface, so call sites never thread `(key, variant)` or call
|
|
556
|
+
* `encode`/`decodeBase64` themselves — a wrong-variant or wrong-key bug can
|
|
557
|
+
* only originate at the one `createCipher` call, not at the dozens of places
|
|
558
|
+
* that used to repeat the pattern.
|
|
559
|
+
*/
|
|
560
|
+
interface Cipher {
|
|
561
|
+
/** Encrypt a JSON-serializable value, returning a base64 wire string. */
|
|
562
|
+
encrypt(data: any): string;
|
|
563
|
+
/** Decode + decrypt a base64 wire string. Never throws. */
|
|
564
|
+
decrypt(data: string): DecryptResult;
|
|
565
|
+
}
|
|
566
|
+
|
|
511
567
|
/**
|
|
512
568
|
* Common RPC types and interfaces for both session and machine clients.
|
|
513
569
|
* Mirrors happy-cli/src/api/rpc/types.ts
|
|
514
570
|
*/
|
|
571
|
+
|
|
515
572
|
/**
|
|
516
573
|
* Generic RPC handler function type
|
|
517
574
|
*/
|
|
@@ -528,8 +585,7 @@ interface RpcRequest {
|
|
|
528
585
|
*/
|
|
529
586
|
interface RpcHandlerConfig {
|
|
530
587
|
scopePrefix: string;
|
|
531
|
-
|
|
532
|
-
encryptionVariant: "legacy" | "dataKey";
|
|
588
|
+
cipher: Cipher;
|
|
533
589
|
logger?: (message: string, data?: unknown) => void;
|
|
534
590
|
}
|
|
535
591
|
|
|
@@ -544,8 +600,7 @@ interface RpcHandlerConfig {
|
|
|
544
600
|
declare class RpcHandlerManager {
|
|
545
601
|
private handlers;
|
|
546
602
|
private readonly scopePrefix;
|
|
547
|
-
private readonly
|
|
548
|
-
private readonly encryptionVariant;
|
|
603
|
+
private readonly cipher;
|
|
549
604
|
private readonly logger;
|
|
550
605
|
private socket;
|
|
551
606
|
private reregisterInterval;
|
|
@@ -556,7 +611,18 @@ declare class RpcHandlerManager {
|
|
|
556
611
|
*/
|
|
557
612
|
registerHandler<TRequest = any, TResponse = any>(method: string, handler: RpcHandler<TRequest, TResponse>): void;
|
|
558
613
|
/**
|
|
559
|
-
*
|
|
614
|
+
* Route a decrypted RPC call to its handler. This is the plaintext core of
|
|
615
|
+
* the manager: it knows nothing about the wire (no base64, no cipher), so it
|
|
616
|
+
* is TOTAL — an unknown method or a throwing handler both resolve to an
|
|
617
|
+
* `{ error }` value rather than rejecting. That makes it the test surface for
|
|
618
|
+
* routing behaviour, exercised without any crypto setup.
|
|
619
|
+
*/
|
|
620
|
+
dispatch(method: string, params: unknown): Promise<unknown>;
|
|
621
|
+
/**
|
|
622
|
+
* Handle an incoming wire RPC request: decrypt params, dispatch in plaintext,
|
|
623
|
+
* encrypt the result. The Cipher is the only encryption seam; on a decrypt
|
|
624
|
+
* failure the handler is still dispatched with `null` params (preserving the
|
|
625
|
+
* previous behaviour where a corrupt payload decrypted to `null`).
|
|
560
626
|
*/
|
|
561
627
|
handleRequest(request: RpcRequest): Promise<string>;
|
|
562
628
|
onSocketConnect(socket: Socket): void;
|
|
@@ -640,30 +706,6 @@ declare class SessionClient extends EventEmitter {
|
|
|
640
706
|
private setupSocketListeners;
|
|
641
707
|
}
|
|
642
708
|
|
|
643
|
-
/**
|
|
644
|
-
* Tailscale detection utility for happy-agent.
|
|
645
|
-
*
|
|
646
|
-
* Adapted from happy-cli/src/utils/tailscale.ts — keep in sync.
|
|
647
|
-
*/
|
|
648
|
-
type TailscaleStatus = "connected" | "disconnected" | "not-installed";
|
|
649
|
-
type TailscaleServeEntry = {
|
|
650
|
-
port: number;
|
|
651
|
-
path: string;
|
|
652
|
-
protocol: string;
|
|
653
|
-
target: string;
|
|
654
|
-
funnel: boolean;
|
|
655
|
-
hostname: string;
|
|
656
|
-
};
|
|
657
|
-
type TailscaleInfo = {
|
|
658
|
-
status: TailscaleStatus;
|
|
659
|
-
ipv4?: string;
|
|
660
|
-
ipv6?: string;
|
|
661
|
-
hostname?: string;
|
|
662
|
-
tailnetName?: string;
|
|
663
|
-
version?: string;
|
|
664
|
-
serves?: TailscaleServeEntry[];
|
|
665
|
-
};
|
|
666
|
-
|
|
667
709
|
/**
|
|
668
710
|
* Tunnel Provider abstraction — unified interface for all tunnel backends.
|
|
669
711
|
*
|