@zhigang1992/happy-cli 0.12.3 → 0.12.5
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-y8CVImEp.cjs → index-B8KwpPnt.cjs} +212 -35
- package/dist/{index-DNeoLdzx.mjs → index-BfGA--2C.mjs} +198 -21
- package/dist/index.cjs +6 -6
- package/dist/index.mjs +6 -6
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +118 -4
- package/dist/lib.d.mts +118 -4
- package/dist/lib.mjs +1 -1
- package/dist/{list-D_NjiLPx.mjs → list-B0EZS1nk.mjs} +1 -1
- package/dist/{list-DiamEbqL.cjs → list-BmyKI4UO.cjs} +1 -1
- package/dist/{prompt-CJh1Mo2A.mjs → prompt-COmkBtjd.mjs} +1 -1
- package/dist/{prompt-Cu47wZlI.cjs → prompt-SOUeW7vB.cjs} +1 -1
- package/dist/{runCodex-DErgypij.cjs → runCodex-CLxMptoC.cjs} +19 -3
- package/dist/{runCodex-B5ZlUUec.mjs → runCodex-Cxhf8ktE.mjs} +19 -3
- package/dist/{types-CllU28mx.cjs → types-0ILrOpLt.cjs} +140 -7
- package/dist/{types-D4_aCy-H.mjs → types-BmcSXhbq.mjs} +139 -6
- package/package.json +1 -1
package/dist/lib.d.mts
CHANGED
|
@@ -291,6 +291,16 @@ type RawJSONLines = z.infer<typeof RawJSONLinesSchema>;
|
|
|
291
291
|
/**
|
|
292
292
|
* Common RPC types and interfaces for both session and machine clients
|
|
293
293
|
*/
|
|
294
|
+
/**
|
|
295
|
+
* Session context for RPC handlers
|
|
296
|
+
* Contains environment and path information for the current session
|
|
297
|
+
*/
|
|
298
|
+
interface RpcSessionContext {
|
|
299
|
+
/** Working directory path for the session */
|
|
300
|
+
path: string;
|
|
301
|
+
/** Environment variables (includes direnv if available) */
|
|
302
|
+
env: Record<string, string>;
|
|
303
|
+
}
|
|
294
304
|
/**
|
|
295
305
|
* Generic RPC handler function type
|
|
296
306
|
* @template TRequest - The request data type
|
|
@@ -326,7 +336,19 @@ declare class RpcHandlerManager {
|
|
|
326
336
|
private readonly encryptionVariant;
|
|
327
337
|
private readonly logger;
|
|
328
338
|
private socket;
|
|
339
|
+
private sessionContext;
|
|
329
340
|
constructor(config: RpcHandlerConfig);
|
|
341
|
+
/**
|
|
342
|
+
* Set the session context (path and environment)
|
|
343
|
+
* This should be called after direnv environment is loaded
|
|
344
|
+
* @param context - The session context with path and environment
|
|
345
|
+
*/
|
|
346
|
+
setSessionContext(context: RpcSessionContext): void;
|
|
347
|
+
/**
|
|
348
|
+
* Get the current session context
|
|
349
|
+
* @returns The session context or null if not set
|
|
350
|
+
*/
|
|
351
|
+
getSessionContext(): RpcSessionContext | null;
|
|
330
352
|
/**
|
|
331
353
|
* Register an RPC handler for a specific method
|
|
332
354
|
* @param method - The method name (without prefix)
|
|
@@ -423,6 +445,30 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
423
445
|
*/
|
|
424
446
|
flush(): Promise<void>;
|
|
425
447
|
close(): Promise<void>;
|
|
448
|
+
/**
|
|
449
|
+
* Download and decrypt a blob from the server
|
|
450
|
+
* @param blobId - The blob ID to download
|
|
451
|
+
* @returns The decrypted binary data and metadata, or null if download/decryption fails
|
|
452
|
+
*/
|
|
453
|
+
downloadBlob(blobId: string): Promise<{
|
|
454
|
+
data: Uint8Array;
|
|
455
|
+
mimeType: string;
|
|
456
|
+
size: number;
|
|
457
|
+
} | null>;
|
|
458
|
+
/**
|
|
459
|
+
* Convert an image_ref content block to a Claude API image content block
|
|
460
|
+
* Downloads, decrypts, and base64 encodes the image
|
|
461
|
+
* @param imageRef - The image reference content block
|
|
462
|
+
* @returns Claude API image content block, or null if conversion fails
|
|
463
|
+
*/
|
|
464
|
+
resolveImageRef(imageRef: ImageRefContent): Promise<{
|
|
465
|
+
type: 'image';
|
|
466
|
+
source: {
|
|
467
|
+
type: 'base64';
|
|
468
|
+
media_type: string;
|
|
469
|
+
data: string;
|
|
470
|
+
};
|
|
471
|
+
} | null>;
|
|
426
472
|
}
|
|
427
473
|
|
|
428
474
|
type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';
|
|
@@ -505,9 +551,32 @@ type Machine = {
|
|
|
505
551
|
daemonState: DaemonState | null;
|
|
506
552
|
daemonStateVersion: number;
|
|
507
553
|
};
|
|
554
|
+
/**
|
|
555
|
+
* Image reference content block for user messages (E2E encrypted images)
|
|
556
|
+
*/
|
|
557
|
+
declare const ImageRefContentSchema: z.ZodObject<{
|
|
558
|
+
type: z.ZodLiteral<"image_ref">;
|
|
559
|
+
blobId: z.ZodString;
|
|
560
|
+
mimeType: z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/webp"]>;
|
|
561
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
562
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
563
|
+
}, "strip", z.ZodTypeAny, {
|
|
564
|
+
type: "image_ref";
|
|
565
|
+
blobId: string;
|
|
566
|
+
mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
|
|
567
|
+
width?: number | undefined;
|
|
568
|
+
height?: number | undefined;
|
|
569
|
+
}, {
|
|
570
|
+
type: "image_ref";
|
|
571
|
+
blobId: string;
|
|
572
|
+
mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
|
|
573
|
+
width?: number | undefined;
|
|
574
|
+
height?: number | undefined;
|
|
575
|
+
}>;
|
|
576
|
+
type ImageRefContent = z.infer<typeof ImageRefContentSchema>;
|
|
508
577
|
declare const UserMessageSchema: z.ZodObject<{
|
|
509
578
|
role: z.ZodLiteral<"user">;
|
|
510
|
-
content: z.ZodObject<{
|
|
579
|
+
content: z.ZodUnion<[z.ZodObject<{
|
|
511
580
|
type: z.ZodLiteral<"text">;
|
|
512
581
|
text: z.ZodString;
|
|
513
582
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -516,7 +585,34 @@ declare const UserMessageSchema: z.ZodObject<{
|
|
|
516
585
|
}, {
|
|
517
586
|
type: "text";
|
|
518
587
|
text: string;
|
|
519
|
-
}
|
|
588
|
+
}>, z.ZodArray<z.ZodUnion<[z.ZodObject<{
|
|
589
|
+
type: z.ZodLiteral<"text">;
|
|
590
|
+
text: z.ZodString;
|
|
591
|
+
}, "strip", z.ZodTypeAny, {
|
|
592
|
+
type: "text";
|
|
593
|
+
text: string;
|
|
594
|
+
}, {
|
|
595
|
+
type: "text";
|
|
596
|
+
text: string;
|
|
597
|
+
}>, z.ZodObject<{
|
|
598
|
+
type: z.ZodLiteral<"image_ref">;
|
|
599
|
+
blobId: z.ZodString;
|
|
600
|
+
mimeType: z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/webp"]>;
|
|
601
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
602
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
603
|
+
}, "strip", z.ZodTypeAny, {
|
|
604
|
+
type: "image_ref";
|
|
605
|
+
blobId: string;
|
|
606
|
+
mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
|
|
607
|
+
width?: number | undefined;
|
|
608
|
+
height?: number | undefined;
|
|
609
|
+
}, {
|
|
610
|
+
type: "image_ref";
|
|
611
|
+
blobId: string;
|
|
612
|
+
mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
|
|
613
|
+
width?: number | undefined;
|
|
614
|
+
height?: number | undefined;
|
|
615
|
+
}>]>, "many">]>;
|
|
520
616
|
localKey: z.ZodOptional<z.ZodString>;
|
|
521
617
|
meta: z.ZodOptional<z.ZodObject<{
|
|
522
618
|
sentFrom: z.ZodOptional<z.ZodString>;
|
|
@@ -550,7 +646,16 @@ declare const UserMessageSchema: z.ZodObject<{
|
|
|
550
646
|
content: {
|
|
551
647
|
type: "text";
|
|
552
648
|
text: string;
|
|
553
|
-
}
|
|
649
|
+
} | ({
|
|
650
|
+
type: "text";
|
|
651
|
+
text: string;
|
|
652
|
+
} | {
|
|
653
|
+
type: "image_ref";
|
|
654
|
+
blobId: string;
|
|
655
|
+
mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
|
|
656
|
+
width?: number | undefined;
|
|
657
|
+
height?: number | undefined;
|
|
658
|
+
})[];
|
|
554
659
|
role: "user";
|
|
555
660
|
localKey?: string | undefined;
|
|
556
661
|
meta?: {
|
|
@@ -567,7 +672,16 @@ declare const UserMessageSchema: z.ZodObject<{
|
|
|
567
672
|
content: {
|
|
568
673
|
type: "text";
|
|
569
674
|
text: string;
|
|
570
|
-
}
|
|
675
|
+
} | ({
|
|
676
|
+
type: "text";
|
|
677
|
+
text: string;
|
|
678
|
+
} | {
|
|
679
|
+
type: "image_ref";
|
|
680
|
+
blobId: string;
|
|
681
|
+
mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
|
|
682
|
+
width?: number | undefined;
|
|
683
|
+
height?: number | undefined;
|
|
684
|
+
})[];
|
|
571
685
|
role: "user";
|
|
572
686
|
localKey?: string | undefined;
|
|
573
687
|
meta?: {
|
package/dist/lib.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-BmcSXhbq.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'fs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as configuration, l as logger, d as decodeBase64, b as decrypt, f as formatTimeAgo, e as libsodiumDecryptFromPublicKey } from './types-
|
|
1
|
+
import { c as configuration, l as logger, d as decodeBase64, b as decrypt, f as formatTimeAgo, e as libsodiumDecryptFromPublicKey } from './types-BmcSXhbq.mjs';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { existsSync, readdirSync, statSync, readFileSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-
|
|
1
|
+
import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-BmcSXhbq.mjs';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { io } from 'socket.io-client';
|
|
4
4
|
import 'chalk';
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var types = require('./types-
|
|
5
|
+
var types = require('./types-0ILrOpLt.cjs');
|
|
6
6
|
var index_js = require('@modelcontextprotocol/sdk/client/index.js');
|
|
7
7
|
var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
8
8
|
var z = require('zod');
|
|
9
9
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
10
10
|
var child_process = require('child_process');
|
|
11
11
|
var node_crypto = require('node:crypto');
|
|
12
|
-
var index = require('./index-
|
|
12
|
+
var index = require('./index-B8KwpPnt.cjs');
|
|
13
13
|
var os = require('node:os');
|
|
14
14
|
var node_path = require('node:path');
|
|
15
15
|
var fs = require('node:fs');
|
|
@@ -754,6 +754,21 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
|
|
|
754
754
|
));
|
|
755
755
|
};
|
|
756
756
|
|
|
757
|
+
function extractTextFromContent(content) {
|
|
758
|
+
if (!Array.isArray(content)) {
|
|
759
|
+
if (content.type === "text") {
|
|
760
|
+
return content.text;
|
|
761
|
+
}
|
|
762
|
+
return "";
|
|
763
|
+
}
|
|
764
|
+
const textParts = [];
|
|
765
|
+
for (const block of content) {
|
|
766
|
+
if (block.type === "text") {
|
|
767
|
+
textParts.push(block.text);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
return textParts.join("\n");
|
|
771
|
+
}
|
|
757
772
|
function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify }) {
|
|
758
773
|
if (shouldExit) {
|
|
759
774
|
return false;
|
|
@@ -849,7 +864,8 @@ async function runCodex(opts) {
|
|
|
849
864
|
permissionMode: messagePermissionMode || "default",
|
|
850
865
|
model: messageModel
|
|
851
866
|
};
|
|
852
|
-
|
|
867
|
+
const textContent = extractTextFromContent(message.content);
|
|
868
|
+
messageQueue.push(textContent, enhancedMode);
|
|
853
869
|
});
|
|
854
870
|
let thinking = false;
|
|
855
871
|
session.keepAlive(thinking, "remote");
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, i as packageJson } from './types-
|
|
3
|
+
import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, i as packageJson } from './types-BmcSXhbq.mjs';
|
|
4
4
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
5
5
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { execSync } from 'child_process';
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
|
-
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-
|
|
10
|
+
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-BfGA--2C.mjs';
|
|
11
11
|
import os from 'node:os';
|
|
12
12
|
import { resolve, join } from 'node:path';
|
|
13
13
|
import fs from 'node:fs';
|
|
@@ -752,6 +752,21 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
|
|
|
752
752
|
));
|
|
753
753
|
};
|
|
754
754
|
|
|
755
|
+
function extractTextFromContent(content) {
|
|
756
|
+
if (!Array.isArray(content)) {
|
|
757
|
+
if (content.type === "text") {
|
|
758
|
+
return content.text;
|
|
759
|
+
}
|
|
760
|
+
return "";
|
|
761
|
+
}
|
|
762
|
+
const textParts = [];
|
|
763
|
+
for (const block of content) {
|
|
764
|
+
if (block.type === "text") {
|
|
765
|
+
textParts.push(block.text);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return textParts.join("\n");
|
|
769
|
+
}
|
|
755
770
|
function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify }) {
|
|
756
771
|
if (shouldExit) {
|
|
757
772
|
return false;
|
|
@@ -847,7 +862,8 @@ async function runCodex(opts) {
|
|
|
847
862
|
permissionMode: messagePermissionMode || "default",
|
|
848
863
|
model: messageModel
|
|
849
864
|
};
|
|
850
|
-
|
|
865
|
+
const textContent = extractTextFromContent(message.content);
|
|
866
|
+
messageQueue.push(textContent, enhancedMode);
|
|
851
867
|
});
|
|
852
868
|
let thinking = false;
|
|
853
869
|
session.keepAlive(thinking, "remote");
|
|
@@ -41,7 +41,7 @@ function _interopNamespaceDefault(e) {
|
|
|
41
41
|
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
42
42
|
|
|
43
43
|
var name = "@zhigang1992/happy-cli";
|
|
44
|
-
var version = "0.12.
|
|
44
|
+
var version = "0.12.5";
|
|
45
45
|
var description = "Mobile and Web client for Claude Code and Codex";
|
|
46
46
|
var author = "Kirill Dubovitskiy";
|
|
47
47
|
var license = "MIT";
|
|
@@ -332,6 +332,43 @@ function decryptWithDataKey(bundle, dataKey) {
|
|
|
332
332
|
return null;
|
|
333
333
|
}
|
|
334
334
|
}
|
|
335
|
+
function decryptBlobWithDataKey(bundle, dataKey) {
|
|
336
|
+
if (bundle.length < 1) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
if (bundle[0] !== 0) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
if (bundle.length < 12 + 16 + 1) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const nonce = bundle.slice(1, 13);
|
|
346
|
+
const authTag = bundle.slice(bundle.length - 16);
|
|
347
|
+
const ciphertext = bundle.slice(13, bundle.length - 16);
|
|
348
|
+
try {
|
|
349
|
+
const decipher = node_crypto.createDecipheriv("aes-256-gcm", dataKey, nonce);
|
|
350
|
+
decipher.setAuthTag(authTag);
|
|
351
|
+
const decrypted = Buffer.concat([
|
|
352
|
+
decipher.update(ciphertext),
|
|
353
|
+
decipher.final()
|
|
354
|
+
]);
|
|
355
|
+
return new Uint8Array(decrypted);
|
|
356
|
+
} catch (error) {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function decryptBlobWithSecretBox(bundle, secret) {
|
|
361
|
+
if (bundle.length < 1 + tweetnacl.secretbox.nonceLength) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
if (bundle[0] !== 0) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
const nonce = bundle.slice(1, 1 + tweetnacl.secretbox.nonceLength);
|
|
368
|
+
const ciphertext = bundle.slice(1 + tweetnacl.secretbox.nonceLength);
|
|
369
|
+
const decrypted = tweetnacl.secretbox.open(ciphertext, nonce, secret);
|
|
370
|
+
return decrypted || null;
|
|
371
|
+
}
|
|
335
372
|
function encrypt(key, variant, data) {
|
|
336
373
|
if (variant === "legacy") {
|
|
337
374
|
return encryptLegacy(data, key);
|
|
@@ -346,6 +383,13 @@ function decrypt(key, variant, data) {
|
|
|
346
383
|
return decryptWithDataKey(data, key);
|
|
347
384
|
}
|
|
348
385
|
}
|
|
386
|
+
function decryptBlob(key, variant, bundle) {
|
|
387
|
+
if (variant === "legacy") {
|
|
388
|
+
return decryptBlobWithSecretBox(bundle, key);
|
|
389
|
+
} else {
|
|
390
|
+
return decryptBlobWithDataKey(bundle, key);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
349
393
|
function authChallenge(secret) {
|
|
350
394
|
const keypair = tweetnacl.sign.keyPair.fromSeed(secret);
|
|
351
395
|
const challenge = getRandomBytes(32);
|
|
@@ -873,12 +917,27 @@ z.z.object({
|
|
|
873
917
|
agentStateVersion: z.z.number()
|
|
874
918
|
})
|
|
875
919
|
});
|
|
920
|
+
const TextContentSchema = z.z.object({
|
|
921
|
+
type: z.z.literal("text"),
|
|
922
|
+
text: z.z.string()
|
|
923
|
+
});
|
|
924
|
+
const ImageRefContentSchema = z.z.object({
|
|
925
|
+
type: z.z.literal("image_ref"),
|
|
926
|
+
blobId: z.z.string(),
|
|
927
|
+
mimeType: z.z.enum(["image/jpeg", "image/png", "image/gif", "image/webp"]),
|
|
928
|
+
width: z.z.number().optional(),
|
|
929
|
+
height: z.z.number().optional()
|
|
930
|
+
});
|
|
931
|
+
const ContentBlockSchema = z.z.union([TextContentSchema, ImageRefContentSchema]);
|
|
932
|
+
const UserMessageContentSchema = z.z.union([
|
|
933
|
+
TextContentSchema,
|
|
934
|
+
// Legacy: single text content
|
|
935
|
+
z.z.array(ContentBlockSchema)
|
|
936
|
+
// New: array of content blocks
|
|
937
|
+
]);
|
|
876
938
|
const UserMessageSchema = z.z.object({
|
|
877
939
|
role: z.z.literal("user"),
|
|
878
|
-
content:
|
|
879
|
-
type: z.z.literal("text"),
|
|
880
|
-
text: z.z.string()
|
|
881
|
-
}),
|
|
940
|
+
content: UserMessageContentSchema,
|
|
882
941
|
localKey: z.z.string().optional(),
|
|
883
942
|
// Mobile messages include this
|
|
884
943
|
meta: MessageMetaSchema.optional()
|
|
@@ -990,12 +1049,29 @@ class RpcHandlerManager {
|
|
|
990
1049
|
encryptionVariant;
|
|
991
1050
|
logger;
|
|
992
1051
|
socket = null;
|
|
1052
|
+
sessionContext = null;
|
|
993
1053
|
constructor(config) {
|
|
994
1054
|
this.scopePrefix = config.scopePrefix;
|
|
995
1055
|
this.encryptionKey = config.encryptionKey;
|
|
996
1056
|
this.encryptionVariant = config.encryptionVariant;
|
|
997
1057
|
this.logger = config.logger || ((msg, data) => logger.debug(msg, data));
|
|
998
1058
|
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Set the session context (path and environment)
|
|
1061
|
+
* This should be called after direnv environment is loaded
|
|
1062
|
+
* @param context - The session context with path and environment
|
|
1063
|
+
*/
|
|
1064
|
+
setSessionContext(context) {
|
|
1065
|
+
this.sessionContext = context;
|
|
1066
|
+
this.logger("[RPC] Session context set", { path: context.path, envVarCount: Object.keys(context.env).length });
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Get the current session context
|
|
1070
|
+
* @returns The session context or null if not set
|
|
1071
|
+
*/
|
|
1072
|
+
getSessionContext() {
|
|
1073
|
+
return this.sessionContext;
|
|
1074
|
+
}
|
|
999
1075
|
/**
|
|
1000
1076
|
* Register an RPC handler for a specific method
|
|
1001
1077
|
* @param method - The method name (without prefix)
|
|
@@ -1073,7 +1149,7 @@ class RpcHandlerManager {
|
|
|
1073
1149
|
}
|
|
1074
1150
|
}
|
|
1075
1151
|
|
|
1076
|
-
const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
1152
|
+
const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-0ILrOpLt.cjs', document.baseURI).href))));
|
|
1077
1153
|
function projectPath() {
|
|
1078
1154
|
const path$1 = path.resolve(__dirname$1, "..");
|
|
1079
1155
|
return path$1;
|
|
@@ -1171,10 +1247,13 @@ function registerCommonHandlers(rpcHandlerManager) {
|
|
|
1171
1247
|
rpcHandlerManager.registerHandler("bash", async (data) => {
|
|
1172
1248
|
logger.debug("Shell command request:", data.command);
|
|
1173
1249
|
try {
|
|
1250
|
+
const sessionContext = rpcHandlerManager.getSessionContext();
|
|
1174
1251
|
const options = {
|
|
1175
1252
|
cwd: data.cwd,
|
|
1176
|
-
timeout: data.timeout || 3e4
|
|
1253
|
+
timeout: data.timeout || 3e4,
|
|
1177
1254
|
// Default 30 seconds timeout
|
|
1255
|
+
// Use session environment if available, otherwise inherit process.env
|
|
1256
|
+
env: sessionContext?.env ?? process.env
|
|
1178
1257
|
};
|
|
1179
1258
|
const { stdout, stderr } = await execAsync(data.command, options);
|
|
1180
1259
|
return {
|
|
@@ -1704,6 +1783,60 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1704
1783
|
logger.debug("[API] socket.close() called");
|
|
1705
1784
|
this.socket.close();
|
|
1706
1785
|
}
|
|
1786
|
+
/**
|
|
1787
|
+
* Download and decrypt a blob from the server
|
|
1788
|
+
* @param blobId - The blob ID to download
|
|
1789
|
+
* @returns The decrypted binary data and metadata, or null if download/decryption fails
|
|
1790
|
+
*/
|
|
1791
|
+
async downloadBlob(blobId) {
|
|
1792
|
+
try {
|
|
1793
|
+
const response = await axios.get(
|
|
1794
|
+
`${configuration.serverUrl}/v1/sessions/${this.sessionId}/blobs/${blobId}`,
|
|
1795
|
+
{
|
|
1796
|
+
headers: {
|
|
1797
|
+
"Authorization": `Bearer ${this.token}`
|
|
1798
|
+
},
|
|
1799
|
+
responseType: "arraybuffer"
|
|
1800
|
+
}
|
|
1801
|
+
);
|
|
1802
|
+
const encryptedData = new Uint8Array(response.data);
|
|
1803
|
+
const mimeType = response.headers["x-blob-mimetype"];
|
|
1804
|
+
const originalSize = parseInt(response.headers["x-blob-size"], 10);
|
|
1805
|
+
const decryptedData = decryptBlob(this.encryptionKey, this.encryptionVariant, encryptedData);
|
|
1806
|
+
if (!decryptedData) {
|
|
1807
|
+
logger.debug("[API] Failed to decrypt blob");
|
|
1808
|
+
return null;
|
|
1809
|
+
}
|
|
1810
|
+
return {
|
|
1811
|
+
data: decryptedData,
|
|
1812
|
+
mimeType,
|
|
1813
|
+
size: originalSize
|
|
1814
|
+
};
|
|
1815
|
+
} catch (error) {
|
|
1816
|
+
logger.debug("[API] Failed to download blob:", error);
|
|
1817
|
+
return null;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* Convert an image_ref content block to a Claude API image content block
|
|
1822
|
+
* Downloads, decrypts, and base64 encodes the image
|
|
1823
|
+
* @param imageRef - The image reference content block
|
|
1824
|
+
* @returns Claude API image content block, or null if conversion fails
|
|
1825
|
+
*/
|
|
1826
|
+
async resolveImageRef(imageRef) {
|
|
1827
|
+
const blob = await this.downloadBlob(imageRef.blobId);
|
|
1828
|
+
if (!blob) {
|
|
1829
|
+
return null;
|
|
1830
|
+
}
|
|
1831
|
+
return {
|
|
1832
|
+
type: "image",
|
|
1833
|
+
source: {
|
|
1834
|
+
type: "base64",
|
|
1835
|
+
media_type: blob.mimeType,
|
|
1836
|
+
data: Buffer.from(blob.data).toString("base64")
|
|
1837
|
+
}
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1707
1840
|
}
|
|
1708
1841
|
|
|
1709
1842
|
class ApiMachineClient {
|