very-happy-cli 0.2.116 → 0.2.117
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-CfKPvoTU.mjs → AcpBackend-C4RMHt0I.mjs} +1 -1
- package/dist/{AcpBackend-CauAQpC1.cjs → AcpBackend-CrbXvcgQ.cjs} +1 -1
- package/dist/{AcpSessionManager-CA6xeET_.cjs → AcpSessionManager-CjAVO4RX.cjs} +1 -1
- package/dist/{AcpSessionManager-BQ6pBRW4.mjs → AcpSessionManager-Cnc8Jatl.mjs} +1 -1
- package/dist/{config-BpR_CwZu.mjs → config-CnA3JIUn.mjs} +2 -2
- package/dist/{config-BoteFn-v.cjs → config-O9quMfxg.cjs} +2 -2
- package/dist/{index-D7azxfcs.mjs → index-B0o3H6_x.mjs} +2 -2
- package/dist/{index-Dq-eFp89.mjs → index-BYZKuQoy.mjs} +499 -42
- package/dist/{index-4jiUeiUz.cjs → index-DcESl4cI.cjs} +510 -44
- package/dist/{index-C45xN8s0.mjs → index-DiRN0Rv8.mjs} +78 -8
- package/dist/{index-lX1UliOs.cjs → index-DqmVH6R5.cjs} +2 -2
- package/dist/{index-DWmhmji9.cjs → index-W-O4xR_O.cjs} +77 -7
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-k3TrBHD0.mjs → installTerminalHooks-DeYqyjCB.mjs} +2 -2
- package/dist/{installTerminalHooks-DnaFkrTF.cjs → installTerminalHooks-zfsWSotO.cjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +41 -1
- package/dist/lib.d.mts +41 -1
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-DRePTOap.mjs → mcp-D_5aOK0I.mjs} +62 -17
- package/dist/{mcp-DSpEpM_2.cjs → mcp-nYqC4FYm.cjs} +62 -16
- package/dist/{runGemini-_9-a7duU.mjs → runGemini-CEURRmM4.mjs} +4 -4
- package/dist/{runGemini-IWHyBq0A.cjs → runGemini-DYf3ntib.cjs} +4 -4
- package/dist/{runOpenClaw-Boq6LQ9a.mjs → runOpenClaw-BozfKWng.mjs} +3 -3
- package/dist/{runOpenClaw-0myYIz1U.cjs → runOpenClaw-CNKjAw-H.cjs} +3 -3
- package/dist/{send-CwWvFfay.cjs → send-BZLhRZb-.cjs} +2 -2
- package/dist/{send-Cyo6mgMl.mjs → send-CYznZGrp.mjs} +2 -2
- package/dist/sessions-DYPB3Peg.mjs +317 -0
- package/dist/sessions-YWt9YEN8.cjs +322 -0
- package/dist/{spawn-CU0DMauA.mjs → spawn-CsrHZd3y.mjs} +3 -4
- package/dist/{spawn-DQ6FTUK9.cjs → spawn-tSvo3stN.cjs} +6 -7
- package/dist/{types-C5kEpkcZ.cjs → types-DD3AK6Nb.cjs} +47 -19
- package/dist/{types-Ds0SiQ1D.mjs → types-jSfU_0o1.mjs} +45 -19
- package/package.json +7 -7
- package/dist/sessions-CbzqYiAy.cjs +0 -204
- package/dist/sessions-lvfTH_ql.mjs +0 -200
|
@@ -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, j as readSettings, k 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-C4RMHt0I.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-C4RMHt0I.mjs';
|
|
3
|
+
import { h as connectionState, A as ApiClient, j as readSettings, k as encodeBase64, l as logger, p as projectPath } from './types-jSfU_0o1.mjs';
|
|
4
|
+
import { A as AcpSessionManager } from './AcpSessionManager-Cnc8Jatl.mjs';
|
|
5
5
|
import { randomUUID } from 'node:crypto';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
|
-
import {
|
|
7
|
+
import { n as initialMachineMetadata, o as createSessionMetadata, u as setupOfflineReconnection, v as notifyDaemonSessionStarted, x as MessageQueue2, y as hashObject, z as startHappyServer, T as TitleGenerator, B as registerKillSessionHandler, C as BasePermissionHandler, E as writeSessionModeFile, F as normalizeAcpPermissionMode, H as removeSessionModeFile } from './index-BYZKuQoy.mjs';
|
|
8
8
|
import 'node:child_process';
|
|
9
9
|
import '@agentclientprotocol/sdk';
|
|
10
10
|
import 'axios';
|
|
@@ -483,12 +483,16 @@ function extractConfigSelector(configOptions, category) {
|
|
|
483
483
|
if (option.category === category) {
|
|
484
484
|
return true;
|
|
485
485
|
}
|
|
486
|
+
if (option.category) {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
486
489
|
const id = normalizeComparable(option.id);
|
|
487
490
|
const name = normalizeComparable(option.name);
|
|
488
491
|
if (category === "model") {
|
|
489
492
|
return id.includes("model") || name.includes("model");
|
|
490
493
|
}
|
|
491
|
-
|
|
494
|
+
const mentionsMode = (value) => value.includes("permission") || value.includes("mode") && !value.includes("model");
|
|
495
|
+
return mentionsMode(id) || mentionsMode(name);
|
|
492
496
|
};
|
|
493
497
|
for (const option of configOptions) {
|
|
494
498
|
if (option.type !== "select" || !optionMatchesCategory(option)) {
|
|
@@ -643,7 +647,27 @@ async function runAcp(opts) {
|
|
|
643
647
|
let sawSlashCommands = false;
|
|
644
648
|
let sawModes = false;
|
|
645
649
|
let sawModels = false;
|
|
646
|
-
const
|
|
650
|
+
const initialPermissionMode = opts.permissionMode ?? "default";
|
|
651
|
+
let fileBackedModeActive = false;
|
|
652
|
+
const permissionModeIsFileBacked = () => opts.agentName === "pi" || !modeSelector && !legacyModes;
|
|
653
|
+
let fileBackedPermissionMode = null;
|
|
654
|
+
const publishFileBackedPermissionMode = (mode) => {
|
|
655
|
+
if (fileBackedPermissionMode === mode) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
try {
|
|
659
|
+
writeSessionModeFile(session.sessionId, mode);
|
|
660
|
+
} catch (error) {
|
|
661
|
+
logger.debug(`[${opts.agentName}] Failed to write session mode file:`, error);
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
fileBackedPermissionMode = mode;
|
|
665
|
+
session.updateMetadata((currentMetadata) => ({ ...currentMetadata, permissionMode: mode }));
|
|
666
|
+
logger.debug(`[${opts.agentName}] Published file-backed permission mode: ${mode}`);
|
|
667
|
+
return true;
|
|
668
|
+
};
|
|
669
|
+
const isAssistantVariant = process.env.HAPPY_SESSION_VARIANT === "assistant";
|
|
670
|
+
const happyServer = await startHappyServer(session, { assistant: isAssistantVariant });
|
|
647
671
|
const mcpServers = {
|
|
648
672
|
happy: {
|
|
649
673
|
command: join(projectPath(), "bin", "happy-mcp.mjs"),
|
|
@@ -655,6 +679,11 @@ async function runAcp(opts) {
|
|
|
655
679
|
cwd: process.cwd(),
|
|
656
680
|
command: opts.command,
|
|
657
681
|
args: opts.args,
|
|
682
|
+
env: {
|
|
683
|
+
HAPPY_MCP_URL: happyServer.url,
|
|
684
|
+
HAPPY_SESSION_ID: session.sessionId,
|
|
685
|
+
HAPPY_PERMISSION_MODE: initialPermissionMode
|
|
686
|
+
},
|
|
658
687
|
mcpServers,
|
|
659
688
|
permissionHandler,
|
|
660
689
|
transportHandler: new DefaultTransport(opts.agentName),
|
|
@@ -708,6 +737,15 @@ async function runAcp(opts) {
|
|
|
708
737
|
if (!requestedMode) {
|
|
709
738
|
return;
|
|
710
739
|
}
|
|
740
|
+
if (permissionModeIsFileBacked()) {
|
|
741
|
+
const mode = normalizeAcpPermissionMode(requestedMode);
|
|
742
|
+
if (!mode) {
|
|
743
|
+
logger.debug(`[${opts.agentName}] Ignoring unknown file-backed permission mode request: ${requestedMode}`);
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
publishFileBackedPermissionMode(mode);
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
711
749
|
if (modeSelector) {
|
|
712
750
|
const resolved = resolveRequestedCode(modeSelector.options, requestedMode);
|
|
713
751
|
if (!resolved) {
|
|
@@ -905,6 +943,7 @@ async function runAcp(opts) {
|
|
|
905
943
|
clearPendingTurn();
|
|
906
944
|
}
|
|
907
945
|
if (msg.status === "error" || msg.status === "stopped") {
|
|
946
|
+
if (msg.status === "error") opts.onBackendError?.(msg.detail);
|
|
908
947
|
stopRunnerFromBackendStatus(msg.status, msg.detail);
|
|
909
948
|
}
|
|
910
949
|
}
|
|
@@ -918,10 +957,12 @@ async function runAcp(opts) {
|
|
|
918
957
|
sendEnvelopes(sessionManager.mapMessage(msg));
|
|
919
958
|
};
|
|
920
959
|
backend.onMessage(onBackendMessage);
|
|
960
|
+
const titleGenerator = new TitleGenerator(session);
|
|
921
961
|
session.onUserMessage((message) => {
|
|
922
962
|
if (!message.content.text) {
|
|
923
963
|
return;
|
|
924
964
|
}
|
|
965
|
+
titleGenerator.maybeGenerate(message.content.text);
|
|
925
966
|
if (typeof message.meta?.permissionMode === "string") {
|
|
926
967
|
currentPermissionMode = message.meta.permissionMode;
|
|
927
968
|
logger.debug(`[${opts.agentName}] Requested ACP permission mode: ${currentPermissionMode}`);
|
|
@@ -953,6 +994,22 @@ async function runAcp(opts) {
|
|
|
953
994
|
}
|
|
954
995
|
}
|
|
955
996
|
session.rpcHandlerManager.registerHandler("abort", handleAbort);
|
|
997
|
+
session.rpcHandlerManager.registerHandler(
|
|
998
|
+
"set-permission-mode",
|
|
999
|
+
async (request) => {
|
|
1000
|
+
if (!fileBackedModeActive) {
|
|
1001
|
+
throw new Error(`${opts.agentName} does not support live permission mode changes`);
|
|
1002
|
+
}
|
|
1003
|
+
const mode = typeof request?.mode === "string" ? normalizeAcpPermissionMode(request.mode) : null;
|
|
1004
|
+
if (!mode) {
|
|
1005
|
+
throw new Error("Invalid permission mode");
|
|
1006
|
+
}
|
|
1007
|
+
if (!publishFileBackedPermissionMode(mode)) {
|
|
1008
|
+
throw new Error("Failed to write session mode file");
|
|
1009
|
+
}
|
|
1010
|
+
return { mode };
|
|
1011
|
+
}
|
|
1012
|
+
);
|
|
956
1013
|
registerKillSessionHandler(session.rpcHandlerManager, async () => {
|
|
957
1014
|
shouldExit = true;
|
|
958
1015
|
messageQueue.close();
|
|
@@ -962,6 +1019,10 @@ async function runAcp(opts) {
|
|
|
962
1019
|
try {
|
|
963
1020
|
const started = await backend.startSession();
|
|
964
1021
|
acpSessionId = started.sessionId;
|
|
1022
|
+
if (permissionModeIsFileBacked()) {
|
|
1023
|
+
fileBackedModeActive = true;
|
|
1024
|
+
publishFileBackedPermissionMode(initialPermissionMode);
|
|
1025
|
+
}
|
|
965
1026
|
if (verbose) {
|
|
966
1027
|
if (!sawSlashCommands) {
|
|
967
1028
|
logAcp("muted", `Outgoing slash commands from ${opts.agentName}: not reported yet`);
|
|
@@ -1024,6 +1085,13 @@ async function runAcp(opts) {
|
|
|
1024
1085
|
}
|
|
1025
1086
|
backend.offMessage?.(onBackendMessage);
|
|
1026
1087
|
await backend.dispose();
|
|
1088
|
+
if (fileBackedPermissionMode) {
|
|
1089
|
+
try {
|
|
1090
|
+
removeSessionModeFile(session.sessionId);
|
|
1091
|
+
} catch (error) {
|
|
1092
|
+
logger.debug(`[${opts.agentName}] Failed to remove session mode file:`, error);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1027
1095
|
try {
|
|
1028
1096
|
happyServer.stop();
|
|
1029
1097
|
} catch (error) {
|
|
@@ -1046,9 +1114,11 @@ async function runAcp(opts) {
|
|
|
1046
1114
|
}
|
|
1047
1115
|
}
|
|
1048
1116
|
|
|
1117
|
+
const PI_ACP_COMMAND = "pi-acp";
|
|
1049
1118
|
const KNOWN_ACP_AGENTS = {
|
|
1050
1119
|
gemini: { command: "gemini", args: ["--experimental-acp"] },
|
|
1051
|
-
opencode: { command: "opencode", args: ["acp"] }
|
|
1120
|
+
opencode: { command: "opencode", args: ["acp"] },
|
|
1121
|
+
pi: { command: PI_ACP_COMMAND, args: [] }
|
|
1052
1122
|
};
|
|
1053
1123
|
function resolveAcpAgentConfig(cliArgs) {
|
|
1054
1124
|
if (cliArgs.length === 0) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-DcESl4cI.cjs');
|
|
4
4
|
var claudeAgentSdk = require('@anthropic-ai/claude-agent-sdk');
|
|
5
5
|
require('chalk');
|
|
6
6
|
require('node:os');
|
|
7
7
|
require('node:crypto');
|
|
8
|
-
require('./types-
|
|
8
|
+
require('./types-DD3AK6Nb.cjs');
|
|
9
9
|
require('axios');
|
|
10
10
|
require('node:util');
|
|
11
11
|
require('node:fs');
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var AcpBackend = require('./AcpBackend-
|
|
4
|
-
var persistence = require('./types-
|
|
5
|
-
var AcpSessionManager = require('./AcpSessionManager-
|
|
3
|
+
var AcpBackend = require('./AcpBackend-CrbXvcgQ.cjs');
|
|
4
|
+
var persistence = require('./types-DD3AK6Nb.cjs');
|
|
5
|
+
var AcpSessionManager = require('./AcpSessionManager-CjAVO4RX.cjs');
|
|
6
6
|
var node_crypto = require('node:crypto');
|
|
7
7
|
var path = require('node:path');
|
|
8
|
-
var index = require('./index-
|
|
8
|
+
var index = require('./index-DcESl4cI.cjs');
|
|
9
9
|
require('node:child_process');
|
|
10
10
|
require('@agentclientprotocol/sdk');
|
|
11
11
|
require('axios');
|
|
@@ -484,12 +484,16 @@ function extractConfigSelector(configOptions, category) {
|
|
|
484
484
|
if (option.category === category) {
|
|
485
485
|
return true;
|
|
486
486
|
}
|
|
487
|
+
if (option.category) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
487
490
|
const id = normalizeComparable(option.id);
|
|
488
491
|
const name = normalizeComparable(option.name);
|
|
489
492
|
if (category === "model") {
|
|
490
493
|
return id.includes("model") || name.includes("model");
|
|
491
494
|
}
|
|
492
|
-
|
|
495
|
+
const mentionsMode = (value) => value.includes("permission") || value.includes("mode") && !value.includes("model");
|
|
496
|
+
return mentionsMode(id) || mentionsMode(name);
|
|
493
497
|
};
|
|
494
498
|
for (const option of configOptions) {
|
|
495
499
|
if (option.type !== "select" || !optionMatchesCategory(option)) {
|
|
@@ -644,7 +648,27 @@ async function runAcp(opts) {
|
|
|
644
648
|
let sawSlashCommands = false;
|
|
645
649
|
let sawModes = false;
|
|
646
650
|
let sawModels = false;
|
|
647
|
-
const
|
|
651
|
+
const initialPermissionMode = opts.permissionMode ?? "default";
|
|
652
|
+
let fileBackedModeActive = false;
|
|
653
|
+
const permissionModeIsFileBacked = () => opts.agentName === "pi" || !modeSelector && !legacyModes;
|
|
654
|
+
let fileBackedPermissionMode = null;
|
|
655
|
+
const publishFileBackedPermissionMode = (mode) => {
|
|
656
|
+
if (fileBackedPermissionMode === mode) {
|
|
657
|
+
return true;
|
|
658
|
+
}
|
|
659
|
+
try {
|
|
660
|
+
index.writeSessionModeFile(session.sessionId, mode);
|
|
661
|
+
} catch (error) {
|
|
662
|
+
persistence.logger.debug(`[${opts.agentName}] Failed to write session mode file:`, error);
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
fileBackedPermissionMode = mode;
|
|
666
|
+
session.updateMetadata((currentMetadata) => ({ ...currentMetadata, permissionMode: mode }));
|
|
667
|
+
persistence.logger.debug(`[${opts.agentName}] Published file-backed permission mode: ${mode}`);
|
|
668
|
+
return true;
|
|
669
|
+
};
|
|
670
|
+
const isAssistantVariant = process.env.HAPPY_SESSION_VARIANT === "assistant";
|
|
671
|
+
const happyServer = await index.startHappyServer(session, { assistant: isAssistantVariant });
|
|
648
672
|
const mcpServers = {
|
|
649
673
|
happy: {
|
|
650
674
|
command: path.join(persistence.projectPath(), "bin", "happy-mcp.mjs"),
|
|
@@ -656,6 +680,11 @@ async function runAcp(opts) {
|
|
|
656
680
|
cwd: process.cwd(),
|
|
657
681
|
command: opts.command,
|
|
658
682
|
args: opts.args,
|
|
683
|
+
env: {
|
|
684
|
+
HAPPY_MCP_URL: happyServer.url,
|
|
685
|
+
HAPPY_SESSION_ID: session.sessionId,
|
|
686
|
+
HAPPY_PERMISSION_MODE: initialPermissionMode
|
|
687
|
+
},
|
|
659
688
|
mcpServers,
|
|
660
689
|
permissionHandler,
|
|
661
690
|
transportHandler: new AcpBackend.DefaultTransport(opts.agentName),
|
|
@@ -709,6 +738,15 @@ async function runAcp(opts) {
|
|
|
709
738
|
if (!requestedMode) {
|
|
710
739
|
return;
|
|
711
740
|
}
|
|
741
|
+
if (permissionModeIsFileBacked()) {
|
|
742
|
+
const mode = index.normalizeAcpPermissionMode(requestedMode);
|
|
743
|
+
if (!mode) {
|
|
744
|
+
persistence.logger.debug(`[${opts.agentName}] Ignoring unknown file-backed permission mode request: ${requestedMode}`);
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
publishFileBackedPermissionMode(mode);
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
712
750
|
if (modeSelector) {
|
|
713
751
|
const resolved = resolveRequestedCode(modeSelector.options, requestedMode);
|
|
714
752
|
if (!resolved) {
|
|
@@ -906,6 +944,7 @@ async function runAcp(opts) {
|
|
|
906
944
|
clearPendingTurn();
|
|
907
945
|
}
|
|
908
946
|
if (msg.status === "error" || msg.status === "stopped") {
|
|
947
|
+
if (msg.status === "error") opts.onBackendError?.(msg.detail);
|
|
909
948
|
stopRunnerFromBackendStatus(msg.status, msg.detail);
|
|
910
949
|
}
|
|
911
950
|
}
|
|
@@ -919,10 +958,12 @@ async function runAcp(opts) {
|
|
|
919
958
|
sendEnvelopes(sessionManager.mapMessage(msg));
|
|
920
959
|
};
|
|
921
960
|
backend.onMessage(onBackendMessage);
|
|
961
|
+
const titleGenerator = new index.TitleGenerator(session);
|
|
922
962
|
session.onUserMessage((message) => {
|
|
923
963
|
if (!message.content.text) {
|
|
924
964
|
return;
|
|
925
965
|
}
|
|
966
|
+
titleGenerator.maybeGenerate(message.content.text);
|
|
926
967
|
if (typeof message.meta?.permissionMode === "string") {
|
|
927
968
|
currentPermissionMode = message.meta.permissionMode;
|
|
928
969
|
persistence.logger.debug(`[${opts.agentName}] Requested ACP permission mode: ${currentPermissionMode}`);
|
|
@@ -954,6 +995,22 @@ async function runAcp(opts) {
|
|
|
954
995
|
}
|
|
955
996
|
}
|
|
956
997
|
session.rpcHandlerManager.registerHandler("abort", handleAbort);
|
|
998
|
+
session.rpcHandlerManager.registerHandler(
|
|
999
|
+
"set-permission-mode",
|
|
1000
|
+
async (request) => {
|
|
1001
|
+
if (!fileBackedModeActive) {
|
|
1002
|
+
throw new Error(`${opts.agentName} does not support live permission mode changes`);
|
|
1003
|
+
}
|
|
1004
|
+
const mode = typeof request?.mode === "string" ? index.normalizeAcpPermissionMode(request.mode) : null;
|
|
1005
|
+
if (!mode) {
|
|
1006
|
+
throw new Error("Invalid permission mode");
|
|
1007
|
+
}
|
|
1008
|
+
if (!publishFileBackedPermissionMode(mode)) {
|
|
1009
|
+
throw new Error("Failed to write session mode file");
|
|
1010
|
+
}
|
|
1011
|
+
return { mode };
|
|
1012
|
+
}
|
|
1013
|
+
);
|
|
957
1014
|
index.registerKillSessionHandler(session.rpcHandlerManager, async () => {
|
|
958
1015
|
shouldExit = true;
|
|
959
1016
|
messageQueue.close();
|
|
@@ -963,6 +1020,10 @@ async function runAcp(opts) {
|
|
|
963
1020
|
try {
|
|
964
1021
|
const started = await backend.startSession();
|
|
965
1022
|
acpSessionId = started.sessionId;
|
|
1023
|
+
if (permissionModeIsFileBacked()) {
|
|
1024
|
+
fileBackedModeActive = true;
|
|
1025
|
+
publishFileBackedPermissionMode(initialPermissionMode);
|
|
1026
|
+
}
|
|
966
1027
|
if (verbose) {
|
|
967
1028
|
if (!sawSlashCommands) {
|
|
968
1029
|
logAcp("muted", `Outgoing slash commands from ${opts.agentName}: not reported yet`);
|
|
@@ -1025,6 +1086,13 @@ async function runAcp(opts) {
|
|
|
1025
1086
|
}
|
|
1026
1087
|
backend.offMessage?.(onBackendMessage);
|
|
1027
1088
|
await backend.dispose();
|
|
1089
|
+
if (fileBackedPermissionMode) {
|
|
1090
|
+
try {
|
|
1091
|
+
index.removeSessionModeFile(session.sessionId);
|
|
1092
|
+
} catch (error) {
|
|
1093
|
+
persistence.logger.debug(`[${opts.agentName}] Failed to remove session mode file:`, error);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1028
1096
|
try {
|
|
1029
1097
|
happyServer.stop();
|
|
1030
1098
|
} catch (error) {
|
|
@@ -1047,9 +1115,11 @@ async function runAcp(opts) {
|
|
|
1047
1115
|
}
|
|
1048
1116
|
}
|
|
1049
1117
|
|
|
1118
|
+
const PI_ACP_COMMAND = "pi-acp";
|
|
1050
1119
|
const KNOWN_ACP_AGENTS = {
|
|
1051
1120
|
gemini: { command: "gemini", args: ["--experimental-acp"] },
|
|
1052
|
-
opencode: { command: "opencode", args: ["acp"] }
|
|
1121
|
+
opencode: { command: "opencode", args: ["acp"] },
|
|
1122
|
+
pi: { command: PI_ACP_COMMAND, args: [] }
|
|
1053
1123
|
};
|
|
1054
1124
|
function resolveAcpAgentConfig(cliArgs) {
|
|
1055
1125
|
if (cliArgs.length === 0) {
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import { join, resolve } from 'node:path';
|
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
|
-
import { p as projectPath } from './types-
|
|
7
|
-
import { t as tmuxSupportsSessionEnv } from './index-
|
|
6
|
+
import { p as projectPath } from './types-jSfU_0o1.mjs';
|
|
7
|
+
import { t as tmuxSupportsSessionEnv } from './index-BYZKuQoy.mjs';
|
|
8
8
|
import 'axios';
|
|
9
9
|
import 'node:util';
|
|
10
10
|
import 'node:fs/promises';
|
|
@@ -5,8 +5,8 @@ var path = require('node:path');
|
|
|
5
5
|
var os = require('node:os');
|
|
6
6
|
var node_child_process = require('node:child_process');
|
|
7
7
|
var chalk = require('chalk');
|
|
8
|
-
var persistence = require('./types-
|
|
9
|
-
var index = require('./index-
|
|
8
|
+
var persistence = require('./types-DD3AK6Nb.cjs');
|
|
9
|
+
var index = require('./index-DcESl4cI.cjs');
|
|
10
10
|
require('axios');
|
|
11
11
|
require('node:util');
|
|
12
12
|
require('node:fs/promises');
|
package/dist/lib.cjs
CHANGED
package/dist/lib.d.cts
CHANGED
|
@@ -315,6 +315,7 @@ declare const MachineMetadataSchema: z$1.ZodObject<{
|
|
|
315
315
|
codex: z$1.ZodBoolean;
|
|
316
316
|
gemini: z$1.ZodBoolean;
|
|
317
317
|
openclaw: z$1.ZodBoolean;
|
|
318
|
+
pi: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
318
319
|
detectedAt: z$1.ZodNumber;
|
|
319
320
|
}, z$1.core.$strip>>;
|
|
320
321
|
resumeSupport: z$1.ZodOptional<z$1.ZodObject<{
|
|
@@ -1045,12 +1046,24 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
1045
1046
|
private startSmartReconnect;
|
|
1046
1047
|
}
|
|
1047
1048
|
|
|
1049
|
+
/**
|
|
1050
|
+
* The backends the daemon can spawn as a remote session.
|
|
1051
|
+
*
|
|
1052
|
+
* One list, four consumers: the `spawn --agent` CLI validator, the daemon's
|
|
1053
|
+
* `/spawn-session` zod enum, the machine RPC `SpawnSessionOptions` type and
|
|
1054
|
+
* the daemon's argv switch in `daemon/run.ts`. Before this module each site
|
|
1055
|
+
* carried its own copy and adding a backend meant finding all of them (B-306
|
|
1056
|
+
* found the CLI one missing). Import from here; do not re-list.
|
|
1057
|
+
*/
|
|
1058
|
+
declare const SPAWN_AGENTS: readonly ["claude", "codex", "gemini", "openclaw", "pi"];
|
|
1059
|
+
type SpawnAgent = (typeof SPAWN_AGENTS)[number];
|
|
1060
|
+
|
|
1048
1061
|
interface SpawnSessionOptions {
|
|
1049
1062
|
machineId?: string;
|
|
1050
1063
|
directory: string;
|
|
1051
1064
|
sessionId?: string;
|
|
1052
1065
|
approvedNewDirectoryCreation?: boolean;
|
|
1053
|
-
agent?:
|
|
1066
|
+
agent?: SpawnAgent;
|
|
1054
1067
|
environmentVariables?: Record<string, string>;
|
|
1055
1068
|
token?: string;
|
|
1056
1069
|
/**
|
|
@@ -1235,6 +1248,21 @@ interface TerminalListItem {
|
|
|
1235
1248
|
paneRows?: number;
|
|
1236
1249
|
}
|
|
1237
1250
|
|
|
1251
|
+
interface CLIAvailability {
|
|
1252
|
+
claude: boolean;
|
|
1253
|
+
codex: boolean;
|
|
1254
|
+
gemini: boolean;
|
|
1255
|
+
openclaw: boolean;
|
|
1256
|
+
/**
|
|
1257
|
+
* pi is spawnable only through the pi-acp adapter (`very-happy pi`), so this
|
|
1258
|
+
* is "both `pi` and `pi-acp` resolve on PATH". Older daemons never send the
|
|
1259
|
+
* field; the Web launcher treats absence as unavailable (unlike the other
|
|
1260
|
+
* agents), because such a daemon cannot spawn pi at all.
|
|
1261
|
+
*/
|
|
1262
|
+
pi: boolean;
|
|
1263
|
+
detectedAt: number;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1238
1266
|
/**
|
|
1239
1267
|
* WebSocket client for machine/daemon communication with Happy server
|
|
1240
1268
|
* Similar to ApiSessionClient but for machine-scoped connections
|
|
@@ -1281,6 +1309,18 @@ declare class ApiMachineClient {
|
|
|
1281
1309
|
* waits until there are none. */
|
|
1282
1310
|
hasLiveTerminals(): boolean;
|
|
1283
1311
|
private webTerminal;
|
|
1312
|
+
/**
|
|
1313
|
+
* The CLI availability last advertised in machine metadata (re-probed by
|
|
1314
|
+
* the keep-alive). Null until the first keep-alive tick; the daemon falls
|
|
1315
|
+
* back to its startup probe then.
|
|
1316
|
+
*/
|
|
1317
|
+
getCLIAvailability(): CLIAvailability | null;
|
|
1318
|
+
/**
|
|
1319
|
+
* Title a web terminal from inside it (`very-happy mcp` change_title →
|
|
1320
|
+
* daemon /terminal-title → here). Same tmux truthfulness as the
|
|
1321
|
+
* `set-terminal-title` RPC.
|
|
1322
|
+
*/
|
|
1323
|
+
setTerminalTitle(terminalId: string, title: string, ifAbsent: boolean): boolean;
|
|
1284
1324
|
/**
|
|
1285
1325
|
* Push text to the clipboard of every web client the user has open
|
|
1286
1326
|
* (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
|
package/dist/lib.d.mts
CHANGED
|
@@ -315,6 +315,7 @@ declare const MachineMetadataSchema: z$1.ZodObject<{
|
|
|
315
315
|
codex: z$1.ZodBoolean;
|
|
316
316
|
gemini: z$1.ZodBoolean;
|
|
317
317
|
openclaw: z$1.ZodBoolean;
|
|
318
|
+
pi: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
318
319
|
detectedAt: z$1.ZodNumber;
|
|
319
320
|
}, z$1.core.$strip>>;
|
|
320
321
|
resumeSupport: z$1.ZodOptional<z$1.ZodObject<{
|
|
@@ -1045,12 +1046,24 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
1045
1046
|
private startSmartReconnect;
|
|
1046
1047
|
}
|
|
1047
1048
|
|
|
1049
|
+
/**
|
|
1050
|
+
* The backends the daemon can spawn as a remote session.
|
|
1051
|
+
*
|
|
1052
|
+
* One list, four consumers: the `spawn --agent` CLI validator, the daemon's
|
|
1053
|
+
* `/spawn-session` zod enum, the machine RPC `SpawnSessionOptions` type and
|
|
1054
|
+
* the daemon's argv switch in `daemon/run.ts`. Before this module each site
|
|
1055
|
+
* carried its own copy and adding a backend meant finding all of them (B-306
|
|
1056
|
+
* found the CLI one missing). Import from here; do not re-list.
|
|
1057
|
+
*/
|
|
1058
|
+
declare const SPAWN_AGENTS: readonly ["claude", "codex", "gemini", "openclaw", "pi"];
|
|
1059
|
+
type SpawnAgent = (typeof SPAWN_AGENTS)[number];
|
|
1060
|
+
|
|
1048
1061
|
interface SpawnSessionOptions {
|
|
1049
1062
|
machineId?: string;
|
|
1050
1063
|
directory: string;
|
|
1051
1064
|
sessionId?: string;
|
|
1052
1065
|
approvedNewDirectoryCreation?: boolean;
|
|
1053
|
-
agent?:
|
|
1066
|
+
agent?: SpawnAgent;
|
|
1054
1067
|
environmentVariables?: Record<string, string>;
|
|
1055
1068
|
token?: string;
|
|
1056
1069
|
/**
|
|
@@ -1235,6 +1248,21 @@ interface TerminalListItem {
|
|
|
1235
1248
|
paneRows?: number;
|
|
1236
1249
|
}
|
|
1237
1250
|
|
|
1251
|
+
interface CLIAvailability {
|
|
1252
|
+
claude: boolean;
|
|
1253
|
+
codex: boolean;
|
|
1254
|
+
gemini: boolean;
|
|
1255
|
+
openclaw: boolean;
|
|
1256
|
+
/**
|
|
1257
|
+
* pi is spawnable only through the pi-acp adapter (`very-happy pi`), so this
|
|
1258
|
+
* is "both `pi` and `pi-acp` resolve on PATH". Older daemons never send the
|
|
1259
|
+
* field; the Web launcher treats absence as unavailable (unlike the other
|
|
1260
|
+
* agents), because such a daemon cannot spawn pi at all.
|
|
1261
|
+
*/
|
|
1262
|
+
pi: boolean;
|
|
1263
|
+
detectedAt: number;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1238
1266
|
/**
|
|
1239
1267
|
* WebSocket client for machine/daemon communication with Happy server
|
|
1240
1268
|
* Similar to ApiSessionClient but for machine-scoped connections
|
|
@@ -1281,6 +1309,18 @@ declare class ApiMachineClient {
|
|
|
1281
1309
|
* waits until there are none. */
|
|
1282
1310
|
hasLiveTerminals(): boolean;
|
|
1283
1311
|
private webTerminal;
|
|
1312
|
+
/**
|
|
1313
|
+
* The CLI availability last advertised in machine metadata (re-probed by
|
|
1314
|
+
* the keep-alive). Null until the first keep-alive tick; the daemon falls
|
|
1315
|
+
* back to its startup probe then.
|
|
1316
|
+
*/
|
|
1317
|
+
getCLIAvailability(): CLIAvailability | null;
|
|
1318
|
+
/**
|
|
1319
|
+
* Title a web terminal from inside it (`very-happy mcp` change_title →
|
|
1320
|
+
* daemon /terminal-title → here). Same tmux truthfulness as the
|
|
1321
|
+
* `set-terminal-title` RPC.
|
|
1322
|
+
*/
|
|
1323
|
+
setTerminalTitle(terminalId: string, title: string, ifAbsent: boolean): boolean;
|
|
1284
1324
|
/**
|
|
1285
1325
|
* Push text to the clipboard of every web client the user has open
|
|
1286
1326
|
* (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
|
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-jSfU_0o1.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'node:util';
|