very-happy-cli 0.2.104 → 0.2.106
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-DDGfk3HJ.cjs → AcpBackend-DMmvLNNM.cjs} +1 -1
- package/dist/{AcpBackend-De4iQ_JG.mjs → AcpBackend-Ux5FD_6F.mjs} +1 -1
- package/dist/{AcpSessionManager-DRzAgHtT.mjs → AcpSessionManager-C1hoU_rK.mjs} +1 -1
- package/dist/{AcpSessionManager-Cdv6Xgwy.cjs → AcpSessionManager-RYkxYWDn.cjs} +1 -1
- package/dist/{config-E3KdWyaQ.mjs → config-DAb5saOC.mjs} +2 -2
- package/dist/{config-CqM5UxVd.cjs → config-Dkn5KcXp.cjs} +2 -2
- package/dist/{index-CX_3uUem.cjs → index-BLW-smJu.cjs} +209 -71
- package/dist/{index--TiLl7-A.mjs → index-CgWdwkhB.mjs} +205 -67
- package/dist/{index-C_dmtMJ6.mjs → index-D2ZzPm58.mjs} +5 -5
- package/dist/{index-De6H3U0N.cjs → index-D48mWUTN.cjs} +2 -2
- package/dist/{index-Bzj1XdPx.mjs → index-DCpgRGWy.mjs} +2 -2
- package/dist/{index-fuavV8uc.cjs → index-Do3JnAi7.cjs} +4 -4
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-BXMBwrvq.cjs → installTerminalHooks-9rn15uP8.cjs} +2 -2
- package/dist/{installTerminalHooks-DV0e8-V3.mjs → installTerminalHooks-l1B-nbWa.mjs} +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-Cq3On_Qo.cjs → mcp-C3zpbx-m.cjs} +2 -2
- package/dist/{mcp-DFS9Zohz.mjs → mcp-ZvHzv_lJ.mjs} +2 -2
- package/dist/{runGemini-BFjtlkZI.mjs → runGemini-0QqaFN1l.mjs} +4 -4
- package/dist/{runGemini-DFvjh8cO.cjs → runGemini-q20IdxQV.cjs} +4 -4
- package/dist/{runOpenClaw-BFYj1F4u.mjs → runOpenClaw-C6Z6MLHq.mjs} +3 -3
- package/dist/{runOpenClaw-B5Og1FED.cjs → runOpenClaw-CtWkyvDJ.cjs} +3 -3
- package/dist/{send-Bog0YPxo.cjs → send-B8YQyV3D.cjs} +2 -2
- package/dist/{send-B666yos0.mjs → send-DEhUWg8v.mjs} +2 -2
- package/dist/{spawn-DrqvVoNF.mjs → spawn-BzbPyTHU.mjs} +2 -2
- package/dist/{spawn-BSdMkMPX.cjs → spawn-ChmlP1Z_.cjs} +2 -2
- package/dist/{types-14LATr9X.cjs → types-C8-WODFE.cjs} +24 -10
- package/dist/{types-D9LyZitb.mjs → types-lSeHEzPR.mjs} +23 -9
- 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-C8-WODFE.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-lSeHEzPR.mjs';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_TIMEOUTS = {
|
|
7
7
|
/** Default initialization timeout: 60 seconds */
|
|
@@ -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-lSeHEzPR.mjs';
|
|
6
|
+
import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-CgWdwkhB.mjs';
|
|
7
7
|
import 'axios';
|
|
8
8
|
import 'chalk';
|
|
9
9
|
import 'node:util';
|
|
@@ -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-C8-WODFE.cjs');
|
|
8
|
+
var index = require('./index-BLW-smJu.cjs');
|
|
9
9
|
require('axios');
|
|
10
10
|
require('chalk');
|
|
11
11
|
require('node:util');
|
|
@@ -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-C8-WODFE.cjs');
|
|
7
7
|
var spawn = require('cross-spawn');
|
|
8
8
|
var path = require('node:path');
|
|
9
9
|
var node_readline = require('node:readline');
|
|
@@ -1929,6 +1929,18 @@ async function awaitFileExist(file, timeout = 1e4) {
|
|
|
1929
1929
|
return false;
|
|
1930
1930
|
}
|
|
1931
1931
|
|
|
1932
|
+
function modelTarget(model) {
|
|
1933
|
+
return model == null || model === "" ? void 0 : model;
|
|
1934
|
+
}
|
|
1935
|
+
function needsModelSwitch(current, next) {
|
|
1936
|
+
return modelTarget(current) !== modelTarget(next);
|
|
1937
|
+
}
|
|
1938
|
+
function modelSwitchFailureNotice(model, error) {
|
|
1939
|
+
const name = modelTarget(model) ?? "default";
|
|
1940
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1941
|
+
return `\u26A0\uFE0F Could not switch to model "${name}" \u2014 continuing with the previous model. ${detail}`;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1932
1944
|
async function claudeRemote(opts) {
|
|
1933
1945
|
let startFrom = opts.sessionId;
|
|
1934
1946
|
if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) {
|
|
@@ -2035,11 +2047,12 @@ async function claudeRemote(opts) {
|
|
|
2035
2047
|
if (opts.onQueryReady) {
|
|
2036
2048
|
opts.onQueryReady({
|
|
2037
2049
|
setPermissionMode: (mode2) => response.setPermissionMode(mode2),
|
|
2050
|
+
setModel: (model) => response.setModel(modelTarget(model)),
|
|
2038
2051
|
interrupt: async () => {
|
|
2039
2052
|
await response.interrupt();
|
|
2040
2053
|
},
|
|
2041
2054
|
steer: (message, nextMode) => {
|
|
2042
|
-
mode = nextMode;
|
|
2055
|
+
mode = { ...nextMode, model: mode.model };
|
|
2043
2056
|
messages.push({
|
|
2044
2057
|
type: "user",
|
|
2045
2058
|
parent_tool_use_id: null,
|
|
@@ -2071,7 +2084,10 @@ async function claudeRemote(opts) {
|
|
|
2071
2084
|
mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
|
|
2072
2085
|
skills: systemInit.skills,
|
|
2073
2086
|
model: systemInit.model,
|
|
2074
|
-
|
|
2087
|
+
// `mode`, not `initial.mode`: the model can move mid-Query
|
|
2088
|
+
// via setModel, and init is re-emitted every turn with the
|
|
2089
|
+
// model actually in force.
|
|
2090
|
+
modelIsDefault: modelTarget(mode.model) === void 0,
|
|
2075
2091
|
// The SDK's own verdict on the mode it will enforce —
|
|
2076
2092
|
// settings (permissions.deny/ask/defaultMode/
|
|
2077
2093
|
// disableBypassPermissionsMode) can override what we
|
|
@@ -2116,19 +2132,29 @@ async function claudeRemote(opts) {
|
|
|
2116
2132
|
messages.end();
|
|
2117
2133
|
continue;
|
|
2118
2134
|
}
|
|
2119
|
-
opts.nextMessage().then((next) => {
|
|
2135
|
+
opts.nextMessage().then(async (next) => {
|
|
2120
2136
|
if (!next) {
|
|
2121
2137
|
messages.end();
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
if (needsModelSwitch(mode.model, next.mode.model)) {
|
|
2141
|
+
try {
|
|
2142
|
+
await response.setModel(modelTarget(next.mode.model));
|
|
2143
|
+
persistence.logger.debug(`[claudeRemote] Model switched to ${modelTarget(next.mode.model) ?? "default"}`);
|
|
2144
|
+
} catch (e) {
|
|
2145
|
+
persistence.logger.debug(`[claudeRemote] setModel failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
2146
|
+
opts.onCompletionEvent?.(modelSwitchFailureNotice(next.mode.model, e));
|
|
2147
|
+
next = { ...next, mode: { ...next.mode, model: mode.model } };
|
|
2148
|
+
}
|
|
2131
2149
|
}
|
|
2150
|
+
mode = next.mode;
|
|
2151
|
+
updateThinking(true);
|
|
2152
|
+
messages.push({
|
|
2153
|
+
type: "user",
|
|
2154
|
+
parent_tool_use_id: null,
|
|
2155
|
+
origin: { kind: "human" },
|
|
2156
|
+
message: { role: "user", content: next.message }
|
|
2157
|
+
});
|
|
2132
2158
|
}).catch(() => {
|
|
2133
2159
|
messages.end();
|
|
2134
2160
|
});
|
|
@@ -3409,6 +3435,12 @@ function applyClaudeSdkMetadata(current, update) {
|
|
|
3409
3435
|
skills: update.skills,
|
|
3410
3436
|
attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
|
|
3411
3437
|
queueCancellation: true,
|
|
3438
|
+
// The model Claude Code reports it is ACTUALLY running. system/init is
|
|
3439
|
+
// re-emitted at every turn boundary (verified against the pinned SDK,
|
|
3440
|
+
// 2026-09-03), including after a live setModel, so this is the web's
|
|
3441
|
+
// only ground truth for "did my switch take effect" — the picker
|
|
3442
|
+
// otherwise renders nothing but the client's own optimistic intent.
|
|
3443
|
+
...update.model ? { currentModelCode: update.model } : {},
|
|
3412
3444
|
...update.modelIsDefault && update.model ? { defaultModelCode: update.model } : {}
|
|
3413
3445
|
};
|
|
3414
3446
|
}
|
|
@@ -3443,6 +3475,102 @@ function createTurnSteeringController() {
|
|
|
3443
3475
|
};
|
|
3444
3476
|
}
|
|
3445
3477
|
|
|
3478
|
+
class LaunchModeGate {
|
|
3479
|
+
constructor(hasher) {
|
|
3480
|
+
this.hasher = hasher;
|
|
3481
|
+
}
|
|
3482
|
+
currentMode = null;
|
|
3483
|
+
currentHash = null;
|
|
3484
|
+
parked = null;
|
|
3485
|
+
/** The mode this launch is running, or null before the first message. */
|
|
3486
|
+
get mode() {
|
|
3487
|
+
return this.currentMode;
|
|
3488
|
+
}
|
|
3489
|
+
/** Hash of {@link mode}; null means "not armed yet — accept anything". */
|
|
3490
|
+
get hash() {
|
|
3491
|
+
return this.currentHash;
|
|
3492
|
+
}
|
|
3493
|
+
/** Whether a message has been adopted into this launch yet. */
|
|
3494
|
+
get armed() {
|
|
3495
|
+
return this.currentHash !== null;
|
|
3496
|
+
}
|
|
3497
|
+
/** Bind the launch to `mode`. Idempotent; safe to call with the same mode. */
|
|
3498
|
+
adopt(mode) {
|
|
3499
|
+
this.currentMode = mode;
|
|
3500
|
+
this.currentHash = this.hasher(mode);
|
|
3501
|
+
}
|
|
3502
|
+
/**
|
|
3503
|
+
* Re-adopt the current mode with one field replaced. No-op before the first
|
|
3504
|
+
* adopt: there is nothing to derive from, and arming here would make the
|
|
3505
|
+
* first real message look like a mode change.
|
|
3506
|
+
*/
|
|
3507
|
+
amend(patch) {
|
|
3508
|
+
if (this.currentMode === null) return null;
|
|
3509
|
+
this.adopt({ ...this.currentMode, ...patch });
|
|
3510
|
+
return this.currentMode;
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* True when `incomingHash` cannot run on this launch's Query and must be
|
|
3514
|
+
* parked for a fresh one. An un-armed gate accepts anything — that is how a
|
|
3515
|
+
* new launch takes its first message, including a replayed parked one.
|
|
3516
|
+
*/
|
|
3517
|
+
requiresRelaunch(incomingHash, isolate) {
|
|
3518
|
+
if (isolate) return true;
|
|
3519
|
+
return this.armed && incomingHash !== this.currentHash;
|
|
3520
|
+
}
|
|
3521
|
+
/** True when `mode` is exactly what this launch adopted (Steer's precondition). */
|
|
3522
|
+
matches(mode) {
|
|
3523
|
+
return this.armed && this.hasher(mode) === this.currentHash;
|
|
3524
|
+
}
|
|
3525
|
+
/**
|
|
3526
|
+
* Hold a message that cannot run on this launch until its successor picks
|
|
3527
|
+
* it up. Survives {@link reset} — the parked message is precisely what the
|
|
3528
|
+
* next launch exists to run.
|
|
3529
|
+
*/
|
|
3530
|
+
park(message) {
|
|
3531
|
+
this.parked = message;
|
|
3532
|
+
}
|
|
3533
|
+
/** Whether a parked message is waiting for the next launch. */
|
|
3534
|
+
get hasParked() {
|
|
3535
|
+
return this.parked !== null;
|
|
3536
|
+
}
|
|
3537
|
+
/**
|
|
3538
|
+
* Take the parked message AND adopt its mode in one step.
|
|
3539
|
+
*
|
|
3540
|
+
* This pairing is the whole point of the class. When parking and adopting
|
|
3541
|
+
* were separate — a `pending` variable in the launcher next to a `modeHash`
|
|
3542
|
+
* one — the replay path took the message and forgot to adopt, so the gate
|
|
3543
|
+
* stayed un-armed and swallowed the NEXT mode change into a Query built for
|
|
3544
|
+
* the previous one. Nothing structural tied the two, and no unit test could
|
|
3545
|
+
* reach the wiring. Here they cannot come apart.
|
|
3546
|
+
*/
|
|
3547
|
+
takeParked() {
|
|
3548
|
+
const message = this.parked;
|
|
3549
|
+
if (!message) return null;
|
|
3550
|
+
this.parked = null;
|
|
3551
|
+
this.adopt(message.mode);
|
|
3552
|
+
return message;
|
|
3553
|
+
}
|
|
3554
|
+
/**
|
|
3555
|
+
* Re-adopt the parked message with a patched mode. Used when an explicit
|
|
3556
|
+
* mode switch lands while a message is parked: the switch is newer than the
|
|
3557
|
+
* snapshot the message carried when it was queued.
|
|
3558
|
+
*/
|
|
3559
|
+
amendParked(patch) {
|
|
3560
|
+
if (!this.parked) return;
|
|
3561
|
+
this.parked = { ...this.parked, mode: { ...this.parked.mode, ...patch } };
|
|
3562
|
+
}
|
|
3563
|
+
/**
|
|
3564
|
+
* Drop back to un-armed. Called when a launch ends. Deliberately does NOT
|
|
3565
|
+
* clear a parked message: parking happens in the launch that is ending, and
|
|
3566
|
+
* the message belongs to the one about to start.
|
|
3567
|
+
*/
|
|
3568
|
+
reset() {
|
|
3569
|
+
this.currentMode = null;
|
|
3570
|
+
this.currentHash = null;
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3446
3574
|
async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode) {
|
|
3447
3575
|
persistence.logger.debug("[claudeRemoteLauncher] Starting remote launcher");
|
|
3448
3576
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
@@ -3650,7 +3778,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3650
3778
|
}
|
|
3651
3779
|
}
|
|
3652
3780
|
try {
|
|
3653
|
-
|
|
3781
|
+
const modeGate = new LaunchModeGate(session.queue.modeHasher);
|
|
3654
3782
|
let previousSessionId = null;
|
|
3655
3783
|
while (!exitReason) {
|
|
3656
3784
|
persistence.logger.debug("[remote]: launch");
|
|
@@ -3669,18 +3797,11 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3669
3797
|
const controller = new AbortController();
|
|
3670
3798
|
abortController = controller;
|
|
3671
3799
|
abortFuture = new Future();
|
|
3672
|
-
let modeHash = null;
|
|
3673
|
-
let mode = null;
|
|
3674
3800
|
const commitPermissionMode = (nextMode) => {
|
|
3675
3801
|
permissionHandler.handleModeChange(nextMode);
|
|
3676
|
-
|
|
3677
|
-
mode = { ...mode, permissionMode: nextMode };
|
|
3678
|
-
modeHash = session.queue.modeHasher(mode);
|
|
3679
|
-
}
|
|
3802
|
+
modeGate.amend({ permissionMode: nextMode });
|
|
3680
3803
|
rewriteQueuedPermissionMode(session.queue.queue, session.queue.modeHasher, nextMode);
|
|
3681
|
-
|
|
3682
|
-
pending = { ...pending, mode: { ...pending.mode, permissionMode: nextMode } };
|
|
3683
|
-
}
|
|
3804
|
+
modeGate.amendParked({ permissionMode: nextMode });
|
|
3684
3805
|
onPermissionModeChange?.(nextMode);
|
|
3685
3806
|
return nextMode;
|
|
3686
3807
|
};
|
|
@@ -3706,22 +3827,28 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3706
3827
|
return permissionHandler.isAborted(toolCallId);
|
|
3707
3828
|
},
|
|
3708
3829
|
nextMessage: async () => {
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
return p;
|
|
3830
|
+
const parked = modeGate.takeParked();
|
|
3831
|
+
if (parked) {
|
|
3832
|
+
permissionHandler.handleModeChange(parked.mode.permissionMode);
|
|
3833
|
+
return parked;
|
|
3714
3834
|
}
|
|
3715
3835
|
let msg = await session.queue.waitForMessagesAndGetAsString(controller.signal);
|
|
3716
3836
|
if (msg) {
|
|
3717
|
-
if (
|
|
3837
|
+
if (modeGate.requiresRelaunch(msg.hash, msg.isolate)) {
|
|
3718
3838
|
persistence.logger.debug("[remote]: mode has changed, pending message");
|
|
3719
|
-
|
|
3839
|
+
const parkedAttachments = msg.attachments ?? [];
|
|
3840
|
+
const parkedStaged = parkedAttachments.length > 0 ? await stageClaudeAttachments(parkedAttachments, {
|
|
3841
|
+
happyHomeDir: persistence.configuration.happyHomeDir,
|
|
3842
|
+
sessionId: session.client.sessionId
|
|
3843
|
+
}) : [];
|
|
3844
|
+
modeGate.park({
|
|
3845
|
+
message: parkedStaged.length > 0 ? appendStagedAttachmentsToPrompt(msg.message, parkedStaged) : msg.message,
|
|
3846
|
+
mode: msg.mode
|
|
3847
|
+
});
|
|
3720
3848
|
return null;
|
|
3721
3849
|
}
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
permissionHandler.handleModeChange(mode.permissionMode);
|
|
3850
|
+
modeGate.adopt(msg.mode);
|
|
3851
|
+
permissionHandler.handleModeChange(msg.mode.permissionMode);
|
|
3725
3852
|
const attachments = msg.attachments ?? [];
|
|
3726
3853
|
if (attachments.length > 0) {
|
|
3727
3854
|
const staged = await stageClaudeAttachments(attachments, {
|
|
@@ -3758,8 +3885,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3758
3885
|
onQueryReady: (q) => {
|
|
3759
3886
|
turnSteering.setInterrupt(q.interrupt);
|
|
3760
3887
|
session.setSteerHandler(async (input) => {
|
|
3761
|
-
|
|
3762
|
-
if (!modeHash || expectedHash !== modeHash) return false;
|
|
3888
|
+
if (!modeGate.matches(input.mode)) return false;
|
|
3763
3889
|
let message = input.message;
|
|
3764
3890
|
if (input.attachments?.length) {
|
|
3765
3891
|
const staged = await stageClaudeAttachments(input.attachments, {
|
|
@@ -3768,19 +3894,16 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3768
3894
|
});
|
|
3769
3895
|
message = appendStagedAttachmentsToPrompt(input.message, staged);
|
|
3770
3896
|
}
|
|
3771
|
-
if (!session.thinking ||
|
|
3897
|
+
if (!session.thinking || !modeGate.matches(input.mode)) return false;
|
|
3772
3898
|
q.steer(message, input.mode);
|
|
3773
3899
|
return true;
|
|
3774
3900
|
});
|
|
3775
|
-
permissionHandler.setPermissionModeUpdater(async (
|
|
3776
|
-
await q.setPermissionMode(
|
|
3901
|
+
permissionHandler.setPermissionModeUpdater(async (mode) => {
|
|
3902
|
+
await q.setPermissionMode(mode);
|
|
3777
3903
|
});
|
|
3778
3904
|
livePermissionModeHandler = async (nextMode) => {
|
|
3779
3905
|
await permissionHandler.setLivePermissionMode(nextMode);
|
|
3780
|
-
|
|
3781
|
-
mode = { ...mode, permissionMode: nextMode };
|
|
3782
|
-
modeHash = session.queue.modeHasher(mode);
|
|
3783
|
-
}
|
|
3906
|
+
modeGate.amend({ permissionMode: nextMode });
|
|
3784
3907
|
onPermissionModeChange?.(nextMode);
|
|
3785
3908
|
return nextMode;
|
|
3786
3909
|
};
|
|
@@ -3811,7 +3934,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3811
3934
|
closeFailed: (error) => session.client.closeClaudeSessionTurn("failed", { error }),
|
|
3812
3935
|
onFailed: (error) => session.onSessionError(error),
|
|
3813
3936
|
onCompleted: () => {
|
|
3814
|
-
const idle = !
|
|
3937
|
+
const idle = !modeGate.hasParked && session.queue.size() === 0;
|
|
3815
3938
|
session.onTurnEnd(idle);
|
|
3816
3939
|
if (idle) {
|
|
3817
3940
|
session.api.push().sendSessionNotification({
|
|
@@ -3870,8 +3993,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3870
3993
|
abortFuture = null;
|
|
3871
3994
|
persistence.logger.debug("[remote]: launch done");
|
|
3872
3995
|
permissionHandler.reset();
|
|
3873
|
-
|
|
3874
|
-
mode = null;
|
|
3996
|
+
modeGate.reset();
|
|
3875
3997
|
}
|
|
3876
3998
|
}
|
|
3877
3999
|
} finally {
|
|
@@ -4168,6 +4290,7 @@ class MessageQueue2 {
|
|
|
4168
4290
|
while (this.queue.length > 0 && this.queue[0].modeHash === targetModeHash && !this.queue[0].isolate) {
|
|
4169
4291
|
const item = this.queue.shift();
|
|
4170
4292
|
sameModeMessages.push(item.message);
|
|
4293
|
+
mode = item.mode;
|
|
4171
4294
|
if (item.attachments) collectedAttachments.push(...item.attachments);
|
|
4172
4295
|
}
|
|
4173
4296
|
persistence.logger.debug(`[MessageQueue2] Collected batch of ${sameModeMessages.length} messages with mode hash: ${targetModeHash}`);
|
|
@@ -4309,6 +4432,18 @@ function hashObject(obj, options, encoding = "hex") {
|
|
|
4309
4432
|
return crypto.createHash("sha256").update(jsonString).digest(encoding);
|
|
4310
4433
|
}
|
|
4311
4434
|
|
|
4435
|
+
function claudeModeHash(mode) {
|
|
4436
|
+
return hashObject({
|
|
4437
|
+
isPlan: mode.permissionMode === "plan",
|
|
4438
|
+
fallbackModel: mode.fallbackModel,
|
|
4439
|
+
customSystemPrompt: mode.customSystemPrompt,
|
|
4440
|
+
appendSystemPrompt: mode.appendSystemPrompt,
|
|
4441
|
+
allowedTools: mode.allowedTools,
|
|
4442
|
+
disallowedTools: mode.disallowedTools,
|
|
4443
|
+
effort: mode.effort
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
|
|
4312
4447
|
function assistantSpawnTags(env = process.env) {
|
|
4313
4448
|
if (env.HAPPY_SPAWNED_BY !== "assistant") return void 0;
|
|
4314
4449
|
if (env.HAPPY_SESSION_VARIANT === "assistant") return void 0;
|
|
@@ -6778,7 +6913,7 @@ function parseJsonObject(text) {
|
|
|
6778
6913
|
return null;
|
|
6779
6914
|
}
|
|
6780
6915
|
}
|
|
6781
|
-
function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
6916
|
+
function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BLW-smJu.cjs', document.baseURI).href))).resolve(s)) {
|
|
6782
6917
|
const platformArch = `${platform}-${arch}`;
|
|
6783
6918
|
const candidates = [
|
|
6784
6919
|
`@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
|
|
@@ -7858,6 +7993,12 @@ async function claimSessionOrExit(happySessionId, options) {
|
|
|
7858
7993
|
}
|
|
7859
7994
|
|
|
7860
7995
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7996
|
+
function sanitizeImportTitle(value) {
|
|
7997
|
+
if (typeof value !== "string") return null;
|
|
7998
|
+
const collapsed = value.replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
|
|
7999
|
+
if (collapsed.length === 0) return null;
|
|
8000
|
+
return collapsed.length > 200 ? `${collapsed.slice(0, 199)}\u2026` : collapsed;
|
|
8001
|
+
}
|
|
7861
8002
|
const hostSuffix = process.env.HAPPY_VARIANT === "dev" ? "-dev" : "";
|
|
7862
8003
|
const initialMachineMetadata = {
|
|
7863
8004
|
host: os$1.hostname() + hostSuffix,
|
|
@@ -8196,6 +8337,10 @@ async function startDaemon() {
|
|
|
8196
8337
|
if (options.importedFromClaudeSessionId && UUID_RE.test(options.importedFromClaudeSessionId)) {
|
|
8197
8338
|
extraEnv.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID = options.importedFromClaudeSessionId;
|
|
8198
8339
|
}
|
|
8340
|
+
const importTitle = sanitizeImportTitle(options.importTitle);
|
|
8341
|
+
if (importTitle) {
|
|
8342
|
+
extraEnv.HAPPY_IMPORT_TITLE = importTitle;
|
|
8343
|
+
}
|
|
8199
8344
|
if (options.resumeCodexThreadId) {
|
|
8200
8345
|
extraEnv.HAPPY_FORK_CODEX_THREAD_ID = options.resumeCodexThreadId;
|
|
8201
8346
|
}
|
|
@@ -10057,7 +10202,7 @@ function registerSideQuestionHandler(rpc, deps) {
|
|
|
10057
10202
|
const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
|
|
10058
10203
|
const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
|
|
10059
10204
|
const run = deps.run ?? (async (input) => {
|
|
10060
|
-
const { query } = await Promise.resolve().then(function () { return require('./index-
|
|
10205
|
+
const { query } = await Promise.resolve().then(function () { return require('./index-D48mWUTN.cjs'); });
|
|
10061
10206
|
return runSideQuestion(query, input);
|
|
10062
10207
|
});
|
|
10063
10208
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -10159,7 +10304,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
10159
10304
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
10160
10305
|
function resolveClaudeBinary() {
|
|
10161
10306
|
try {
|
|
10162
|
-
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-
|
|
10307
|
+
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-BLW-smJu.cjs', document.baseURI).href)));
|
|
10163
10308
|
const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
10164
10309
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
10165
10310
|
const path$1 = getClaudeCliPath();
|
|
@@ -10596,6 +10741,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
10596
10741
|
const forkedFromSessionId = process.env.HAPPY_FORKED_FROM_SESSION_ID;
|
|
10597
10742
|
const forkedFromMessageId = process.env.HAPPY_FORKED_FROM_MESSAGE_ID;
|
|
10598
10743
|
const importedFromClaudeSessionId = process.env.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID;
|
|
10744
|
+
const importTitle = process.env.HAPPY_IMPORT_TITLE;
|
|
10599
10745
|
let metadata = {
|
|
10600
10746
|
path: workingDirectory,
|
|
10601
10747
|
host: os.hostname(),
|
|
@@ -10626,6 +10772,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
10626
10772
|
...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
|
|
10627
10773
|
...forkedFromMessageId ? { forkedFromMessageId } : {},
|
|
10628
10774
|
...importedFromClaudeSessionId ? { importedFromClaudeSessionId } : {},
|
|
10775
|
+
...importTitle ? { summary: { text: importTitle, updatedAt: Date.now() } } : {},
|
|
10629
10776
|
...isAssistantVariant ? { variant: "assistant" } : {},
|
|
10630
10777
|
// B-091: sessions the assistant dispatched (daemon spawn RPC exports
|
|
10631
10778
|
// HAPPY_SPAWNED_BY, B-069) are born with the 'assistant' tag so every
|
|
@@ -10856,16 +11003,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
10856
11003
|
...currentState,
|
|
10857
11004
|
controlledByUser: options.startingMode !== "remote"
|
|
10858
11005
|
}));
|
|
10859
|
-
const messageQueue = new MessageQueue2(
|
|
10860
|
-
isPlan: mode.permissionMode === "plan",
|
|
10861
|
-
model: mode.model,
|
|
10862
|
-
fallbackModel: mode.fallbackModel,
|
|
10863
|
-
customSystemPrompt: mode.customSystemPrompt,
|
|
10864
|
-
appendSystemPrompt: mode.appendSystemPrompt,
|
|
10865
|
-
allowedTools: mode.allowedTools,
|
|
10866
|
-
disallowedTools: mode.disallowedTools,
|
|
10867
|
-
effort: mode.effort
|
|
10868
|
-
}));
|
|
11006
|
+
const messageQueue = new MessageQueue2(claudeModeHash);
|
|
10869
11007
|
session.rpcHandlerManager.registerHandler("cancelQueuedMessage", async (params) => ({
|
|
10870
11008
|
removed: messageQueue.cancelPending(
|
|
10871
11009
|
typeof params?.localKey === "string" ? params.localKey : void 0,
|
|
@@ -12366,9 +12504,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
12366
12504
|
};
|
|
12367
12505
|
}
|
|
12368
12506
|
|
|
12369
|
-
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-
|
|
12507
|
+
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-BLW-smJu.cjs', document.baseURI).href)));
|
|
12370
12508
|
const __dirname$1 = path.dirname(__filename$1);
|
|
12371
|
-
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
12509
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BLW-smJu.cjs', document.baseURI).href)));
|
|
12372
12510
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
12373
12511
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
12374
12512
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -14992,7 +15130,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14992
15130
|
process.exit(0);
|
|
14993
15131
|
} else if (subcommand === "install-terminal-hooks") {
|
|
14994
15132
|
try {
|
|
14995
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
15133
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-9rn15uP8.cjs'); });
|
|
14996
15134
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
14997
15135
|
if (command.action === "help") {
|
|
14998
15136
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -15009,7 +15147,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15009
15147
|
}
|
|
15010
15148
|
} else if (subcommand === "spawn") {
|
|
15011
15149
|
try {
|
|
15012
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
15150
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-ChmlP1Z_.cjs'); });
|
|
15013
15151
|
await handleSpawnCommand(args.slice(1));
|
|
15014
15152
|
} catch (error) {
|
|
15015
15153
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -15021,7 +15159,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15021
15159
|
return;
|
|
15022
15160
|
} else if (subcommand === "send") {
|
|
15023
15161
|
try {
|
|
15024
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
15162
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-B8YQyV3D.cjs'); });
|
|
15025
15163
|
await handleSendCommand(args.slice(1));
|
|
15026
15164
|
} catch (error) {
|
|
15027
15165
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -15127,9 +15265,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15127
15265
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
15128
15266
|
const projectId = args[3];
|
|
15129
15267
|
try {
|
|
15130
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
15131
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-
|
|
15132
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
15268
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dkn5KcXp.cjs'); });
|
|
15269
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-C8-WODFE.cjs'); }).then(function (n) { return n.persistence; });
|
|
15270
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-C8-WODFE.cjs'); }).then(function (n) { return n.api; });
|
|
15133
15271
|
let userEmail = void 0;
|
|
15134
15272
|
try {
|
|
15135
15273
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -15160,7 +15298,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15160
15298
|
}
|
|
15161
15299
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
15162
15300
|
try {
|
|
15163
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
15301
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dkn5KcXp.cjs'); });
|
|
15164
15302
|
const config = readGeminiLocalConfig();
|
|
15165
15303
|
if (config.googleCloudProject) {
|
|
15166
15304
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -15200,7 +15338,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15200
15338
|
process.exit(0);
|
|
15201
15339
|
}
|
|
15202
15340
|
try {
|
|
15203
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
15341
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-q20IdxQV.cjs'); });
|
|
15204
15342
|
let startedBy = void 0;
|
|
15205
15343
|
for (let i = 1; i < args.length; i++) {
|
|
15206
15344
|
if (args[i] === "--started-by") {
|
|
@@ -15222,7 +15360,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15222
15360
|
return;
|
|
15223
15361
|
} else if (subcommand === "acp") {
|
|
15224
15362
|
try {
|
|
15225
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
15363
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-Do3JnAi7.cjs'); });
|
|
15226
15364
|
let startedBy = void 0;
|
|
15227
15365
|
let verbose = false;
|
|
15228
15366
|
const acpArgs = [];
|
|
@@ -15262,7 +15400,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15262
15400
|
return;
|
|
15263
15401
|
} else if (subcommand === "openclaw") {
|
|
15264
15402
|
try {
|
|
15265
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
15403
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CtWkyvDJ.cjs'); });
|
|
15266
15404
|
let startedBy = void 0;
|
|
15267
15405
|
let verbose = false;
|
|
15268
15406
|
let gatewayUrl;
|
|
@@ -15313,7 +15451,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
15313
15451
|
return;
|
|
15314
15452
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
15315
15453
|
try {
|
|
15316
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
15454
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-C3zpbx-m.cjs'); });
|
|
15317
15455
|
await handleMcpCommand();
|
|
15318
15456
|
} catch (error) {
|
|
15319
15457
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|