very-happy-cli 0.2.93 → 0.2.95
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-COv_3umE.cjs → AcpBackend-BXsbwTbl.cjs} +1 -1
- package/dist/{AcpBackend-C5507ePk.mjs → AcpBackend-Cuiff4Nu.mjs} +1 -1
- package/dist/{AcpSessionManager-Bd1trXWx.mjs → AcpSessionManager-BU69q_vR.mjs} +1 -1
- package/dist/{AcpSessionManager-vm4rIcH0.cjs → AcpSessionManager-BXGmMoe8.cjs} +1 -1
- package/dist/{config-BJjvra5x.mjs → config-2GD21yg_.mjs} +2 -2
- package/dist/{config-SZEQWS8k.cjs → config-BVOE0pni.cjs} +2 -2
- package/dist/{index-DaVhaBF2.cjs → index-BzbaMrIa.cjs} +333 -49
- package/dist/{index-17NbIAkU.cjs → index-CbPc1iVx.cjs} +4 -4
- package/dist/{index-C00jxV83.mjs → index-DVEdpWq0.mjs} +331 -47
- package/dist/{index-D-U-7DAy.mjs → index-DZ0uw6ef.mjs} +5 -5
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-CRjlRj9K.cjs → installTerminalHooks-BrrsyTMd.cjs} +2 -2
- package/dist/{installTerminalHooks-DsECLFy3.mjs → installTerminalHooks-FiujjEvb.mjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +9 -0
- package/dist/lib.d.mts +9 -0
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-Bs6R9P7q.mjs → mcp-0mZcHPtz.mjs} +2 -2
- package/dist/{mcp-C-dDCrXm.cjs → mcp-ziyMk3eS.cjs} +2 -2
- package/dist/{runGemini-DapsCPLi.cjs → runGemini-C91O1oxi.cjs} +4 -4
- package/dist/{runGemini-CrSCxKqI.mjs → runGemini-D_InkOhk.mjs} +4 -4
- package/dist/{runOpenClaw-C9dhyV4x.cjs → runOpenClaw-B1RRfA1V.cjs} +3 -3
- package/dist/{runOpenClaw-Cnagj-hv.mjs → runOpenClaw-BjebGmV6.mjs} +3 -3
- package/dist/{send-DlHES1EO.mjs → send-CxLL0z9J.mjs} +2 -2
- package/dist/{send-PmtzSBVM.cjs → send-DgK6MtgT.cjs} +2 -2
- package/dist/{spawn-OE9kENQi.cjs → spawn-Dian7x_g.cjs} +2 -2
- package/dist/{spawn-DgZUVvT2.mjs → spawn-uTPD3qOt.mjs} +2 -2
- package/dist/{types-Cx5wn5Hf.mjs → types-BLE8Hfmh.mjs} +34 -14
- package/dist/{types-BHVxYajT.cjs → types-HRuZ13LS.cjs} +34 -14
- package/package.json +7 -7
package/dist/lib.cjs
CHANGED
package/dist/lib.d.cts
CHANGED
|
@@ -1055,6 +1055,12 @@ interface TerminalListItem {
|
|
|
1055
1055
|
createdAt?: number;
|
|
1056
1056
|
activityAt?: number;
|
|
1057
1057
|
agentState?: AgentState;
|
|
1058
|
+
/** Mirror reconcile (design v3): stricter "claude is really here" gate (its
|
|
1059
|
+
* own TUI footer/dialog present) — daemon-internal, NOT pushed to web and
|
|
1060
|
+
* NOT part of the list signature. Only this may trigger mirror adopt (which
|
|
1061
|
+
* re-opens the B-107 input gate); `agentState` alone would false-positive
|
|
1062
|
+
* on a bare `node` process. */
|
|
1063
|
+
claudeConfident?: boolean;
|
|
1058
1064
|
/** Terminal mirror (B-105): shadow session id of the hand-typed claude
|
|
1059
1065
|
* running inside this terminal (set via the daemon's mirror resolver).
|
|
1060
1066
|
* The web shows the xterm ↔ structured toggle when present. */
|
|
@@ -1147,6 +1153,9 @@ declare class ApiMachineClient {
|
|
|
1147
1153
|
resolveMirrorSessionId: (terminalId: string) => string | undefined;
|
|
1148
1154
|
onTerminalClosed: (terminalId: string) => void;
|
|
1149
1155
|
onTerminalList: (terminals: TerminalListItem[]) => void;
|
|
1156
|
+
/** design v3: unconditional per-tick reconcile (self-heals lost bindings
|
|
1157
|
+
* on an unchanged-signature list). */
|
|
1158
|
+
onTerminalListTick: (terminals: TerminalListItem[]) => void;
|
|
1150
1159
|
isMirrorInputAllowed: (terminalId: string) => boolean;
|
|
1151
1160
|
}): void;
|
|
1152
1161
|
/** Mirror bindings changed → re-derive and (on diff) push the list now. */
|
package/dist/lib.d.mts
CHANGED
|
@@ -1055,6 +1055,12 @@ interface TerminalListItem {
|
|
|
1055
1055
|
createdAt?: number;
|
|
1056
1056
|
activityAt?: number;
|
|
1057
1057
|
agentState?: AgentState;
|
|
1058
|
+
/** Mirror reconcile (design v3): stricter "claude is really here" gate (its
|
|
1059
|
+
* own TUI footer/dialog present) — daemon-internal, NOT pushed to web and
|
|
1060
|
+
* NOT part of the list signature. Only this may trigger mirror adopt (which
|
|
1061
|
+
* re-opens the B-107 input gate); `agentState` alone would false-positive
|
|
1062
|
+
* on a bare `node` process. */
|
|
1063
|
+
claudeConfident?: boolean;
|
|
1058
1064
|
/** Terminal mirror (B-105): shadow session id of the hand-typed claude
|
|
1059
1065
|
* running inside this terminal (set via the daemon's mirror resolver).
|
|
1060
1066
|
* The web shows the xterm ↔ structured toggle when present. */
|
|
@@ -1147,6 +1153,9 @@ declare class ApiMachineClient {
|
|
|
1147
1153
|
resolveMirrorSessionId: (terminalId: string) => string | undefined;
|
|
1148
1154
|
onTerminalClosed: (terminalId: string) => void;
|
|
1149
1155
|
onTerminalList: (terminals: TerminalListItem[]) => void;
|
|
1156
|
+
/** design v3: unconditional per-tick reconcile (self-heals lost bindings
|
|
1157
|
+
* on an unchanged-signature list). */
|
|
1158
|
+
onTerminalListTick: (terminals: TerminalListItem[]) => void;
|
|
1150
1159
|
isMirrorInputAllowed: (terminalId: string) => boolean;
|
|
1151
1160
|
}): void;
|
|
1152
1161
|
/** Mirror bindings changed → re-derive and (on diff) push the list now. */
|
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-BLE8Hfmh.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'node:util';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { p as pushClipboardViaDaemon } from './index-
|
|
4
|
+
import { p as pushClipboardViaDaemon } from './index-DVEdpWq0.mjs';
|
|
5
5
|
import { C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, c as CLIPBOARD_MAX_BYTES } from './limits-CwFb5S2b.mjs';
|
|
6
|
-
import { l as logger } from './types-
|
|
6
|
+
import { l as logger } from './types-BLE8Hfmh.mjs';
|
|
7
7
|
import 'chalk';
|
|
8
8
|
import 'node:os';
|
|
9
9
|
import 'node:crypto';
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
4
4
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
5
5
|
var z = require('zod');
|
|
6
|
-
var index = require('./index-
|
|
6
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
7
7
|
var limits = require('./limits-KdWKmwtH.cjs');
|
|
8
|
-
var persistence = require('./types-
|
|
8
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
9
9
|
require('chalk');
|
|
10
10
|
require('node:os');
|
|
11
11
|
require('node:crypto');
|
|
@@ -4,10 +4,10 @@ var ink = require('ink');
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
6
|
var path = require('node:path');
|
|
7
|
-
var persistence = require('./types-
|
|
8
|
-
var index = require('./index-
|
|
9
|
-
var AcpBackend = require('./AcpBackend-
|
|
10
|
-
var config = require('./config-
|
|
7
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
8
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
9
|
+
var AcpBackend = require('./AcpBackend-BXsbwTbl.cjs');
|
|
10
|
+
var config = require('./config-BVOE0pni.cjs');
|
|
11
11
|
require('axios');
|
|
12
12
|
require('chalk');
|
|
13
13
|
require('node:util');
|
|
@@ -2,10 +2,10 @@ import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
-
import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-
|
|
6
|
-
import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-
|
|
7
|
-
import { A as AcpBackend } from './AcpBackend-
|
|
8
|
-
import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-
|
|
5
|
+
import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-BLE8Hfmh.mjs';
|
|
6
|
+
import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-DVEdpWq0.mjs';
|
|
7
|
+
import { A as AcpBackend } from './AcpBackend-Cuiff4Nu.mjs';
|
|
8
|
+
import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-2GD21yg_.mjs';
|
|
9
9
|
import 'axios';
|
|
10
10
|
import 'chalk';
|
|
11
11
|
import 'node:util';
|
|
@@ -5,9 +5,9 @@ var node_child_process = require('node:child_process');
|
|
|
5
5
|
var os = require('node:os');
|
|
6
6
|
var node_fs = require('node:fs');
|
|
7
7
|
var path = require('node:path');
|
|
8
|
-
var persistence = require('./types-
|
|
9
|
-
var AcpSessionManager = require('./AcpSessionManager-
|
|
10
|
-
var index = require('./index-
|
|
8
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
9
|
+
var AcpSessionManager = require('./AcpSessionManager-BXGmMoe8.cjs');
|
|
10
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
11
11
|
var WebSocket = require('ws');
|
|
12
12
|
var ed = require('@noble/ed25519');
|
|
13
13
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-
|
|
7
|
-
import { A as AcpSessionManager } from './AcpSessionManager-
|
|
8
|
-
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-
|
|
6
|
+
import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-BLE8Hfmh.mjs';
|
|
7
|
+
import { A as AcpSessionManager } from './AcpSessionManager-BU69q_vR.mjs';
|
|
8
|
+
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-DVEdpWq0.mjs';
|
|
9
9
|
import WebSocket from 'ws';
|
|
10
10
|
import * as ed from '@noble/ed25519';
|
|
11
11
|
import { sha512 } from '@noble/hashes/sha2.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { r as readPersistedSessions, c as configuration } from './types-
|
|
5
|
-
import { b as sendUserMessage, a as sessionWebUrl } from './index-
|
|
4
|
+
import { r as readPersistedSessions, c as configuration } from './types-BLE8Hfmh.mjs';
|
|
5
|
+
import { b as sendUserMessage, a as sessionWebUrl } from './index-DVEdpWq0.mjs';
|
|
6
6
|
import 'axios';
|
|
7
7
|
import 'node:util';
|
|
8
8
|
import 'node:os';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var persistence = require('./types-
|
|
7
|
-
var index = require('./index-
|
|
6
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
7
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
8
8
|
require('axios');
|
|
9
9
|
require('node:util');
|
|
10
10
|
require('node:os');
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var index = require('./index-
|
|
7
|
-
var persistence = require('./types-
|
|
6
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
7
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
8
8
|
require('node:os');
|
|
9
9
|
require('node:crypto');
|
|
10
10
|
require('cross-spawn');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-
|
|
5
|
-
import { l as logger } from './types-
|
|
4
|
+
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-DVEdpWq0.mjs';
|
|
5
|
+
import { l as logger } from './types-BLE8Hfmh.mjs';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import 'cross-spawn';
|
|
@@ -29,7 +29,7 @@ import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
|
|
|
29
29
|
import { Expo } from 'expo-server-sdk';
|
|
30
30
|
|
|
31
31
|
var name = "very-happy-cli";
|
|
32
|
-
var version = "0.2.
|
|
32
|
+
var version = "0.2.95";
|
|
33
33
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
34
34
|
var author = "Kirill Dubovitskiy";
|
|
35
35
|
var contributors = [
|
|
@@ -142,12 +142,12 @@ var dependencies = {
|
|
|
142
142
|
zod: "^4.0.0"
|
|
143
143
|
};
|
|
144
144
|
var optionalDependencies = {
|
|
145
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
146
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
147
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
148
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
149
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
150
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
145
|
+
"very-happy-tools-arm64-darwin": "0.2.95",
|
|
146
|
+
"very-happy-tools-x64-darwin": "0.2.95",
|
|
147
|
+
"very-happy-tools-arm64-linux": "0.2.95",
|
|
148
|
+
"very-happy-tools-x64-linux": "0.2.95",
|
|
149
|
+
"very-happy-tools-arm64-win32": "0.2.95",
|
|
150
|
+
"very-happy-tools-x64-win32": "0.2.95"
|
|
151
151
|
};
|
|
152
152
|
var devDependencies = {
|
|
153
153
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -10257,6 +10257,13 @@ function looksLikeClaudeCommand(currentCommand) {
|
|
|
10257
10257
|
const cmd = (currentCommand || "").trim().replace(/^-/, "").toLowerCase();
|
|
10258
10258
|
return cmd === "claude" || cmd === "node" || /^\d+\.\d+(\.\d+)?$/.test(cmd);
|
|
10259
10259
|
}
|
|
10260
|
+
function isClaudeConfident(tail) {
|
|
10261
|
+
const lines = tail.replace(/\r/g, "").split("\n").map((l) => l.trimEnd());
|
|
10262
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
10263
|
+
const text = lines.join("\n");
|
|
10264
|
+
const last15 = lines.slice(-15).join("\n");
|
|
10265
|
+
return last15.includes("Do you want") || last15.includes("Would you like to proceed") || /^[\s│]*[❯>]\s*1\.\s/m.test(last15) || text.includes("esc to interrupt") || text.includes("? for shortcuts") || text.includes("bypass permissions on") || text.includes("\u23F5\u23F5");
|
|
10266
|
+
}
|
|
10260
10267
|
function planScrollAction(paneInMode, alternateOn, paneWantsMouse, lines, claudeLike = false, paneRows = 24) {
|
|
10261
10268
|
const count = Math.min(Math.abs(Math.trunc(lines)), 200);
|
|
10262
10269
|
if (count === 0) return { kind: "none" };
|
|
@@ -10643,9 +10650,16 @@ class WebTerminalManager {
|
|
|
10643
10650
|
/** terminalId → shadow session id (daemon's mirror manager). Feeds the
|
|
10644
10651
|
* list push (toggle availability) and closed-terminal records. */
|
|
10645
10652
|
mirrorResolver = null;
|
|
10653
|
+
mirrorTickObserver = null;
|
|
10646
10654
|
/** Fired once per terminal whose close was just recorded — the mirror
|
|
10647
10655
|
* manager archives + tears down that terminal's binding. */
|
|
10648
10656
|
onTerminalClosedCb = null;
|
|
10657
|
+
/** Mirror reconcile (design v3): fired every list-track tick, BEFORE the
|
|
10658
|
+
* signature short-circuit, so a claude-running terminal whose binding was
|
|
10659
|
+
* lost self-heals even when nothing about the list changed. */
|
|
10660
|
+
setMirrorTickObserver(fn) {
|
|
10661
|
+
this.mirrorTickObserver = fn;
|
|
10662
|
+
}
|
|
10649
10663
|
setMirrorSessionResolver(fn) {
|
|
10650
10664
|
this.mirrorResolver = fn;
|
|
10651
10665
|
this.kickListRefresh();
|
|
@@ -10828,6 +10842,7 @@ class WebTerminalManager {
|
|
|
10828
10842
|
this.emitActivity(Object.fromEntries(
|
|
10829
10843
|
list.filter((t) => t.activityAt).map((t) => [t.id, t.activityAt])
|
|
10830
10844
|
));
|
|
10845
|
+
this.mirrorTickObserver?.(list);
|
|
10831
10846
|
const sig = terminalListSignature(list);
|
|
10832
10847
|
if (sig === this.lastListSignature) return;
|
|
10833
10848
|
this.lastListSignature = sig;
|
|
@@ -11767,6 +11782,7 @@ class WebTerminalManager {
|
|
|
11767
11782
|
} catch {
|
|
11768
11783
|
}
|
|
11769
11784
|
}
|
|
11785
|
+
const probe = this.probeAgentState(s.name, s.paneCurrentCommand);
|
|
11770
11786
|
out.push({
|
|
11771
11787
|
id,
|
|
11772
11788
|
title,
|
|
@@ -11777,7 +11793,10 @@ class WebTerminalManager {
|
|
|
11777
11793
|
// tmux last-activity (epoch s) → ms; optional so old daemons
|
|
11778
11794
|
// simply omit it and web clients fall back to createdAt.
|
|
11779
11795
|
activityAt: s.activity,
|
|
11780
|
-
agentState:
|
|
11796
|
+
agentState: probe.agentState,
|
|
11797
|
+
// Daemon-internal (not pushed to web / not in the signature):
|
|
11798
|
+
// the mirror reconciler's stricter "claude is really here" gate.
|
|
11799
|
+
claudeConfident: probe.claudeConfident,
|
|
11781
11800
|
manual: s.manual
|
|
11782
11801
|
});
|
|
11783
11802
|
}
|
|
@@ -11799,7 +11818,7 @@ class WebTerminalManager {
|
|
|
11799
11818
|
if (live) {
|
|
11800
11819
|
try {
|
|
11801
11820
|
const { command, tail } = live.agentProbeInput();
|
|
11802
|
-
return classifyPane(command || polledCommand || "", tail);
|
|
11821
|
+
return { agentState: classifyPane(command || polledCommand || "", tail), claudeConfident: isClaudeConfident(tail) };
|
|
11803
11822
|
} catch {
|
|
11804
11823
|
}
|
|
11805
11824
|
}
|
|
@@ -11815,16 +11834,16 @@ class WebTerminalManager {
|
|
|
11815
11834
|
tmuxArgs(["display-message", "-p", "-t", sessionName, "#{pane_current_command}"]),
|
|
11816
11835
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11817
11836
|
);
|
|
11818
|
-
if (cmd.status !== 0 || typeof cmd.stdout !== "string") return void 0;
|
|
11837
|
+
if (cmd.status !== 0 || typeof cmd.stdout !== "string") return { agentState: void 0, claudeConfident: false };
|
|
11819
11838
|
const cap = spawnSync(
|
|
11820
11839
|
"tmux",
|
|
11821
11840
|
tmuxArgs(["capture-pane", "-p", "-t", sessionName, "-S", "-40"]),
|
|
11822
11841
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11823
11842
|
);
|
|
11824
|
-
if (cap.status !== 0 || typeof cap.stdout !== "string") return void 0;
|
|
11825
|
-
return classifyPane(cmd.stdout.trim(), cap.stdout);
|
|
11843
|
+
if (cap.status !== 0 || typeof cap.stdout !== "string") return { agentState: void 0, claudeConfident: false };
|
|
11844
|
+
return { agentState: classifyPane(cmd.stdout.trim(), cap.stdout), claudeConfident: isClaudeConfident(cap.stdout) };
|
|
11826
11845
|
} catch {
|
|
11827
|
-
return void 0;
|
|
11846
|
+
return { agentState: void 0, claudeConfident: false };
|
|
11828
11847
|
}
|
|
11829
11848
|
}
|
|
11830
11849
|
/**
|
|
@@ -14151,6 +14170,7 @@ class ApiMachineClient {
|
|
|
14151
14170
|
setMirrorIntegration(integration) {
|
|
14152
14171
|
this.webTerminal.setMirrorSessionResolver(integration.resolveMirrorSessionId);
|
|
14153
14172
|
this.webTerminal.setOnTerminalClosed(integration.onTerminalClosed);
|
|
14173
|
+
this.webTerminal.setMirrorTickObserver(integration.onTerminalListTick);
|
|
14154
14174
|
this.mirrorListObserver = integration.onTerminalList;
|
|
14155
14175
|
this.mirrorInputAllowed = integration.isMirrorInputAllowed;
|
|
14156
14176
|
}
|
|
@@ -15644,4 +15664,4 @@ const RawJSONLinesSchema = z$1.discriminatedUnion("type", [
|
|
|
15644
15664
|
}).passthrough()
|
|
15645
15665
|
]);
|
|
15646
15666
|
|
|
15647
|
-
export { detectResumeSupport as $, ApiClient as A, deriveLocalCliUpdateSummary as B, updateSettings as C, encodeBase64Url as D, decodeBase64 as E, writeCredentialsLegacy as F, writeCredentialsDataKey as G, readCredentialsForConfiguredRelay as H, InvalidateSync as I, encrypt as J, isClaudeSessionId as K, getLocalHappyAgentCredentialPath as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, readLocalHappyAgentCredentials as N, decryptWithDataKey as O, decryptLegacy as P, extractCompleteLines as Q, RawJSONLinesSchema as R, decideBackfill as S, parseTerminalHookPayload as T, tmuxArgs as U, scrubTmuxClientEnv as V, decideMirrorBinding as W,
|
|
15667
|
+
export { detectResumeSupport as $, ApiClient as A, deriveLocalCliUpdateSummary as B, updateSettings as C, encodeBase64Url as D, decodeBase64 as E, writeCredentialsLegacy as F, writeCredentialsDataKey as G, readCredentialsForConfiguredRelay as H, InvalidateSync as I, encrypt as J, isClaudeSessionId as K, getLocalHappyAgentCredentialPath as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, readLocalHappyAgentCredentials as N, decryptWithDataKey as O, decryptLegacy as P, extractCompleteLines as Q, RawJSONLinesSchema as R, decideBackfill as S, parseTerminalHookPayload as T, tmuxArgs as U, scrubTmuxClientEnv as V, decideMirrorBinding as W, MIRROR_BACKFILL_LINES_DEFAULT as X, persistSession as Y, mirrorLineKey as Z, mirrorLocalId as _, ApiSessionClient as a, detectCLIAvailability as a0, acquireDaemonLock as a1, summarizeSpawnSessionForLog as a2, deletePersistedSessions as a3, decrypt as a4, writeDaemonState as a5, fetchCliUpdateState as a6, resolveCliUpdateCheckInterval as a7, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as a8, releaseDaemonLock as a9, isValidSessionId as aa, listVhTerminals as ab, isValidTerminalId as ac, readVhTerminal as ad, sendToVhTerminal as ae, startOfflineReconnection as af, clearCredentials as ag, clearMachineId as ah, SandboxConfigSchema as ai, CodexAppServerClient as aj, getLatestDaemonLog as ak, persistence as al, api as am, createEnvelope as b, configuration as c, contentLogMetadata as d, errorLogMetadata as e, packageJson as f, delay as g, connectionState as h, readSettings as i, encodeBase64 as j, ensurePrivateDirectorySync as k, logger as l, hardenPrivateFileSync as m, readDaemonState as n, clearDaemonState as o, projectPath as p, getProjectPath as q, readPersistedSessions as r, initializeSandbox as s, wrapCommand as t, AsyncLock as u, ensurePrivateDirectory as v, writePrivateFileSync as w, hardenPrivateFile as x, readCredentials as y, credentialRelayProblem as z };
|
|
@@ -51,7 +51,7 @@ var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
|
51
51
|
var pty__namespace = /*#__PURE__*/_interopNamespaceDefault(pty);
|
|
52
52
|
|
|
53
53
|
var name = "very-happy-cli";
|
|
54
|
-
var version = "0.2.
|
|
54
|
+
var version = "0.2.95";
|
|
55
55
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
56
56
|
var author = "Kirill Dubovitskiy";
|
|
57
57
|
var contributors = [
|
|
@@ -164,12 +164,12 @@ var dependencies = {
|
|
|
164
164
|
zod: "^4.0.0"
|
|
165
165
|
};
|
|
166
166
|
var optionalDependencies = {
|
|
167
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
168
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
169
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
170
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
171
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
172
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
167
|
+
"very-happy-tools-arm64-darwin": "0.2.95",
|
|
168
|
+
"very-happy-tools-x64-darwin": "0.2.95",
|
|
169
|
+
"very-happy-tools-arm64-linux": "0.2.95",
|
|
170
|
+
"very-happy-tools-x64-linux": "0.2.95",
|
|
171
|
+
"very-happy-tools-arm64-win32": "0.2.95",
|
|
172
|
+
"very-happy-tools-x64-win32": "0.2.95"
|
|
173
173
|
};
|
|
174
174
|
var devDependencies = {
|
|
175
175
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -1545,7 +1545,7 @@ class RpcHandlerManager {
|
|
|
1545
1545
|
}
|
|
1546
1546
|
}
|
|
1547
1547
|
|
|
1548
|
-
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
1548
|
+
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-HRuZ13LS.cjs', document.baseURI).href))));
|
|
1549
1549
|
function projectPath() {
|
|
1550
1550
|
const path = path$1.resolve(__dirname$1, "..");
|
|
1551
1551
|
return path;
|
|
@@ -10279,6 +10279,13 @@ function looksLikeClaudeCommand(currentCommand) {
|
|
|
10279
10279
|
const cmd = (currentCommand || "").trim().replace(/^-/, "").toLowerCase();
|
|
10280
10280
|
return cmd === "claude" || cmd === "node" || /^\d+\.\d+(\.\d+)?$/.test(cmd);
|
|
10281
10281
|
}
|
|
10282
|
+
function isClaudeConfident(tail) {
|
|
10283
|
+
const lines = tail.replace(/\r/g, "").split("\n").map((l) => l.trimEnd());
|
|
10284
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
10285
|
+
const text = lines.join("\n");
|
|
10286
|
+
const last15 = lines.slice(-15).join("\n");
|
|
10287
|
+
return last15.includes("Do you want") || last15.includes("Would you like to proceed") || /^[\s│]*[❯>]\s*1\.\s/m.test(last15) || text.includes("esc to interrupt") || text.includes("? for shortcuts") || text.includes("bypass permissions on") || text.includes("\u23F5\u23F5");
|
|
10288
|
+
}
|
|
10282
10289
|
function planScrollAction(paneInMode, alternateOn, paneWantsMouse, lines, claudeLike = false, paneRows = 24) {
|
|
10283
10290
|
const count = Math.min(Math.abs(Math.trunc(lines)), 200);
|
|
10284
10291
|
if (count === 0) return { kind: "none" };
|
|
@@ -10665,9 +10672,16 @@ class WebTerminalManager {
|
|
|
10665
10672
|
/** terminalId → shadow session id (daemon's mirror manager). Feeds the
|
|
10666
10673
|
* list push (toggle availability) and closed-terminal records. */
|
|
10667
10674
|
mirrorResolver = null;
|
|
10675
|
+
mirrorTickObserver = null;
|
|
10668
10676
|
/** Fired once per terminal whose close was just recorded — the mirror
|
|
10669
10677
|
* manager archives + tears down that terminal's binding. */
|
|
10670
10678
|
onTerminalClosedCb = null;
|
|
10679
|
+
/** Mirror reconcile (design v3): fired every list-track tick, BEFORE the
|
|
10680
|
+
* signature short-circuit, so a claude-running terminal whose binding was
|
|
10681
|
+
* lost self-heals even when nothing about the list changed. */
|
|
10682
|
+
setMirrorTickObserver(fn) {
|
|
10683
|
+
this.mirrorTickObserver = fn;
|
|
10684
|
+
}
|
|
10671
10685
|
setMirrorSessionResolver(fn) {
|
|
10672
10686
|
this.mirrorResolver = fn;
|
|
10673
10687
|
this.kickListRefresh();
|
|
@@ -10850,6 +10864,7 @@ class WebTerminalManager {
|
|
|
10850
10864
|
this.emitActivity(Object.fromEntries(
|
|
10851
10865
|
list.filter((t) => t.activityAt).map((t) => [t.id, t.activityAt])
|
|
10852
10866
|
));
|
|
10867
|
+
this.mirrorTickObserver?.(list);
|
|
10853
10868
|
const sig = terminalListSignature(list);
|
|
10854
10869
|
if (sig === this.lastListSignature) return;
|
|
10855
10870
|
this.lastListSignature = sig;
|
|
@@ -11789,6 +11804,7 @@ class WebTerminalManager {
|
|
|
11789
11804
|
} catch {
|
|
11790
11805
|
}
|
|
11791
11806
|
}
|
|
11807
|
+
const probe = this.probeAgentState(s.name, s.paneCurrentCommand);
|
|
11792
11808
|
out.push({
|
|
11793
11809
|
id,
|
|
11794
11810
|
title,
|
|
@@ -11799,7 +11815,10 @@ class WebTerminalManager {
|
|
|
11799
11815
|
// tmux last-activity (epoch s) → ms; optional so old daemons
|
|
11800
11816
|
// simply omit it and web clients fall back to createdAt.
|
|
11801
11817
|
activityAt: s.activity,
|
|
11802
|
-
agentState:
|
|
11818
|
+
agentState: probe.agentState,
|
|
11819
|
+
// Daemon-internal (not pushed to web / not in the signature):
|
|
11820
|
+
// the mirror reconciler's stricter "claude is really here" gate.
|
|
11821
|
+
claudeConfident: probe.claudeConfident,
|
|
11803
11822
|
manual: s.manual
|
|
11804
11823
|
});
|
|
11805
11824
|
}
|
|
@@ -11821,7 +11840,7 @@ class WebTerminalManager {
|
|
|
11821
11840
|
if (live) {
|
|
11822
11841
|
try {
|
|
11823
11842
|
const { command, tail } = live.agentProbeInput();
|
|
11824
|
-
return classifyPane(command || polledCommand || "", tail);
|
|
11843
|
+
return { agentState: classifyPane(command || polledCommand || "", tail), claudeConfident: isClaudeConfident(tail) };
|
|
11825
11844
|
} catch {
|
|
11826
11845
|
}
|
|
11827
11846
|
}
|
|
@@ -11837,16 +11856,16 @@ class WebTerminalManager {
|
|
|
11837
11856
|
tmuxArgs(["display-message", "-p", "-t", sessionName, "#{pane_current_command}"]),
|
|
11838
11857
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11839
11858
|
);
|
|
11840
|
-
if (cmd.status !== 0 || typeof cmd.stdout !== "string") return void 0;
|
|
11859
|
+
if (cmd.status !== 0 || typeof cmd.stdout !== "string") return { agentState: void 0, claudeConfident: false };
|
|
11841
11860
|
const cap = node_child_process.spawnSync(
|
|
11842
11861
|
"tmux",
|
|
11843
11862
|
tmuxArgs(["capture-pane", "-p", "-t", sessionName, "-S", "-40"]),
|
|
11844
11863
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11845
11864
|
);
|
|
11846
|
-
if (cap.status !== 0 || typeof cap.stdout !== "string") return void 0;
|
|
11847
|
-
return classifyPane(cmd.stdout.trim(), cap.stdout);
|
|
11865
|
+
if (cap.status !== 0 || typeof cap.stdout !== "string") return { agentState: void 0, claudeConfident: false };
|
|
11866
|
+
return { agentState: classifyPane(cmd.stdout.trim(), cap.stdout), claudeConfident: isClaudeConfident(cap.stdout) };
|
|
11848
11867
|
} catch {
|
|
11849
|
-
return void 0;
|
|
11868
|
+
return { agentState: void 0, claudeConfident: false };
|
|
11850
11869
|
}
|
|
11851
11870
|
}
|
|
11852
11871
|
/**
|
|
@@ -14173,6 +14192,7 @@ class ApiMachineClient {
|
|
|
14173
14192
|
setMirrorIntegration(integration) {
|
|
14174
14193
|
this.webTerminal.setMirrorSessionResolver(integration.resolveMirrorSessionId);
|
|
14175
14194
|
this.webTerminal.setOnTerminalClosed(integration.onTerminalClosed);
|
|
14195
|
+
this.webTerminal.setMirrorTickObserver(integration.onTerminalListTick);
|
|
14176
14196
|
this.mirrorListObserver = integration.onTerminalList;
|
|
14177
14197
|
this.mirrorInputAllowed = integration.isMirrorInputAllowed;
|
|
14178
14198
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.95",
|
|
4
4
|
"description": "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.",
|
|
5
5
|
"author": "Kirill Dubovitskiy",
|
|
6
6
|
"contributors": [
|
|
@@ -113,12 +113,12 @@
|
|
|
113
113
|
"zod": "^4.0.0"
|
|
114
114
|
},
|
|
115
115
|
"optionalDependencies": {
|
|
116
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
117
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
118
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
119
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
120
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
121
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
116
|
+
"very-happy-tools-arm64-darwin": "0.2.95",
|
|
117
|
+
"very-happy-tools-x64-darwin": "0.2.95",
|
|
118
|
+
"very-happy-tools-arm64-linux": "0.2.95",
|
|
119
|
+
"very-happy-tools-x64-linux": "0.2.95",
|
|
120
|
+
"very-happy-tools-arm64-win32": "0.2.95",
|
|
121
|
+
"very-happy-tools-x64-win32": "0.2.95"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@slopus/happy-wire": "workspace:*",
|