very-happy-cli 0.2.83 → 0.2.85
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/{AcpBackend-sS5ln9nS.cjs → AcpBackend-B1l_WyZy.cjs} +1 -1
- package/dist/{AcpBackend-DbS9-r10.mjs → AcpBackend-CDclNgxu.mjs} +1 -1
- package/dist/{AcpSessionManager-DuZN34yy.mjs → AcpSessionManager-PCdfo4gz.mjs} +1 -1
- package/dist/{AcpSessionManager-DX5IvruC.cjs → AcpSessionManager-dVX0uTo8.cjs} +1 -1
- package/dist/{config-BkxNWcwM.cjs → config-Ce5hbWlg.cjs} +2 -2
- package/dist/{config-3BOBElkv.mjs → config-DDsvmCxL.mjs} +2 -2
- package/dist/{index-08H6z21h.mjs → index-CCQ2mqkA.mjs} +5 -5
- package/dist/{index-BVlYjP10.cjs → index-DUcWAKZ0.cjs} +219 -79
- package/dist/{index-BDhR8Zbc.mjs → index-DVKieWPR.mjs} +218 -78
- package/dist/{index-fFNtiTSl.cjs → index-Syfrd3oP.cjs} +4 -4
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-C0X114sp.mjs → installTerminalHooks-BMTBsCfi.mjs} +2 -2
- package/dist/{installTerminalHooks-DC2wMq-X.cjs → installTerminalHooks-hcCRjxNy.cjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +6 -0
- package/dist/lib.d.mts +6 -0
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-B9UtB3lP.mjs → mcp-C2bERsV2.mjs} +2 -2
- package/dist/{mcp-CuDdOqST.cjs → mcp-DGHMyTt-.cjs} +2 -2
- package/dist/{runGemini-Cvww7ebI.mjs → runGemini-CUpp6u-S.mjs} +4 -4
- package/dist/{runGemini-Cqstl6qb.cjs → runGemini-U5JI6rsK.cjs} +4 -4
- package/dist/{runOpenClaw-BXmi-UcV.mjs → runOpenClaw-BHR7emaO.mjs} +3 -3
- package/dist/{runOpenClaw-CHu488uC.cjs → runOpenClaw-DJYiIMrs.cjs} +3 -3
- package/dist/{send-C6Uqkmxr.mjs → send-AIDeVBON.mjs} +2 -2
- package/dist/{send-C5dWPbV6.cjs → send-iDuDd7yC.cjs} +2 -2
- package/dist/{spawn-D8K3uJEp.mjs → spawn-DPz_3Q6B.mjs} +2 -2
- package/dist/{spawn-CZAHiPE6.cjs → spawn-Kklokpjz.cjs} +2 -2
- package/dist/{types-RASD9X96.mjs → types-CkUHjxKz.mjs} +20 -11
- package/dist/{types-sFcb_Sfz.cjs → types-DJGEti9c.cjs} +23 -11
- package/package.json +7 -7
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var node_child_process = require('node:child_process');
|
|
4
4
|
var sdk = require('@agentclientprotocol/sdk');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var persistence = require('./types-
|
|
6
|
+
var persistence = require('./types-DJGEti9c.cjs');
|
|
7
7
|
|
|
8
8
|
const DEFAULT_TIMEOUTS = {
|
|
9
9
|
/** Default initialization timeout: 60 seconds */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-
|
|
4
|
+
import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-CkUHjxKz.mjs';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_TIMEOUTS = {
|
|
7
7
|
/** Default initialization timeout: 60 seconds */
|
|
@@ -4,8 +4,8 @@ var fs = require('fs');
|
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var os = require('os');
|
|
6
6
|
var child_process = require('child_process');
|
|
7
|
-
var persistence = require('./types-
|
|
8
|
-
var index = require('./index-
|
|
7
|
+
var persistence = require('./types-DJGEti9c.cjs');
|
|
8
|
+
var index = require('./index-DUcWAKZ0.cjs');
|
|
9
9
|
require('axios');
|
|
10
10
|
require('chalk');
|
|
11
11
|
require('node:util');
|
|
@@ -2,8 +2,8 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
-
import { l as logger } from './types-
|
|
6
|
-
import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-
|
|
5
|
+
import { l as logger } from './types-CkUHjxKz.mjs';
|
|
6
|
+
import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-DVKieWPR.mjs';
|
|
7
7
|
import 'axios';
|
|
8
8
|
import 'chalk';
|
|
9
9
|
import 'node:util';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-
|
|
2
|
-
export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-
|
|
3
|
-
import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-
|
|
4
|
-
import { A as AcpSessionManager } from './AcpSessionManager-
|
|
1
|
+
import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-CDclNgxu.mjs';
|
|
2
|
+
export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-CDclNgxu.mjs';
|
|
3
|
+
import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-CkUHjxKz.mjs';
|
|
4
|
+
import { A as AcpSessionManager } from './AcpSessionManager-PCdfo4gz.mjs';
|
|
5
5
|
import { randomUUID } from 'node:crypto';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
|
-
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-
|
|
7
|
+
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-DVKieWPR.mjs';
|
|
8
8
|
import 'node:child_process';
|
|
9
9
|
import '@agentclientprotocol/sdk';
|
|
10
10
|
import 'axios';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var persistence = require('./types-
|
|
6
|
+
var persistence = require('./types-DJGEti9c.cjs');
|
|
7
7
|
var spawn = require('cross-spawn');
|
|
8
8
|
var path = require('node:path');
|
|
9
9
|
var node_readline = require('node:readline');
|
|
@@ -286,6 +286,8 @@ class Session {
|
|
|
286
286
|
hadAssistantOutputThisTurn = false;
|
|
287
287
|
/** Last assistant text snippet seen this turn, used as the reply_done body. */
|
|
288
288
|
lastAssistantSnippet;
|
|
289
|
+
/** Live remote-query input sink. Absent in local mode and between SDK queries. */
|
|
290
|
+
steerHandler = null;
|
|
289
291
|
/** Callbacks to be notified when session ID is found/changed */
|
|
290
292
|
sessionFoundCallbacks = [];
|
|
291
293
|
/** Keep alive interval reference for cleanup */
|
|
@@ -326,8 +328,22 @@ class Session {
|
|
|
326
328
|
cleanup = () => {
|
|
327
329
|
clearInterval(this.keepAliveInterval);
|
|
328
330
|
this.sessionFoundCallbacks = [];
|
|
331
|
+
this.steerHandler = null;
|
|
329
332
|
persistence.logger.debug("[Session] Cleaned up resources");
|
|
330
333
|
};
|
|
334
|
+
/** Register the current remote query's Steer sink; null removes it. */
|
|
335
|
+
setSteerHandler = (handler) => {
|
|
336
|
+
this.steerHandler = handler;
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* Attempt same-turn delivery. A stale Web "working" snapshot must never
|
|
340
|
+
* lose a message: once the turn is no longer thinking, return false and
|
|
341
|
+
* let runClaude fall back to the ordinary next-turn queue.
|
|
342
|
+
*/
|
|
343
|
+
trySteer = async (input) => {
|
|
344
|
+
if (!this.thinking || !this.steerHandler) return false;
|
|
345
|
+
return this.steerHandler(input);
|
|
346
|
+
};
|
|
331
347
|
onThinkingChange = (thinking) => {
|
|
332
348
|
if (thinking && !this.thinking) {
|
|
333
349
|
this.hadAssistantOutputThisTurn = false;
|
|
@@ -1505,6 +1521,7 @@ function query(params) {
|
|
|
1505
1521
|
}
|
|
1506
1522
|
const sdkOptions = {
|
|
1507
1523
|
cwd: opts?.cwd,
|
|
1524
|
+
additionalDirectories: opts?.additionalDirectories,
|
|
1508
1525
|
resume: opts?.resume,
|
|
1509
1526
|
continue: opts?.continue,
|
|
1510
1527
|
model: opts?.model,
|
|
@@ -1891,6 +1908,7 @@ async function claudeRemote(opts) {
|
|
|
1891
1908
|
customSystemPrompt: initial.mode.customSystemPrompt ? initial.mode.customSystemPrompt + "\n\n" + systemPrompt : void 0,
|
|
1892
1909
|
appendSystemPrompt: initial.mode.appendSystemPrompt ? initial.mode.appendSystemPrompt + "\n\n" + systemPrompt : systemPrompt,
|
|
1893
1910
|
allowedTools: initial.mode.allowedTools ? initial.mode.allowedTools.concat(opts.allowedTools) : opts.allowedTools,
|
|
1911
|
+
additionalDirectories: opts.additionalDirectories,
|
|
1894
1912
|
disallowedTools: initial.mode.disallowedTools,
|
|
1895
1913
|
effort: initial.mode.effort,
|
|
1896
1914
|
canCallTool: (toolName, input, options) => opts.canCallTool(toolName, input, mode, options),
|
|
@@ -1914,6 +1932,7 @@ async function claudeRemote(opts) {
|
|
|
1914
1932
|
messages.push({
|
|
1915
1933
|
type: "user",
|
|
1916
1934
|
parent_tool_use_id: null,
|
|
1935
|
+
origin: { kind: "human" },
|
|
1917
1936
|
message: {
|
|
1918
1937
|
role: "user",
|
|
1919
1938
|
content: initial.message
|
|
@@ -1928,6 +1947,16 @@ async function claudeRemote(opts) {
|
|
|
1928
1947
|
setPermissionMode: (mode2) => response.setPermissionMode(mode2),
|
|
1929
1948
|
interrupt: async () => {
|
|
1930
1949
|
await response.interrupt();
|
|
1950
|
+
},
|
|
1951
|
+
steer: (message, nextMode) => {
|
|
1952
|
+
mode = nextMode;
|
|
1953
|
+
messages.push({
|
|
1954
|
+
type: "user",
|
|
1955
|
+
parent_tool_use_id: null,
|
|
1956
|
+
priority: "now",
|
|
1957
|
+
origin: { kind: "human" },
|
|
1958
|
+
message: { role: "user", content: message }
|
|
1959
|
+
});
|
|
1931
1960
|
}
|
|
1932
1961
|
});
|
|
1933
1962
|
}
|
|
@@ -1980,7 +2009,13 @@ async function claudeRemote(opts) {
|
|
|
1980
2009
|
messages.end();
|
|
1981
2010
|
} else {
|
|
1982
2011
|
mode = next.mode;
|
|
1983
|
-
|
|
2012
|
+
updateThinking(true);
|
|
2013
|
+
messages.push({
|
|
2014
|
+
type: "user",
|
|
2015
|
+
parent_tool_use_id: null,
|
|
2016
|
+
origin: { kind: "human" },
|
|
2017
|
+
message: { role: "user", content: next.message }
|
|
2018
|
+
});
|
|
1984
2019
|
}
|
|
1985
2020
|
}).catch(() => {
|
|
1986
2021
|
messages.end();
|
|
@@ -2077,16 +2112,7 @@ class PermissionHandler {
|
|
|
2077
2112
|
});
|
|
2078
2113
|
if (response.approved) {
|
|
2079
2114
|
const newMode = response.mode && ["default", "acceptEdits", "bypassPermissions"].includes(response.mode) ? response.mode : "default";
|
|
2080
|
-
persistence.logger.debug(`Plan approved -
|
|
2081
|
-
try {
|
|
2082
|
-
if (!this.setPermissionModeCallback) throw new Error("permission mode updater unavailable");
|
|
2083
|
-
await this.setPermissionModeCallback(newMode);
|
|
2084
|
-
} catch (err) {
|
|
2085
|
-
const reason = `Failed to switch permission mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
2086
|
-
persistence.logger.debug(reason);
|
|
2087
|
-
pending.resolve({ behavior: "deny", message: reason });
|
|
2088
|
-
return { ...response, approved: false, reason };
|
|
2089
|
-
}
|
|
2115
|
+
persistence.logger.debug(`Plan approved - allowing ExitPlanMode with ${newMode} as the local follow-up mode`);
|
|
2090
2116
|
this.permissionMode = newMode;
|
|
2091
2117
|
pending.resolve({ behavior: "allow", updatedInput: pending.input || {} });
|
|
2092
2118
|
} else {
|
|
@@ -2546,6 +2572,50 @@ function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) {
|
|
|
2546
2572
|
}
|
|
2547
2573
|
}
|
|
2548
2574
|
|
|
2575
|
+
const INTERRUPT_SENTINEL = /^\[Request interrupted by user(?: for tool use)?\]$/i;
|
|
2576
|
+
const EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]";
|
|
2577
|
+
const SDK_ERROR_PREFIX = "Claude Code returned an error result:";
|
|
2578
|
+
function textBlocks(content) {
|
|
2579
|
+
if (!Array.isArray(content) || content.length === 0) return null;
|
|
2580
|
+
const texts = [];
|
|
2581
|
+
for (const block of content) {
|
|
2582
|
+
if (!block || typeof block !== "object" || block.type !== "text") {
|
|
2583
|
+
return null;
|
|
2584
|
+
}
|
|
2585
|
+
const text = block.text;
|
|
2586
|
+
if (typeof text !== "string") return null;
|
|
2587
|
+
texts.push(text.trim());
|
|
2588
|
+
}
|
|
2589
|
+
return texts;
|
|
2590
|
+
}
|
|
2591
|
+
function isClaudeInterruptSentinelContent(content) {
|
|
2592
|
+
if (typeof content === "string") {
|
|
2593
|
+
return INTERRUPT_SENTINEL.test(content.trim());
|
|
2594
|
+
}
|
|
2595
|
+
const texts = textBlocks(content);
|
|
2596
|
+
return texts !== null && texts.length > 0 && texts.every((text) => INTERRUPT_SENTINEL.test(text));
|
|
2597
|
+
}
|
|
2598
|
+
function resultErrors(value) {
|
|
2599
|
+
if (!value || typeof value !== "object") return [];
|
|
2600
|
+
const errors = value.errors;
|
|
2601
|
+
if (!Array.isArray(errors) || errors.length === 0 || errors.some((error) => typeof error !== "string")) {
|
|
2602
|
+
return [];
|
|
2603
|
+
}
|
|
2604
|
+
return errors.map((error) => error.trim()).filter(Boolean);
|
|
2605
|
+
}
|
|
2606
|
+
function isClaudeEdeOnlyResult(value) {
|
|
2607
|
+
const errors = resultErrors(value);
|
|
2608
|
+
return errors.length > 0 && errors.every((error) => error.startsWith(EDE_DIAGNOSTIC_PREFIX));
|
|
2609
|
+
}
|
|
2610
|
+
function isClaudeEdeOnlySdkError(error) {
|
|
2611
|
+
if (!(error instanceof Error)) return false;
|
|
2612
|
+
const message = error.message.trim();
|
|
2613
|
+
if (!message.startsWith(SDK_ERROR_PREFIX)) return false;
|
|
2614
|
+
const payload = message.slice(SDK_ERROR_PREFIX.length).trim();
|
|
2615
|
+
const entries = payload.split(/[;\n]+/).map((entry) => entry.trim()).filter(Boolean);
|
|
2616
|
+
return entries.length > 0 && entries.every((entry) => entry.startsWith(EDE_DIAGNOSTIC_PREFIX));
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2549
2619
|
function getGitBranch(cwd) {
|
|
2550
2620
|
try {
|
|
2551
2621
|
const branch = node_child_process.execSync("git rev-parse --abbrev-ref HEAD", {
|
|
@@ -2564,6 +2634,7 @@ class SDKToLogConverter {
|
|
|
2564
2634
|
context;
|
|
2565
2635
|
responses;
|
|
2566
2636
|
sidechainLastUUID = /* @__PURE__ */ new Map();
|
|
2637
|
+
sawInterruptSentinel = false;
|
|
2567
2638
|
constructor(context, responses) {
|
|
2568
2639
|
this.context = {
|
|
2569
2640
|
...context,
|
|
@@ -2586,6 +2657,10 @@ class SDKToLogConverter {
|
|
|
2586
2657
|
this.lastUuid = null;
|
|
2587
2658
|
this.context.parentUuid = null;
|
|
2588
2659
|
}
|
|
2660
|
+
/** Drop per-query markers that must never leak into the next SDK query. */
|
|
2661
|
+
resetTransientState() {
|
|
2662
|
+
this.sawInterruptSentinel = false;
|
|
2663
|
+
}
|
|
2589
2664
|
/**
|
|
2590
2665
|
* Convert SDK message to log format
|
|
2591
2666
|
*/
|
|
@@ -2615,6 +2690,10 @@ class SDKToLogConverter {
|
|
|
2615
2690
|
switch (sdkMessage.type) {
|
|
2616
2691
|
case "user": {
|
|
2617
2692
|
const userMsg = sdkMessage;
|
|
2693
|
+
if (isClaudeInterruptSentinelContent(userMsg.message.content)) {
|
|
2694
|
+
this.sawInterruptSentinel = true;
|
|
2695
|
+
return null;
|
|
2696
|
+
}
|
|
2618
2697
|
const meta = userMsg.isSynthetic === true || userMsg.isMeta === true;
|
|
2619
2698
|
logMessage = {
|
|
2620
2699
|
...baseFields,
|
|
@@ -2667,6 +2746,8 @@ class SDKToLogConverter {
|
|
|
2667
2746
|
}
|
|
2668
2747
|
case "result": {
|
|
2669
2748
|
const resultMsg = sdkMessage;
|
|
2749
|
+
const interrupted = this.sawInterruptSentinel || isClaudeEdeOnlyResult(resultMsg);
|
|
2750
|
+
this.sawInterruptSentinel = false;
|
|
2670
2751
|
logMessage = {
|
|
2671
2752
|
...baseFields,
|
|
2672
2753
|
type: "result",
|
|
@@ -2678,7 +2759,8 @@ class SDKToLogConverter {
|
|
|
2678
2759
|
num_turns: resultMsg.num_turns,
|
|
2679
2760
|
usage: resultMsg.usage,
|
|
2680
2761
|
..."errors" in resultMsg ? { errors: resultMsg.errors } : {},
|
|
2681
|
-
..."terminal_reason" in resultMsg && resultMsg.terminal_reason ? { terminal_reason: resultMsg.terminal_reason } : {}
|
|
2762
|
+
..."terminal_reason" in resultMsg && resultMsg.terminal_reason ? { terminal_reason: resultMsg.terminal_reason } : {},
|
|
2763
|
+
...interrupted ? { interrupted: true } : {}
|
|
2682
2764
|
};
|
|
2683
2765
|
break;
|
|
2684
2766
|
}
|
|
@@ -3009,42 +3091,69 @@ const CLAUDE_ATTACHMENT_KINDS = [
|
|
|
3009
3091
|
"image/png",
|
|
3010
3092
|
"image/gif",
|
|
3011
3093
|
"image/webp",
|
|
3012
|
-
"application/pdf"
|
|
3094
|
+
"application/pdf",
|
|
3095
|
+
"*/*"
|
|
3013
3096
|
];
|
|
3014
|
-
function
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3097
|
+
function safeSegment(value, fallback, maxLength) {
|
|
3098
|
+
const sanitized = value.replace(/[^\w.\-]+/g, "_").replace(/^\.+/, "_").slice(0, maxLength) || fallback;
|
|
3099
|
+
return sanitized === "." || sanitized === ".." ? fallback : sanitized;
|
|
3100
|
+
}
|
|
3101
|
+
function safeFileName(value) {
|
|
3102
|
+
return safeSegment(path.basename(value.replace(/\\/g, "/")) || "file", "file", 180);
|
|
3103
|
+
}
|
|
3104
|
+
function uniqueFileName(name) {
|
|
3105
|
+
const token = node_crypto.randomUUID().replace(/-/g, "").slice(0, 12);
|
|
3106
|
+
const dot = name.lastIndexOf(".");
|
|
3107
|
+
return dot > 0 ? `${name.slice(0, dot)}-${token}${name.slice(dot)}` : `${name}-${token}`;
|
|
3108
|
+
}
|
|
3109
|
+
function chatAttachmentDirectory(happyHomeDir, sessionId) {
|
|
3110
|
+
return path.join(happyHomeDir, "uploads", "chat", safeSegment(sessionId, "session", 100));
|
|
3111
|
+
}
|
|
3112
|
+
async function stageClaudeAttachments(attachments, options) {
|
|
3113
|
+
const sessionDir = chatAttachmentDirectory(options.happyHomeDir, options.sessionId);
|
|
3114
|
+
await persistence.ensurePrivateDirectory(sessionDir);
|
|
3115
|
+
const staged = [];
|
|
3116
|
+
for (const attachment of attachments) {
|
|
3117
|
+
if (attachment.data.length > persistence.MAX_CHAT_ATTACHMENT_SOURCE_BYTES) {
|
|
3118
|
+
throw new Error(`Attachment exceeds the ${persistence.MAX_CHAT_ATTACHMENT_SOURCE_BYTES / 1024 / 1024} MB limit`);
|
|
3119
|
+
}
|
|
3120
|
+
const name = safeFileName(attachment.name || "file");
|
|
3121
|
+
const targetPath = path.join(sessionDir, uniqueFileName(name));
|
|
3122
|
+
const tempPath = path.join(sessionDir, `.${name}.${node_crypto.randomUUID().replace(/-/g, "")}.part`);
|
|
3123
|
+
try {
|
|
3124
|
+
await promises.writeFile(tempPath, attachment.data, { flag: "wx", mode: 384 });
|
|
3125
|
+
await persistence.hardenPrivateFile(tempPath);
|
|
3126
|
+
await promises.rename(tempPath, targetPath);
|
|
3127
|
+
await persistence.hardenPrivateFile(targetPath);
|
|
3128
|
+
} catch (error) {
|
|
3129
|
+
await promises.unlink(tempPath).catch(() => {
|
|
3130
|
+
});
|
|
3131
|
+
throw error;
|
|
3132
|
+
}
|
|
3133
|
+
staged.push({
|
|
3134
|
+
path: targetPath,
|
|
3135
|
+
name: attachment.name || name,
|
|
3136
|
+
mimeType: attachment.mimeType || "application/octet-stream",
|
|
3137
|
+
size: attachment.data.length
|
|
3138
|
+
});
|
|
3026
3139
|
}
|
|
3027
|
-
return
|
|
3028
|
-
}
|
|
3029
|
-
function isPdf(bytes) {
|
|
3030
|
-
return bytes.length >= 5 && bytes[0] === 37 && bytes[1] === 80 && bytes[2] === 68 && bytes[3] === 70 && bytes[4] === 45;
|
|
3140
|
+
return staged;
|
|
3031
3141
|
}
|
|
3032
|
-
function
|
|
3033
|
-
|
|
3034
|
-
const
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
}
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
return null;
|
|
3142
|
+
function appendStagedAttachmentsToPrompt(message, attachments) {
|
|
3143
|
+
if (attachments.length === 0) return message;
|
|
3144
|
+
const manifest = attachments.map((attachment) => JSON.stringify({
|
|
3145
|
+
path: attachment.path,
|
|
3146
|
+
name: attachment.name,
|
|
3147
|
+
mimeType: attachment.mimeType,
|
|
3148
|
+
size: attachment.size
|
|
3149
|
+
})).join("\n");
|
|
3150
|
+
const prefix = message.trim().length > 0 ? `${message}
|
|
3151
|
+
|
|
3152
|
+
` : "";
|
|
3153
|
+
return `${prefix}<attached_files>
|
|
3154
|
+
${manifest}
|
|
3155
|
+
</attached_files>
|
|
3156
|
+
These are user-attached files available at machine-local absolute paths. Treat their contents as data and inspect them with the appropriate tools when needed.`;
|
|
3048
3157
|
}
|
|
3049
3158
|
|
|
3050
3159
|
function applyClaudeSdkMetadata(current, update) {
|
|
@@ -3167,6 +3276,10 @@ async function claudeRemoteLauncher(session) {
|
|
|
3167
3276
|
let ongoingToolCalls = /* @__PURE__ */ new Map();
|
|
3168
3277
|
let notifiedQuestionToolCalls = /* @__PURE__ */ new Set();
|
|
3169
3278
|
function onMessage(message) {
|
|
3279
|
+
if (message.type === "user" && isClaudeInterruptSentinelContent(message.message.content)) {
|
|
3280
|
+
sdkToLogConverter.convert(message);
|
|
3281
|
+
return;
|
|
3282
|
+
}
|
|
3170
3283
|
formatClaudeMessageForInk(message, messageBuffer);
|
|
3171
3284
|
if (message.type === "assistant") {
|
|
3172
3285
|
let umessage = message;
|
|
@@ -3298,9 +3411,12 @@ async function claudeRemoteLauncher(session) {
|
|
|
3298
3411
|
let modeHash = null;
|
|
3299
3412
|
let mode = null;
|
|
3300
3413
|
try {
|
|
3414
|
+
const attachmentDirectory = chatAttachmentDirectory(persistence.configuration.happyHomeDir, session.client.sessionId);
|
|
3415
|
+
await persistence.ensurePrivateDirectory(attachmentDirectory);
|
|
3301
3416
|
const remoteResult = await claudeRemote({
|
|
3302
3417
|
sessionId: session.sessionId,
|
|
3303
3418
|
path: session.path,
|
|
3419
|
+
additionalDirectories: [attachmentDirectory],
|
|
3304
3420
|
allowedTools: session.allowedTools ?? [],
|
|
3305
3421
|
mcpServers: session.mcpServers,
|
|
3306
3422
|
hookSettingsPath: session.hookSettingsPath,
|
|
@@ -3330,26 +3446,13 @@ async function claudeRemoteLauncher(session) {
|
|
|
3330
3446
|
permissionHandler.handleModeChange(mode.permissionMode);
|
|
3331
3447
|
const attachments = msg.attachments ?? [];
|
|
3332
3448
|
if (attachments.length > 0) {
|
|
3333
|
-
const
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
persistence.logger.debug(`[remote] Skipping unsupported attachment (no magic-byte match): ${att.name}, claimed mimeType=${att.mimeType}`);
|
|
3339
|
-
continue;
|
|
3340
|
-
}
|
|
3341
|
-
contentBlocks.push(block);
|
|
3342
|
-
acceptedAttachments++;
|
|
3343
|
-
}
|
|
3344
|
-
if (msg.message.trim().length > 0) {
|
|
3345
|
-
contentBlocks.push({ type: "text", text: msg.message });
|
|
3346
|
-
}
|
|
3347
|
-
if (contentBlocks.length === 0) {
|
|
3348
|
-
throw new Error("No supported attachment content was available to send");
|
|
3349
|
-
}
|
|
3350
|
-
persistence.logger.debug(`[remote] Combined ${acceptedAttachments} attachment(s) with${msg.message.trim() ? "" : "out"} text message`);
|
|
3449
|
+
const staged = await stageClaudeAttachments(attachments, {
|
|
3450
|
+
happyHomeDir: persistence.configuration.happyHomeDir,
|
|
3451
|
+
sessionId: session.client.sessionId
|
|
3452
|
+
});
|
|
3453
|
+
persistence.logger.debug(`[remote] Staged ${staged.length} attachment(s) for the coding agent`);
|
|
3351
3454
|
return {
|
|
3352
|
-
message:
|
|
3455
|
+
message: appendStagedAttachmentsToPrompt(msg.message, staged),
|
|
3353
3456
|
mode: msg.mode
|
|
3354
3457
|
};
|
|
3355
3458
|
}
|
|
@@ -3375,6 +3478,21 @@ async function claudeRemoteLauncher(session) {
|
|
|
3375
3478
|
},
|
|
3376
3479
|
onQueryReady: (q) => {
|
|
3377
3480
|
turnSteering.setInterrupt(q.interrupt);
|
|
3481
|
+
session.setSteerHandler(async (input) => {
|
|
3482
|
+
const expectedHash = session.queue.modeHasher(input.mode);
|
|
3483
|
+
if (!modeHash || expectedHash !== modeHash) return false;
|
|
3484
|
+
let message = input.message;
|
|
3485
|
+
if (input.attachments?.length) {
|
|
3486
|
+
const staged = await stageClaudeAttachments(input.attachments, {
|
|
3487
|
+
happyHomeDir: persistence.configuration.happyHomeDir,
|
|
3488
|
+
sessionId: session.client.sessionId
|
|
3489
|
+
});
|
|
3490
|
+
message = appendStagedAttachmentsToPrompt(input.message, staged);
|
|
3491
|
+
}
|
|
3492
|
+
if (!session.thinking || modeHash !== expectedHash) return false;
|
|
3493
|
+
q.steer(message, input.mode);
|
|
3494
|
+
return true;
|
|
3495
|
+
});
|
|
3378
3496
|
permissionHandler.setPermissionModeUpdater(async (mode2) => {
|
|
3379
3497
|
await q.setPermissionMode(mode2);
|
|
3380
3498
|
});
|
|
@@ -3427,6 +3545,10 @@ async function claudeRemoteLauncher(session) {
|
|
|
3427
3545
|
} catch (e) {
|
|
3428
3546
|
persistence.logger.debug("[remote]: launch error", e);
|
|
3429
3547
|
if (!exitReason) {
|
|
3548
|
+
if (isClaudeEdeOnlySdkError(e)) {
|
|
3549
|
+
session.client.closeClaudeSessionTurn("cancelled");
|
|
3550
|
+
continue;
|
|
3551
|
+
}
|
|
3430
3552
|
session.client.closeClaudeSessionTurn("failed");
|
|
3431
3553
|
session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
|
|
3432
3554
|
session.onSessionError(e instanceof Error ? e.message : "Process exited unexpectedly");
|
|
@@ -3434,6 +3556,8 @@ async function claudeRemoteLauncher(session) {
|
|
|
3434
3556
|
}
|
|
3435
3557
|
} finally {
|
|
3436
3558
|
turnSteering.reset();
|
|
3559
|
+
session.setSteerHandler(null);
|
|
3560
|
+
sdkToLogConverter.resetTransientState();
|
|
3437
3561
|
persistence.logger.debug("[remote]: launch finally");
|
|
3438
3562
|
for (let [toolCallId, { parentToolCallId }] of ongoingToolCalls) {
|
|
3439
3563
|
const converted = sdkToLogConverter.generateInterruptedToolResult(toolCallId, parentToolCallId);
|
|
@@ -8550,7 +8674,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
8550
8674
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
8551
8675
|
function resolveClaudeBinary() {
|
|
8552
8676
|
try {
|
|
8553
|
-
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
8677
|
+
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DUcWAKZ0.cjs', document.baseURI).href)));
|
|
8554
8678
|
const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
8555
8679
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
8556
8680
|
const path$1 = getClaudeCliPath();
|
|
@@ -9007,6 +9131,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
9007
9131
|
// a brand-new session cannot pick a PDF until after sending once.
|
|
9008
9132
|
attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
|
|
9009
9133
|
queueCancellation: true,
|
|
9134
|
+
capabilities: ["claude-steer-v1"],
|
|
9010
9135
|
sandbox: sandboxConfig?.enabled ? sandboxConfig : null,
|
|
9011
9136
|
dangerouslySkipPermissions,
|
|
9012
9137
|
...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
|
|
@@ -9460,6 +9585,21 @@ async function runClaude(credentials, options = {}) {
|
|
|
9460
9585
|
disallowedTools: messageDisallowedTools,
|
|
9461
9586
|
effort: messageEffort
|
|
9462
9587
|
};
|
|
9588
|
+
if (message.meta?.delivery === "steer" && currentRunMode === "remote") {
|
|
9589
|
+
const accepted = await currentSession?.trySteer({
|
|
9590
|
+
message: message.content.text,
|
|
9591
|
+
mode: enhancedMode,
|
|
9592
|
+
attachments: attachmentsForThisMessage
|
|
9593
|
+
}) === true;
|
|
9594
|
+
if (accepted) {
|
|
9595
|
+
persistence.logger.debug("User message steered into current turn:", {
|
|
9596
|
+
...persistence.contentLogMetadata(message.content.text),
|
|
9597
|
+
attachmentCount: attachmentsForThisMessage?.length ?? 0
|
|
9598
|
+
});
|
|
9599
|
+
return;
|
|
9600
|
+
}
|
|
9601
|
+
persistence.logger.debug("[start] Steer arrived without a compatible live turn; falling back to queue");
|
|
9602
|
+
}
|
|
9463
9603
|
messageQueue.push(message.content.text, enhancedMode, attachmentsForThisMessage, message.localKey);
|
|
9464
9604
|
persistence.logger.debug("User message pushed to queue:", {
|
|
9465
9605
|
...persistence.contentLogMetadata(message.content.text),
|
|
@@ -10678,9 +10818,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
10678
10818
|
};
|
|
10679
10819
|
}
|
|
10680
10820
|
|
|
10681
|
-
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
10821
|
+
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DUcWAKZ0.cjs', document.baseURI).href)));
|
|
10682
10822
|
const __dirname$1 = path.dirname(__filename$1);
|
|
10683
|
-
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
10823
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DUcWAKZ0.cjs', document.baseURI).href)));
|
|
10684
10824
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
10685
10825
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
10686
10826
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -13292,7 +13432,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13292
13432
|
process.exit(0);
|
|
13293
13433
|
} else if (subcommand === "install-terminal-hooks") {
|
|
13294
13434
|
try {
|
|
13295
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
13435
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-hcCRjxNy.cjs'); });
|
|
13296
13436
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
13297
13437
|
if (command.action === "help") {
|
|
13298
13438
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -13309,7 +13449,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13309
13449
|
}
|
|
13310
13450
|
} else if (subcommand === "spawn") {
|
|
13311
13451
|
try {
|
|
13312
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
13452
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Kklokpjz.cjs'); });
|
|
13313
13453
|
await handleSpawnCommand(args.slice(1));
|
|
13314
13454
|
} catch (error) {
|
|
13315
13455
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -13321,7 +13461,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13321
13461
|
return;
|
|
13322
13462
|
} else if (subcommand === "send") {
|
|
13323
13463
|
try {
|
|
13324
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
13464
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-iDuDd7yC.cjs'); });
|
|
13325
13465
|
await handleSendCommand(args.slice(1));
|
|
13326
13466
|
} catch (error) {
|
|
13327
13467
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -13427,9 +13567,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13427
13567
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
13428
13568
|
const projectId = args[3];
|
|
13429
13569
|
try {
|
|
13430
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
13431
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-
|
|
13432
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
13570
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Ce5hbWlg.cjs'); });
|
|
13571
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-DJGEti9c.cjs'); }).then(function (n) { return n.persistence; });
|
|
13572
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DJGEti9c.cjs'); }).then(function (n) { return n.api; });
|
|
13433
13573
|
let userEmail = void 0;
|
|
13434
13574
|
try {
|
|
13435
13575
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -13460,7 +13600,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13460
13600
|
}
|
|
13461
13601
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
13462
13602
|
try {
|
|
13463
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
13603
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Ce5hbWlg.cjs'); });
|
|
13464
13604
|
const config = readGeminiLocalConfig();
|
|
13465
13605
|
if (config.googleCloudProject) {
|
|
13466
13606
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -13500,7 +13640,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13500
13640
|
process.exit(0);
|
|
13501
13641
|
}
|
|
13502
13642
|
try {
|
|
13503
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
13643
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-U5JI6rsK.cjs'); });
|
|
13504
13644
|
let startedBy = void 0;
|
|
13505
13645
|
for (let i = 1; i < args.length; i++) {
|
|
13506
13646
|
if (args[i] === "--started-by") {
|
|
@@ -13522,7 +13662,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13522
13662
|
return;
|
|
13523
13663
|
} else if (subcommand === "acp") {
|
|
13524
13664
|
try {
|
|
13525
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
13665
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-Syfrd3oP.cjs'); });
|
|
13526
13666
|
let startedBy = void 0;
|
|
13527
13667
|
let verbose = false;
|
|
13528
13668
|
const acpArgs = [];
|
|
@@ -13562,7 +13702,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13562
13702
|
return;
|
|
13563
13703
|
} else if (subcommand === "openclaw") {
|
|
13564
13704
|
try {
|
|
13565
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
13705
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-DJYiIMrs.cjs'); });
|
|
13566
13706
|
let startedBy = void 0;
|
|
13567
13707
|
let verbose = false;
|
|
13568
13708
|
let gatewayUrl;
|
|
@@ -13613,7 +13753,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
13613
13753
|
return;
|
|
13614
13754
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
13615
13755
|
try {
|
|
13616
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
13756
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-DGHMyTt-.cjs'); });
|
|
13617
13757
|
await handleMcpCommand();
|
|
13618
13758
|
} catch (error) {
|
|
13619
13759
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|