very-happy-cli 0.2.159 → 0.2.161
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-VsfkZiVF.mjs → AcpBackend-6U6pQgx1.mjs} +4 -2
- package/dist/{AcpBackend-DUYFlyfN.cjs → AcpBackend-Ba98QDif.cjs} +78 -76
- package/dist/{AcpSessionManager-Bdv8LWXh.cjs → AcpSessionManager-BAY1Pggx.cjs} +9 -9
- package/dist/{AcpSessionManager-rYtVb0kN.mjs → AcpSessionManager-CoMWFVw3.mjs} +1 -1
- package/dist/BasePermissionHandler-2R0uH2CI.cjs +157 -0
- package/dist/BasePermissionHandler-BvvhBTja.mjs +155 -0
- package/dist/BaseReasoningProcessor-DyhO1uoU.mjs +198 -0
- package/dist/BaseReasoningProcessor-fsVNmCEF.cjs +200 -0
- package/dist/RemoteModeDisplay-D-HewyXg.mjs +150 -0
- package/dist/RemoteModeDisplay-NC1gPHtj.cjs +153 -0
- package/dist/agentAttachments-Dbw8iMCZ.cjs +20 -0
- package/dist/agentAttachments-M_B5qEF2.mjs +18 -0
- package/dist/agentGuidance-B5NATuFa.cjs +28 -0
- package/dist/agentGuidance-CQuNlNx8.mjs +20 -0
- package/dist/{agentHome-CvsJyeQB.mjs → agentHome-Ck1i1TQB.mjs} +8 -22
- package/dist/{agentHome-CHh4lmjM.cjs → agentHome-DvNnGphb.cjs} +14 -28
- package/dist/api-B2vLMS-z.cjs +3346 -0
- package/dist/api-SffjRQ1b.mjs +3339 -0
- package/dist/{types-Dh-s4Lqs.mjs → apiMachine-BpW9t8MO.mjs} +9116 -16205
- package/dist/{types-BbvK1Tr_.cjs → apiMachine-gFA54X7y.cjs} +9104 -16247
- package/dist/assistantTools-BfA0R3_m.cjs +380 -0
- package/dist/assistantTools-CgiTbnWb.mjs +376 -0
- package/dist/attachmentContent-CSGxr71v.mjs +82 -0
- package/dist/attachmentContent-DMMZzevR.cjs +88 -0
- package/dist/attachmentLimits-CzVrqgLR.cjs +354 -0
- package/dist/attachmentLimits-yba1uHFO.mjs +348 -0
- package/dist/auth-Bt4ceBBy.cjs +227 -0
- package/dist/auth-CYHjQ8oQ.mjs +225 -0
- package/dist/auth-DdyVZSo6.mjs +218 -0
- package/dist/auth-x4CEoysH.cjs +220 -0
- package/dist/authRelay-BdYkC1Po.cjs +156 -0
- package/dist/authRelay-DSAvg1uv.mjs +143 -0
- package/dist/{auto-DKmEls8Z.cjs → auto-BDXDUnjB.cjs} +70 -79
- package/dist/{auto-nb8GhRRy.mjs → auto-CXLlRi3a.mjs} +27 -36
- package/dist/backgroundTaskActivity-8PdPxrvy.mjs +149 -0
- package/dist/backgroundTaskActivity-CBvUdj39.cjs +157 -0
- package/dist/bootstrap-BNQq05jR.mjs +112 -0
- package/dist/bootstrap-CkgIq8N3.cjs +116 -0
- package/dist/browser-9pyhQr1R.mjs +20 -0
- package/dist/browser-BDOlKWYe.cjs +22 -0
- package/dist/claudeCliPath-BqkaH2oR.mjs +8 -0
- package/dist/claudeCliPath-U4HHmV4r.cjs +10 -0
- package/dist/claudeLocal-BDuGFnjJ.cjs +343 -0
- package/dist/claudeLocal-CQa8qnwq.mjs +339 -0
- package/dist/claudeLocalLauncher-Bd5I2-j6.cjs +154 -0
- package/dist/claudeLocalLauncher-CDqQI9ak.mjs +152 -0
- package/dist/cliUpdate-DsKXPFYp.cjs +120 -0
- package/dist/cliUpdate-Y34VGe9Y.mjs +112 -0
- package/dist/client-Brn-UwVk.mjs +100 -0
- package/dist/client-CXb1VJui.mjs +112 -0
- package/dist/client-C_axwRry.cjs +104 -0
- package/dist/client-DOBWJL3u.cjs +119 -0
- package/dist/codex/happyMcpStdioBridge.cjs +33 -14
- package/dist/codex/happyMcpStdioBridge.mjs +26 -7
- package/dist/codexAppServerClient-ZzhUTWPo.cjs +1090 -0
- package/dist/codexAppServerClient-oeQKD6Qf.mjs +1088 -0
- package/dist/codexCommand-C7H0NpBe.cjs +2088 -0
- package/dist/codexCommand-CJ82bl3l.mjs +2086 -0
- package/dist/codexThreadFork-BCaEMBiM.mjs +338 -0
- package/dist/codexThreadFork-BZqF-9bX.cjs +350 -0
- package/dist/{config-ClLtM6F3.mjs → config-BglnktIo.mjs} +7 -40
- package/dist/{config-DLx-vW3I.cjs → config-CYpL1Ahd.cjs} +26 -59
- package/dist/configuration-DoWFJUPm.mjs +170 -0
- package/dist/configuration-v9f8LM9T.cjs +181 -0
- package/dist/connect-hgcNjyAB.mjs +682 -0
- package/dist/connect-yEvjdRvx.cjs +684 -0
- package/dist/constants-BC4St0xd.mjs +11 -0
- package/dist/constants-VJ0N6WuG.cjs +17 -0
- package/dist/contentLogMetadata-BlWI0egu.mjs +51 -0
- package/dist/contentLogMetadata-ZSFk_NjQ.cjs +54 -0
- package/dist/context-B45vMtSZ.cjs +69 -0
- package/dist/context-C9GHPLEm.mjs +65 -0
- package/dist/controlClient-DjoKTtgK.mjs +260 -0
- package/dist/controlClient-fEHE85bH.cjs +279 -0
- package/dist/createSessionMetadata-BRLB9CNO.cjs +58 -0
- package/dist/createSessionMetadata-mIeehclp.mjs +54 -0
- package/dist/defaultPermissionMode-BnxJPVHT.mjs +4 -0
- package/dist/defaultPermissionMode-CxmTXUQR.cjs +7 -0
- package/dist/detectCLI-CSGMlV51.mjs +58 -0
- package/dist/detectCLI-DR9ZaN6B.cjs +61 -0
- package/dist/deterministicJson-DKDP_mM-.cjs +507 -0
- package/dist/deterministicJson-p835AdAU.mjs +502 -0
- package/dist/doctor-BPkYWSuq.mjs +75 -0
- package/dist/doctor-BeUuQXFs.mjs +391 -0
- package/dist/doctor-hVNnSZJn.cjs +395 -0
- package/dist/doctor-u46qYYKX.cjs +79 -0
- package/dist/doctorReadiness-BCZGcN0a.cjs +151 -0
- package/dist/doctorReadiness-C208SMN9.mjs +142 -0
- package/dist/editPaths-BVfS_FFL.mjs +68 -0
- package/dist/editPaths-Bqp4OFPw.cjs +73 -0
- package/dist/ensureDaemonRunning-CO7d1gOC.mjs +61 -0
- package/dist/ensureDaemonRunning-Dg9aZfjs.cjs +64 -0
- package/dist/handleResumeCommand-BiTPK0qd.mjs +240 -0
- package/dist/handleResumeCommand-DnVmy7a3.cjs +245 -0
- package/dist/ids-B6ZC0HGt.cjs +13 -0
- package/dist/ids-DU6sLx4C.mjs +10 -0
- package/dist/index-B6UGRQ7h.mjs +102 -0
- package/dist/{index-2mCaeKyf.mjs → index-CAFwetLk.mjs} +68 -38
- package/dist/index-Cqx-Raq6.mjs +68 -0
- package/dist/index-D3kI0hDR.cjs +107 -0
- package/dist/index-DA7yINuk.cjs +994 -0
- package/dist/{index-BEOMECtE.cjs → index-LIn6nCcq.cjs} +121 -91
- package/dist/index-Pf2cV9cn.cjs +182 -0
- package/dist/index-SPGPenK5.mjs +158 -0
- package/dist/index-gNTWtSKN.cjs +71 -0
- package/dist/index-qdS1friN.mjs +949 -0
- package/dist/index.cjs +5 -46
- package/dist/index.mjs +5 -46
- package/dist/{install-BPhJppvd.mjs → install-BO_W7VhL.mjs} +37 -37
- package/dist/install-Bu85vlHD.cjs +88 -0
- package/dist/install-ClUUl3yp.mjs +86 -0
- package/dist/{install-BOHrUaFM.cjs → install-Cs5qAPrB.cjs} +38 -38
- package/dist/{installPiTools-DuZ6jZvX.cjs → installPiTools-BKnXjrVu.cjs} +2 -3
- package/dist/{installPiTools-Cj7yU9Fc.mjs → installPiTools-B_CdM5_2.mjs} +1 -2
- package/dist/{installTerminalHooks-Cou3WUf3.cjs → installTerminalHooks-BQZbvxsZ.cjs} +5 -40
- package/dist/{installTerminalHooks-WeznjkuC.mjs → installTerminalHooks-By7gBMEF.mjs} +3 -38
- package/dist/lib.cjs +28 -19
- package/dist/lib.d.cts +12 -2
- package/dist/lib.d.mts +12 -2
- package/dist/lib.mjs +23 -14
- package/dist/lidState-C2dI0FAN.mjs +297 -0
- package/dist/lidState-KHHu1015.cjs +305 -0
- package/dist/limits-C-a7gr04.cjs +43 -0
- package/dist/limits-DIo7rEBR.mjs +36 -0
- package/dist/localHappyAgentAuth-BXiHPXdC.cjs +86 -0
- package/dist/localHappyAgentAuth-DCsetiyG.mjs +82 -0
- package/dist/logger-Bc8-u1w0.cjs +275 -0
- package/dist/logger-fXoNzNuB.mjs +271 -0
- package/dist/loginShellEnv-BkuYtExZ.cjs +182 -0
- package/dist/loginShellEnv-Dw8M7tkI.mjs +167 -0
- package/dist/machineMetadata-BHjehxJY.mjs +38 -0
- package/dist/machineMetadata-BibDMFVx.cjs +41 -0
- package/dist/main-BktM4A1K.mjs +939 -0
- package/dist/main-CLaX-t-b.cjs +941 -0
- package/dist/manager-BQ4flvQZ.mjs +101 -0
- package/dist/manager-Cly8xVIR.cjs +105 -0
- package/dist/{mcp-Dy3f_K0h.mjs → mcp-CeUd9KDr.mjs} +27 -33
- package/dist/{mcp-CPYbtsYG.cjs → mcp-GBfE70nk.cjs} +42 -48
- package/dist/messageBuffer-BWlGgR3A.mjs +71 -0
- package/dist/messageBuffer-fJMH6uY8.cjs +73 -0
- package/dist/mirrorProtocol-BNLtoWjO.mjs +170 -0
- package/dist/mirrorProtocol-BUtmg1ws.cjs +186 -0
- package/dist/oneShotPrompts-CL0dip9C.cjs +16 -0
- package/dist/oneShotPrompts-DT4p6RNd.mjs +12 -0
- package/dist/package-Cl5BEP5x.cjs +173 -0
- package/dist/package-uOg9SCKi.mjs +171 -0
- package/dist/path-B7zW-WwE.cjs +18 -0
- package/dist/path-D2wdaNSk.mjs +15 -0
- package/dist/peerTools-CIeiy9wn.cjs +283 -0
- package/dist/peerTools-Dz3_7Bkk.mjs +272 -0
- package/dist/permissionMode-CH4FoZfU.mjs +80 -0
- package/dist/permissionMode-CrV-XuMs.cjs +87 -0
- package/dist/persistence-CBNMzSa8.cjs +414 -0
- package/dist/persistence-oET5n61f.mjs +372 -0
- package/dist/piExtension.mjs +2 -1
- package/dist/piRunnerArgs-Bf7RUF__.cjs +66 -0
- package/dist/piRunnerArgs-Dk1ncwHF.mjs +59 -0
- package/dist/{piRuntime-NtF0YqjH.cjs → piRuntime-B_6TE9Eb.cjs} +4 -4
- package/dist/{piRuntime-kLZNpAAl.mjs → piRuntime-BwRdhK_N.mjs} +2 -2
- package/dist/{piTerminal-B0fEOV_2.mjs → piTerminal-Bap3R8Re.mjs} +32 -35
- package/dist/{piTerminal-9J0GAKzb.cjs → piTerminal-CagmEoez.cjs} +32 -35
- package/dist/previewPath-B0rBdhy1.cjs +83 -0
- package/dist/previewPath-CXN4Vag0.mjs +81 -0
- package/dist/projectPath-BTBIMB57.mjs +10 -0
- package/dist/projectPath-ChLhdOyt.cjs +13 -0
- package/dist/registerCommonHandlers-BjSV2Skz.cjs +538 -0
- package/dist/registerCommonHandlers-CrgvJsOy.mjs +536 -0
- package/dist/registerKillSessionHandler-6TC2S3lf.cjs +366 -0
- package/dist/registerKillSessionHandler-Cbc8Rgtd.mjs +363 -0
- package/dist/remoteSessionClient-BNx78NLb.cjs +634 -0
- package/dist/remoteSessionClient-CO7qOjR0.mjs +612 -0
- package/dist/resources-BdFBQi8r.mjs +117 -0
- package/dist/resources-JDPugcDq.cjs +120 -0
- package/dist/run-2l5vSt2h.mjs +5743 -0
- package/dist/run-D5xAEWSB.cjs +5766 -0
- package/dist/runClaude-BX6ixjtW.cjs +894 -0
- package/dist/runClaude-BgN6xo05.mjs +892 -0
- package/dist/runClaudeDeps-Bp20MScE.cjs +4168 -0
- package/dist/runClaudeDeps-COBBhD9o.mjs +4129 -0
- package/dist/{runGemini-F-mqx3_K.cjs → runGemini-CSMPkt0p.cjs} +202 -175
- package/dist/{runGemini-DV6Ouadt.mjs → runGemini-Cc2jq-uh.mjs} +58 -31
- package/dist/{runOpenClaw-D7MlPS5n.mjs → runOpenClaw-CIlCwdW2.mjs} +31 -32
- package/dist/{runOpenClaw-Qqo9j63M.cjs → runOpenClaw-YBwua4Rf.cjs} +64 -65
- package/dist/sandbox-C4gXLP1p.cjs +187 -0
- package/dist/sandbox-CNkwOtHI.mjs +180 -0
- package/dist/selfCheck-CU8xSDsl.cjs +87 -0
- package/dist/selfCheck-hJ6PCh7v.mjs +84 -0
- package/dist/{send-CLhYXNgy.mjs → send-CGHcKZ-w.mjs} +12 -5
- package/dist/{send-4qJTCAYW.cjs → send-DY9Nr-x4.cjs} +16 -9
- package/dist/server-II51Mimf.cjs +407 -0
- package/dist/server-m2b5pamZ.mjs +404 -0
- package/dist/sessionLock-7ePAYDOg.cjs +205 -0
- package/dist/sessionLock-Cw6FmbMv.mjs +197 -0
- package/dist/sessionModeFile-BVCV5f7E.cjs +36 -0
- package/dist/sessionModeFile-CDmDyRkD.mjs +32 -0
- package/dist/sessionOps-C_f1wKOr.mjs +760 -0
- package/dist/sessionOps-DJdExmBy.cjs +783 -0
- package/dist/sessionScanner-CaAHLyNV.mjs +206 -0
- package/dist/sessionScanner-D1goKdd3.cjs +209 -0
- package/dist/{sessions-Bh1pyddi.cjs → sessions-DGs6ALNo.cjs} +37 -28
- package/dist/{sessions-CzIH2rGp.mjs → sessions-DnvmWUel.mjs} +17 -8
- package/dist/setupOfflineReconnection-CVViqZft.mjs +72 -0
- package/dist/setupOfflineReconnection-R7XuR_sj.cjs +74 -0
- package/dist/smallFastModel-BLNgMrwR.mjs +18 -0
- package/dist/smallFastModel-D_uxGMo3.cjs +21 -0
- package/dist/{spawn-CmFOSVdW.cjs → spawn-CXTH7qg1.cjs} +61 -65
- package/dist/{spawn-CPIWlPOM.mjs → spawn-DNYSvFtC.mjs} +35 -40
- package/dist/spawnAgents-BGQiEF-w.cjs +52 -0
- package/dist/spawnAgents-DZzZ9jMI.mjs +45 -0
- package/dist/spawnHappyCLI-BhYj84rv.cjs +66 -0
- package/dist/spawnHappyCLI-cqWQbwsb.mjs +64 -0
- package/dist/specialCommands-BSqhYg5X.mjs +52 -0
- package/dist/specialCommands-DSsTeRej.cjs +54 -0
- package/dist/startFileWatcher-CKKx-8ZO.cjs +71 -0
- package/dist/startFileWatcher-CdegMbJj.mjs +69 -0
- package/dist/startupPlan-BLMbfQIH.cjs +12 -0
- package/dist/startupPlan-DFMyNgAs.mjs +10 -0
- package/dist/streamRelay-BiKw59Cc.cjs +233 -0
- package/dist/streamRelay-FPVbHpbM.mjs +231 -0
- package/dist/sync-CVk4QERO.cjs +71 -0
- package/dist/sync-CxD-w_40.mjs +69 -0
- package/dist/systemPrompt-BygJcmbi.cjs +97 -0
- package/dist/systemPrompt-DmtypUc7.mjs +94 -0
- package/dist/{teams-CEahj4cm.mjs → teams-BOC6nIPL.mjs} +9 -40
- package/dist/{teams-CB1R9-Z9.cjs → teams-BsvpOBfn.cjs} +14 -45
- package/dist/template-BaHAmH2K.cjs +129 -0
- package/dist/template-CiOPa2rd.mjs +121 -0
- package/dist/{terminalTitleSuggest-DKgX3osW.mjs → terminalTitleSuggest-CeKsX_V6.mjs} +1 -9
- package/dist/{terminalTitleSuggest-Dji8I0Jy.cjs → terminalTitleSuggest-DhvRFX3H.cjs} +0 -10
- package/dist/terminals-B_bfC9c2.cjs +250 -0
- package/dist/terminals-Dlg0x3nY.mjs +235 -0
- package/dist/time-BZNdNiIV.mjs +38 -0
- package/dist/time-CNRE4ChD.cjs +42 -0
- package/dist/titleGenerator-CFRhU-xq.cjs +172 -0
- package/dist/titleGenerator-ox6ptCsp.mjs +166 -0
- package/dist/tmuxSocket-B8Yx20sT.mjs +19 -0
- package/dist/tmuxSocket-D-Xt6Vn-.cjs +24 -0
- package/dist/{todo-DqyRI4wP.cjs → todo-B-KB7oAB.cjs} +15 -12
- package/dist/{todo-Cknp5D4U.mjs → todo-C5KBVbUw.mjs} +11 -8
- package/dist/tools-BZabNIid.mjs +177 -0
- package/dist/tools-BmQQUATY.mjs +60 -0
- package/dist/tools-CsSovyNp.cjs +180 -0
- package/dist/tools-lMDra4Pv.cjs +63 -0
- package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
- package/dist/trimIdent-BAjmv_TG.mjs +20 -0
- package/dist/types-CRS-srZK.cjs +66 -0
- package/dist/types-CkqAACXx.mjs +64 -0
- package/dist/uninstall-B1WLtC1d.mjs +47 -0
- package/dist/uninstall-fvA5aWpU.cjs +49 -0
- package/package.json +7 -7
- package/scripts/session_hook_forwarder.cjs +9 -2
- package/dist/agentGuidance-BRDN1NoZ.cjs +0 -2217
- package/dist/agentGuidance-KgvYuF3R.mjs +0 -2145
- package/dist/index-BF6WfgV5.mjs +0 -19624
- package/dist/index-C-JazrMB.mjs +0 -52
- package/dist/index-blDSadUR.cjs +0 -58
- package/dist/index-rH3DrQ5B.cjs +0 -19688
- package/dist/limits-BH5CV5vR.cjs +0 -2683
- package/dist/limits-CjRj8IX5.mjs +0 -2558
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function shellescape(s) {
|
|
4
|
+
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const VH_TMUX_SOCKET_ENV = "VH_TMUX_SOCKET";
|
|
8
|
+
function tmuxSocketFlags(env = process.env) {
|
|
9
|
+
const socket = env[VH_TMUX_SOCKET_ENV];
|
|
10
|
+
return socket ? ["-S", socket] : [];
|
|
11
|
+
}
|
|
12
|
+
function tmuxArgs(args, env = process.env) {
|
|
13
|
+
return [...tmuxSocketFlags(env), ...args];
|
|
14
|
+
}
|
|
15
|
+
function scrubTmuxClientEnv(env) {
|
|
16
|
+
delete env.TMUX;
|
|
17
|
+
delete env.TMUX_PANE;
|
|
18
|
+
return env;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.VH_TMUX_SOCKET_ENV = VH_TMUX_SOCKET_ENV;
|
|
22
|
+
exports.scrubTmuxClientEnv = scrubTmuxClientEnv;
|
|
23
|
+
exports.shellescape = shellescape;
|
|
24
|
+
exports.tmuxArgs = tmuxArgs;
|
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var configuration = require('./configuration-v9f8LM9T.cjs');
|
|
4
|
+
var index = require('./index-DA7yINuk.cjs');
|
|
5
|
+
var persistence = require('./persistence-CBNMzSa8.cjs');
|
|
6
|
+
var context = require('./context-B45vMtSZ.cjs');
|
|
7
|
+
require('node:fs');
|
|
8
|
+
require('node:os');
|
|
9
|
+
require('node:path');
|
|
10
|
+
require('./package-Cl5BEP5x.cjs');
|
|
11
|
+
require('node:fs/promises');
|
|
5
12
|
require('zod');
|
|
6
13
|
require('@paralleldrive/cuid2');
|
|
7
|
-
require('
|
|
8
|
-
require('node:fs');
|
|
14
|
+
require('./authRelay-BdYkC1Po.cjs');
|
|
9
15
|
require('node:crypto');
|
|
10
16
|
require('tweetnacl');
|
|
17
|
+
require('./logger-Bc8-u1w0.cjs');
|
|
11
18
|
require('chalk');
|
|
12
19
|
require('node:util');
|
|
13
|
-
require('node:os');
|
|
14
|
-
require('node:path');
|
|
15
|
-
require('axios');
|
|
16
|
-
require('socket.io-client');
|
|
17
20
|
|
|
18
21
|
async function authenticatedBuiltinTodoClient() {
|
|
19
22
|
if (process.env.VH_TEAM_SCOPE_FILE !== void 0) {
|
|
20
23
|
throw new Error("Scoped Teams sessions cannot access account Todos; ask the owner session.");
|
|
21
24
|
}
|
|
22
25
|
const sessionId = process.env.HAPPY_SESSION_ID;
|
|
23
|
-
if (sessionId && await
|
|
26
|
+
if (sessionId && await context.readTeamScope(context.teamScopePath(sessionId))) {
|
|
24
27
|
throw new Error("Scoped Teams sessions cannot access account Todos; ask the owner session.");
|
|
25
28
|
}
|
|
26
29
|
const credentials = await persistence.readCredentialsForConfiguredRelay();
|
|
27
30
|
if (!credentials) throw new Error("Sign in to Very Happy with `very-happy auth login` before accessing Todos.");
|
|
28
|
-
return
|
|
31
|
+
return index.createBuiltinTodoClient(credentials, { serverUrl: configuration.configuration.serverUrl, clientId: "very-happy-cli-todo" });
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
const TODO_HELP = `very-happy todo \u2014 account-owned built-in Todos (JSON output)
|
|
@@ -89,7 +92,7 @@ async function handleTodoCommand(args) {
|
|
|
89
92
|
return;
|
|
90
93
|
}
|
|
91
94
|
if (command.action === "skill") {
|
|
92
|
-
console.log(
|
|
95
|
+
console.log(index.BUILTIN_TODO_SKILL);
|
|
93
96
|
return;
|
|
94
97
|
}
|
|
95
98
|
const client = await authenticatedBuiltinTodoClient();
|
|
@@ -108,7 +111,7 @@ async function handleTodoCommand(args) {
|
|
|
108
111
|
} else result = await client.update(record, command.action === "edit" ? { ...command.title !== void 0 ? { title: command.title } : {}, ...command.note !== void 0 ? { note: command.note } : {} } : { status: command.action === "complete" ? "done" : "open" });
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
|
-
console.log(JSON.stringify({ serverUrl:
|
|
114
|
+
console.log(JSON.stringify({ serverUrl: configuration.configuration.serverUrl, result }));
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
exports.TODO_HELP = TODO_HELP;
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { c as configuration } from './configuration-DoWFJUPm.mjs';
|
|
2
|
+
import { f as createBuiltinTodoClient, B as BUILTIN_TODO_SKILL } from './index-qdS1friN.mjs';
|
|
3
|
+
import { readCredentialsForConfiguredRelay } from './persistence-oET5n61f.mjs';
|
|
4
|
+
import { r as readTeamScope, t as teamScopePath } from './context-C9GHPLEm.mjs';
|
|
5
|
+
import 'node:fs';
|
|
6
|
+
import 'node:os';
|
|
7
|
+
import 'node:path';
|
|
8
|
+
import './package-uOg9SCKi.mjs';
|
|
9
|
+
import 'node:fs/promises';
|
|
3
10
|
import 'zod';
|
|
4
11
|
import '@paralleldrive/cuid2';
|
|
5
|
-
import '
|
|
6
|
-
import 'node:fs';
|
|
12
|
+
import './authRelay-DSAvg1uv.mjs';
|
|
7
13
|
import 'node:crypto';
|
|
8
14
|
import 'tweetnacl';
|
|
15
|
+
import './logger-fXoNzNuB.mjs';
|
|
9
16
|
import 'chalk';
|
|
10
17
|
import 'node:util';
|
|
11
|
-
import 'node:os';
|
|
12
|
-
import 'node:path';
|
|
13
|
-
import 'axios';
|
|
14
|
-
import 'socket.io-client';
|
|
15
18
|
|
|
16
19
|
async function authenticatedBuiltinTodoClient() {
|
|
17
20
|
if (process.env.VH_TEAM_SCOPE_FILE !== void 0) {
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { a as AutomationNameSchema, b as AutomationConcurrencySchema, c as AutomationActionSchema, d as AutomationTriggerSchema } from './index-qdS1friN.mjs';
|
|
3
|
+
import { a as authenticatedAutomationsClient, b as automationRunIdFromEnv } from './client-CXb1VJui.mjs';
|
|
4
|
+
|
|
5
|
+
const AUTOMATION_TOOL_NAMES = [
|
|
6
|
+
"automation_list",
|
|
7
|
+
"automation_get",
|
|
8
|
+
"automation_create",
|
|
9
|
+
"automation_update",
|
|
10
|
+
"automation_pause",
|
|
11
|
+
"automation_resume",
|
|
12
|
+
"automation_delete",
|
|
13
|
+
"automation_run",
|
|
14
|
+
"automation_fire",
|
|
15
|
+
"automation_runs",
|
|
16
|
+
"automation_report",
|
|
17
|
+
"automation_ack"
|
|
18
|
+
];
|
|
19
|
+
const id = z.string().min(1).max(128);
|
|
20
|
+
const ref = { name: AutomationNameSchema.optional().describe("Automation name"), id: id.optional().describe("Automation id (alternative to name)") };
|
|
21
|
+
const payload = z.string().max(65536).optional().describe("Payload text; JSON lets prompts use {{payload.field}}");
|
|
22
|
+
const maxRuntimeMs = z.number().int().min(6e4).max(7 * 864e5).optional();
|
|
23
|
+
const AUTOMATION_TOOL_SCHEMAS = {
|
|
24
|
+
automation_list: { description: "List this account\u2019s automations (name, trigger, action, machine, status, next run). Defaults to every machine.", readOnly: true, inputSchema: { machineId: id.optional().describe("Only this machine id, or 'this' for the current machine") } },
|
|
25
|
+
automation_get: { description: "Read one automation by name or id, including its version (needed for automation_update).", readOnly: true, inputSchema: ref },
|
|
26
|
+
automation_create: {
|
|
27
|
+
description: "Create an automation: a trigger (cron+tz / interval / once / manual) and an action (spawn a session, send into a session, or run a script argv) on one machine. Defaults to the current machine. Prompts and argv may use {{payload}}, {{payload.path}}, {{run.id}}, {{automation.name}}, {{now}}.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
name: AutomationNameSchema,
|
|
30
|
+
description: z.string().max(4e3).optional(),
|
|
31
|
+
machineId: id.optional().describe("Target machine id; omit or 'this' for the current machine"),
|
|
32
|
+
trigger: AutomationTriggerSchema,
|
|
33
|
+
action: AutomationActionSchema,
|
|
34
|
+
concurrency: AutomationConcurrencySchema.optional().describe("skip (default): a run while another is active is recorded as skipped; queue: it waits"),
|
|
35
|
+
maxRuntimeMs,
|
|
36
|
+
paused: z.boolean().optional().describe("Create paused")
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
automation_update: {
|
|
40
|
+
description: "Change an automation (name / description / machine / trigger / action / concurrency / maxRuntimeMs). Requires the current version from automation_get; a stale version is rejected.",
|
|
41
|
+
inputSchema: {
|
|
42
|
+
...ref,
|
|
43
|
+
version: z.number().int().positive(),
|
|
44
|
+
newName: AutomationNameSchema.optional(),
|
|
45
|
+
description: z.string().max(4e3).nullable().optional(),
|
|
46
|
+
machineId: id.optional(),
|
|
47
|
+
trigger: AutomationTriggerSchema.optional(),
|
|
48
|
+
action: AutomationActionSchema.optional(),
|
|
49
|
+
concurrency: AutomationConcurrencySchema.optional(),
|
|
50
|
+
maxRuntimeMs
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
automation_pause: { description: "Pause an automation: no new scheduled runs and fire is refused until resumed.", inputSchema: ref },
|
|
54
|
+
automation_resume: { description: "Resume a paused automation; the next run is computed from now.", inputSchema: ref },
|
|
55
|
+
automation_delete: { description: "Delete an automation and its run history. Irreversible.", destructive: true, inputSchema: ref },
|
|
56
|
+
automation_run: { description: "Queue one run of an automation now (source: manual), optionally with a payload.", inputSchema: { ...ref, payload } },
|
|
57
|
+
automation_fire: { description: "Trigger an automation by name as an external event, with an optional payload and dedupe key (the same key within 24h returns the original run).", inputSchema: { name: AutomationNameSchema, payload, dedupeKey: z.string().min(1).max(256).optional() } },
|
|
58
|
+
automation_runs: { description: "List runs, newest first: status, session, summary, error, attention. Filter by automation, status or attention.", readOnly: true, inputSchema: { ...ref, status: z.string().min(1).max(64).optional(), attention: z.boolean().optional().describe("Only runs flagged for a human"), limit: z.number().int().min(1).max(200).optional() } },
|
|
59
|
+
automation_report: {
|
|
60
|
+
description: 'Report the result of an automation run. Without runId it targets the run that STARTED this session (VH_AUTOMATION_RUN_ID); in a continued sticky session always pass the runId named in the latest "[Very Happy automation \u2026 run <id>; \u2026]" prompt header. Use status done with a short summary, or failed with the error; set needsAttention when a human must look.',
|
|
61
|
+
inputSchema: { runId: id.optional(), status: z.enum(["done", "failed"]), summary: z.string().max(4096).optional(), error: z.string().max(4096).optional(), needsAttention: z.boolean().optional(), attentionReason: z.string().max(512).optional() }
|
|
62
|
+
},
|
|
63
|
+
automation_ack: { description: "Clear the attention flag of a run after a human handled it.", inputSchema: { runId: id } }
|
|
64
|
+
};
|
|
65
|
+
async function resolve(context, args) {
|
|
66
|
+
if (args.id) return context.client.get(args.id);
|
|
67
|
+
if (args.name) return context.client.getByName(args.name);
|
|
68
|
+
throw new Error("Give the automation name or id");
|
|
69
|
+
}
|
|
70
|
+
function machineFor(context, requested) {
|
|
71
|
+
if (requested && requested !== "this") return requested;
|
|
72
|
+
return context.machineId;
|
|
73
|
+
}
|
|
74
|
+
function requireMachine(context, requested) {
|
|
75
|
+
const machine = machineFor(context, requested);
|
|
76
|
+
if (!machine) throw new Error("This machine is not registered with Very Happy; pass machineId explicitly");
|
|
77
|
+
return machine;
|
|
78
|
+
}
|
|
79
|
+
async function executeAutomationTool(name, args, context) {
|
|
80
|
+
const { client } = context;
|
|
81
|
+
switch (name) {
|
|
82
|
+
case "automation_list":
|
|
83
|
+
return { automations: await client.list(machineFor(context, args.machineId)) };
|
|
84
|
+
case "automation_get":
|
|
85
|
+
return { automation: await resolve(context, args) };
|
|
86
|
+
case "automation_create": {
|
|
87
|
+
const input = {
|
|
88
|
+
name: args.name,
|
|
89
|
+
machineId: requireMachine(context, args.machineId),
|
|
90
|
+
trigger: args.trigger,
|
|
91
|
+
action: args.action,
|
|
92
|
+
...args.description !== void 0 ? { description: args.description } : {},
|
|
93
|
+
...args.concurrency !== void 0 ? { concurrency: args.concurrency } : {},
|
|
94
|
+
...args.maxRuntimeMs !== void 0 ? { maxRuntimeMs: args.maxRuntimeMs } : {},
|
|
95
|
+
...args.paused ? { status: "paused" } : {}
|
|
96
|
+
};
|
|
97
|
+
return { automation: await client.create(input) };
|
|
98
|
+
}
|
|
99
|
+
case "automation_update": {
|
|
100
|
+
const current = await resolve(context, args);
|
|
101
|
+
const input = {
|
|
102
|
+
version: args.version,
|
|
103
|
+
...args.newName !== void 0 ? { name: args.newName } : {},
|
|
104
|
+
...args.description !== void 0 ? { description: args.description } : {},
|
|
105
|
+
...args.machineId !== void 0 ? { machineId: machineFor(context, args.machineId) } : {},
|
|
106
|
+
...args.trigger !== void 0 ? { trigger: args.trigger } : {},
|
|
107
|
+
...args.action !== void 0 ? { action: args.action } : {},
|
|
108
|
+
...args.concurrency !== void 0 ? { concurrency: args.concurrency } : {},
|
|
109
|
+
...args.maxRuntimeMs !== void 0 ? { maxRuntimeMs: args.maxRuntimeMs } : {}
|
|
110
|
+
};
|
|
111
|
+
return { automation: await client.update(current.id, input) };
|
|
112
|
+
}
|
|
113
|
+
case "automation_pause":
|
|
114
|
+
return { automation: await client.pause((await resolve(context, args)).id) };
|
|
115
|
+
case "automation_resume":
|
|
116
|
+
return { automation: await client.resume((await resolve(context, args)).id) };
|
|
117
|
+
case "automation_delete": {
|
|
118
|
+
const target = await resolve(context, args);
|
|
119
|
+
await client.remove(target.id);
|
|
120
|
+
return { deleted: true, id: target.id, name: target.name };
|
|
121
|
+
}
|
|
122
|
+
case "automation_run":
|
|
123
|
+
return { run: await client.run((await resolve(context, args)).id, args.payload !== void 0 ? { payload: args.payload } : {}) };
|
|
124
|
+
case "automation_fire":
|
|
125
|
+
return client.fire(args.name, { ...args.payload !== void 0 ? { payload: args.payload } : {}, ...args.dedupeKey !== void 0 ? { dedupeKey: args.dedupeKey } : {} });
|
|
126
|
+
case "automation_runs": {
|
|
127
|
+
const automationId = args.id ?? (args.name ? (await client.getByName(args.name)).id : void 0);
|
|
128
|
+
return { runs: await client.runs({ automationId, status: args.status, attention: args.attention === true, limit: args.limit }) };
|
|
129
|
+
}
|
|
130
|
+
case "automation_report": {
|
|
131
|
+
const runId = args.runId ?? automationRunIdFromEnv(context.env ?? process.env);
|
|
132
|
+
if (!runId) throw new Error("No run id: pass runId (this session was not started by an automation)");
|
|
133
|
+
const report = {
|
|
134
|
+
status: args.status,
|
|
135
|
+
...args.summary !== void 0 ? { summary: args.summary } : {},
|
|
136
|
+
...args.error !== void 0 ? { error: args.error } : {},
|
|
137
|
+
...args.needsAttention !== void 0 ? { needsAttention: args.needsAttention } : {},
|
|
138
|
+
...args.attentionReason !== void 0 ? { attentionReason: args.attentionReason } : {}
|
|
139
|
+
};
|
|
140
|
+
return { run: await client.report(runId, report) };
|
|
141
|
+
}
|
|
142
|
+
case "automation_ack":
|
|
143
|
+
return { run: await client.ack(args.runId) };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function createAutomationToolExecutor() {
|
|
147
|
+
let context = null;
|
|
148
|
+
return async (name, args) => {
|
|
149
|
+
context ??= authenticatedAutomationsClient("mcp-auto").then(({ client, machineId }) => ({ client, machineId }));
|
|
150
|
+
let resolved;
|
|
151
|
+
try {
|
|
152
|
+
resolved = await context;
|
|
153
|
+
} catch (error) {
|
|
154
|
+
context = null;
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
return executeAutomationTool(name, args, resolved);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function registerAutomationTools(server, execute = createAutomationToolExecutor()) {
|
|
161
|
+
for (const name of AUTOMATION_TOOL_NAMES) {
|
|
162
|
+
const spec = AUTOMATION_TOOL_SCHEMAS[name];
|
|
163
|
+
server.registerTool(name, {
|
|
164
|
+
description: spec.description,
|
|
165
|
+
inputSchema: spec.inputSchema,
|
|
166
|
+
annotations: { readOnlyHint: spec.readOnly === true, idempotentHint: name !== "automation_run" && name !== "automation_create", openWorldHint: false, destructiveHint: spec.destructive === true }
|
|
167
|
+
}, async (args) => {
|
|
168
|
+
try {
|
|
169
|
+
return { content: [{ type: "text", text: JSON.stringify(await execute(name, args ?? {})) }], isError: false };
|
|
170
|
+
} catch (error) {
|
|
171
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Automation operation failed" }], isError: true };
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export { AUTOMATION_TOOL_NAMES as A, registerAutomationTools as r };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { c as createTeamsClient } from './client-Brn-UwVk.mjs';
|
|
3
|
+
|
|
4
|
+
const TEAM_TOOL_NAMES = ["team_create", "team_join", "team_inspect", "team_delegate", "team_message", "team_submit", "team_accept", "team_return", "team_cancel", "team_handoff", "team_schedule_create", "team_schedule_pause", "team_schedule_resume", "team_schedule_cancel"];
|
|
5
|
+
const id = z.string().min(1).max(128);
|
|
6
|
+
const text = z.string().min(1).max(32e3);
|
|
7
|
+
const requestId = id.describe("Unique operation ID. Reuse the same ID and arguments after an uncertain response.");
|
|
8
|
+
function registerTeamsTools(server, sessionId, client = createTeamsClient(sessionId)) {
|
|
9
|
+
const register = (name, description, inputSchema, execute) => {
|
|
10
|
+
server.registerTool(name, { description, inputSchema, annotations: { readOnlyHint: name === "team_inspect", idempotentHint: true, openWorldHint: false, destructiveHint: ["team_cancel", "team_handoff", "team_return", "team_schedule_cancel"].includes(name) } }, async (args) => {
|
|
11
|
+
try {
|
|
12
|
+
return { content: [{ type: "text", text: JSON.stringify(await execute(args)) }], isError: false };
|
|
13
|
+
} catch (error) {
|
|
14
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Teams operation failed" }], isError: true };
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
register(
|
|
19
|
+
"team_create",
|
|
20
|
+
"Create an official Very Happy team and join this session as its root bot. Does not grant access outside this account.",
|
|
21
|
+
{ name: id, machineId: id.optional(), requestId },
|
|
22
|
+
(args) => client.initialize(args)
|
|
23
|
+
);
|
|
24
|
+
register(
|
|
25
|
+
"team_join",
|
|
26
|
+
"Join an existing team as a root bot using this session owner\u2019s account. Scoped workers cannot elevate their role.",
|
|
27
|
+
{ teamId: id, name: id, botId: id.optional().describe("Existing root bot to reconnect; preserves its identity"), requestId },
|
|
28
|
+
(args) => client.initialize(args)
|
|
29
|
+
);
|
|
30
|
+
register("team_inspect", "Read your visible team tasks, attempts and messages. Inspect before decisions; submission is not acceptance.", {}, () => client.inspect());
|
|
31
|
+
const action = (name, description, fields) => register(
|
|
32
|
+
`team_${name}`,
|
|
33
|
+
description,
|
|
34
|
+
{ requestId, ...fields },
|
|
35
|
+
({ requestId: key, ...args }) => client.action({ type: name, ...args, ...name === "delegate" && args.directory === void 0 ? { directory: process.cwd() } : {} }, key)
|
|
36
|
+
);
|
|
37
|
+
action("delegate", "Delegate a goal with acceptance criteria. Use parentTaskId for subdelegation. Existing assigneeBotId or a managed worker may execute it.", {
|
|
38
|
+
goal: text,
|
|
39
|
+
acceptance: z.array(text).min(1).max(32),
|
|
40
|
+
parentTaskId: id.optional(),
|
|
41
|
+
assigneeBotId: id.optional(),
|
|
42
|
+
botName: id.optional(),
|
|
43
|
+
directory: z.string().min(1).optional(),
|
|
44
|
+
assistant: z.enum(["claude", "codex", "pi-acp"]).optional(),
|
|
45
|
+
model: z.string().trim().min(1).max(256).optional()
|
|
46
|
+
});
|
|
47
|
+
action("message", "Send a persistent task-related message. Delivery does not mean the model has read or acted on it.", { taskId: id, body: text, recipientBotId: id.optional() });
|
|
48
|
+
action("submit", "Submit evidence for your current attempt and goal version. The owner still has to accept it.", { taskId: id, attemptId: id, goalVersion: z.number().int().positive(), result: text });
|
|
49
|
+
const current = { attemptId: id, goalVersion: z.number().int().positive() };
|
|
50
|
+
action("accept", "Accept a task you own after checking its evidence. Resource cleanup is tracked separately.", { taskId: id, ...current });
|
|
51
|
+
action("return", "Return your task for further work with a concrete reason.", { taskId: id, reason: text, ...current });
|
|
52
|
+
action("cancel", "Cancel an owned task and its dependent work. Cleanup may remain pending.", { taskId: id, reason: text, ...current });
|
|
53
|
+
action("handoff", "Move an owned task to another bot; prior execution authority is superseded.", { taskId: id, assigneeBotId: id, ...current });
|
|
54
|
+
register("team_schedule_create", "Create a persistent one-time or fixed-interval reminder for your own root bot. Delivery wakes the bound session; it does not prove task completion. Use epoch milliseconds, and inspect before retrying.", { requestId, name: id, botId: id, body: text, runAt: z.number().int().nonnegative(), intervalMs: z.number().int().min(6e4).optional() }, ({ requestId: key, ...args }) => client.action({ type: "schedule-create", ...args }, key));
|
|
55
|
+
for (const operation of ["pause", "resume", "cancel"]) {
|
|
56
|
+
register(`team_schedule_${operation}`, `${operation} your root bot\u2019s schedule using its current version from team_inspect. An already in-flight message may still arrive.`, { requestId, scheduleId: id, version: z.number().int().positive() }, ({ requestId: key, ...args }) => client.action({ type: `schedule-${operation}`, ...args }, key));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { TEAM_TOOL_NAMES as T, registerTeamsTools as r };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var z = require('zod');
|
|
4
|
+
var index = require('./index-DA7yINuk.cjs');
|
|
5
|
+
var client = require('./client-DOBWJL3u.cjs');
|
|
6
|
+
|
|
7
|
+
const AUTOMATION_TOOL_NAMES = [
|
|
8
|
+
"automation_list",
|
|
9
|
+
"automation_get",
|
|
10
|
+
"automation_create",
|
|
11
|
+
"automation_update",
|
|
12
|
+
"automation_pause",
|
|
13
|
+
"automation_resume",
|
|
14
|
+
"automation_delete",
|
|
15
|
+
"automation_run",
|
|
16
|
+
"automation_fire",
|
|
17
|
+
"automation_runs",
|
|
18
|
+
"automation_report",
|
|
19
|
+
"automation_ack"
|
|
20
|
+
];
|
|
21
|
+
const id = z.z.string().min(1).max(128);
|
|
22
|
+
const ref = { name: index.AutomationNameSchema.optional().describe("Automation name"), id: id.optional().describe("Automation id (alternative to name)") };
|
|
23
|
+
const payload = z.z.string().max(65536).optional().describe("Payload text; JSON lets prompts use {{payload.field}}");
|
|
24
|
+
const maxRuntimeMs = z.z.number().int().min(6e4).max(7 * 864e5).optional();
|
|
25
|
+
const AUTOMATION_TOOL_SCHEMAS = {
|
|
26
|
+
automation_list: { description: "List this account\u2019s automations (name, trigger, action, machine, status, next run). Defaults to every machine.", readOnly: true, inputSchema: { machineId: id.optional().describe("Only this machine id, or 'this' for the current machine") } },
|
|
27
|
+
automation_get: { description: "Read one automation by name or id, including its version (needed for automation_update).", readOnly: true, inputSchema: ref },
|
|
28
|
+
automation_create: {
|
|
29
|
+
description: "Create an automation: a trigger (cron+tz / interval / once / manual) and an action (spawn a session, send into a session, or run a script argv) on one machine. Defaults to the current machine. Prompts and argv may use {{payload}}, {{payload.path}}, {{run.id}}, {{automation.name}}, {{now}}.",
|
|
30
|
+
inputSchema: {
|
|
31
|
+
name: index.AutomationNameSchema,
|
|
32
|
+
description: z.z.string().max(4e3).optional(),
|
|
33
|
+
machineId: id.optional().describe("Target machine id; omit or 'this' for the current machine"),
|
|
34
|
+
trigger: index.AutomationTriggerSchema,
|
|
35
|
+
action: index.AutomationActionSchema,
|
|
36
|
+
concurrency: index.AutomationConcurrencySchema.optional().describe("skip (default): a run while another is active is recorded as skipped; queue: it waits"),
|
|
37
|
+
maxRuntimeMs,
|
|
38
|
+
paused: z.z.boolean().optional().describe("Create paused")
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
automation_update: {
|
|
42
|
+
description: "Change an automation (name / description / machine / trigger / action / concurrency / maxRuntimeMs). Requires the current version from automation_get; a stale version is rejected.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
...ref,
|
|
45
|
+
version: z.z.number().int().positive(),
|
|
46
|
+
newName: index.AutomationNameSchema.optional(),
|
|
47
|
+
description: z.z.string().max(4e3).nullable().optional(),
|
|
48
|
+
machineId: id.optional(),
|
|
49
|
+
trigger: index.AutomationTriggerSchema.optional(),
|
|
50
|
+
action: index.AutomationActionSchema.optional(),
|
|
51
|
+
concurrency: index.AutomationConcurrencySchema.optional(),
|
|
52
|
+
maxRuntimeMs
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
automation_pause: { description: "Pause an automation: no new scheduled runs and fire is refused until resumed.", inputSchema: ref },
|
|
56
|
+
automation_resume: { description: "Resume a paused automation; the next run is computed from now.", inputSchema: ref },
|
|
57
|
+
automation_delete: { description: "Delete an automation and its run history. Irreversible.", destructive: true, inputSchema: ref },
|
|
58
|
+
automation_run: { description: "Queue one run of an automation now (source: manual), optionally with a payload.", inputSchema: { ...ref, payload } },
|
|
59
|
+
automation_fire: { description: "Trigger an automation by name as an external event, with an optional payload and dedupe key (the same key within 24h returns the original run).", inputSchema: { name: index.AutomationNameSchema, payload, dedupeKey: z.z.string().min(1).max(256).optional() } },
|
|
60
|
+
automation_runs: { description: "List runs, newest first: status, session, summary, error, attention. Filter by automation, status or attention.", readOnly: true, inputSchema: { ...ref, status: z.z.string().min(1).max(64).optional(), attention: z.z.boolean().optional().describe("Only runs flagged for a human"), limit: z.z.number().int().min(1).max(200).optional() } },
|
|
61
|
+
automation_report: {
|
|
62
|
+
description: 'Report the result of an automation run. Without runId it targets the run that STARTED this session (VH_AUTOMATION_RUN_ID); in a continued sticky session always pass the runId named in the latest "[Very Happy automation \u2026 run <id>; \u2026]" prompt header. Use status done with a short summary, or failed with the error; set needsAttention when a human must look.',
|
|
63
|
+
inputSchema: { runId: id.optional(), status: z.z.enum(["done", "failed"]), summary: z.z.string().max(4096).optional(), error: z.z.string().max(4096).optional(), needsAttention: z.z.boolean().optional(), attentionReason: z.z.string().max(512).optional() }
|
|
64
|
+
},
|
|
65
|
+
automation_ack: { description: "Clear the attention flag of a run after a human handled it.", inputSchema: { runId: id } }
|
|
66
|
+
};
|
|
67
|
+
async function resolve(context, args) {
|
|
68
|
+
if (args.id) return context.client.get(args.id);
|
|
69
|
+
if (args.name) return context.client.getByName(args.name);
|
|
70
|
+
throw new Error("Give the automation name or id");
|
|
71
|
+
}
|
|
72
|
+
function machineFor(context, requested) {
|
|
73
|
+
if (requested && requested !== "this") return requested;
|
|
74
|
+
return context.machineId;
|
|
75
|
+
}
|
|
76
|
+
function requireMachine(context, requested) {
|
|
77
|
+
const machine = machineFor(context, requested);
|
|
78
|
+
if (!machine) throw new Error("This machine is not registered with Very Happy; pass machineId explicitly");
|
|
79
|
+
return machine;
|
|
80
|
+
}
|
|
81
|
+
async function executeAutomationTool(name, args, context) {
|
|
82
|
+
const { client: client$1 } = context;
|
|
83
|
+
switch (name) {
|
|
84
|
+
case "automation_list":
|
|
85
|
+
return { automations: await client$1.list(machineFor(context, args.machineId)) };
|
|
86
|
+
case "automation_get":
|
|
87
|
+
return { automation: await resolve(context, args) };
|
|
88
|
+
case "automation_create": {
|
|
89
|
+
const input = {
|
|
90
|
+
name: args.name,
|
|
91
|
+
machineId: requireMachine(context, args.machineId),
|
|
92
|
+
trigger: args.trigger,
|
|
93
|
+
action: args.action,
|
|
94
|
+
...args.description !== void 0 ? { description: args.description } : {},
|
|
95
|
+
...args.concurrency !== void 0 ? { concurrency: args.concurrency } : {},
|
|
96
|
+
...args.maxRuntimeMs !== void 0 ? { maxRuntimeMs: args.maxRuntimeMs } : {},
|
|
97
|
+
...args.paused ? { status: "paused" } : {}
|
|
98
|
+
};
|
|
99
|
+
return { automation: await client$1.create(input) };
|
|
100
|
+
}
|
|
101
|
+
case "automation_update": {
|
|
102
|
+
const current = await resolve(context, args);
|
|
103
|
+
const input = {
|
|
104
|
+
version: args.version,
|
|
105
|
+
...args.newName !== void 0 ? { name: args.newName } : {},
|
|
106
|
+
...args.description !== void 0 ? { description: args.description } : {},
|
|
107
|
+
...args.machineId !== void 0 ? { machineId: machineFor(context, args.machineId) } : {},
|
|
108
|
+
...args.trigger !== void 0 ? { trigger: args.trigger } : {},
|
|
109
|
+
...args.action !== void 0 ? { action: args.action } : {},
|
|
110
|
+
...args.concurrency !== void 0 ? { concurrency: args.concurrency } : {},
|
|
111
|
+
...args.maxRuntimeMs !== void 0 ? { maxRuntimeMs: args.maxRuntimeMs } : {}
|
|
112
|
+
};
|
|
113
|
+
return { automation: await client$1.update(current.id, input) };
|
|
114
|
+
}
|
|
115
|
+
case "automation_pause":
|
|
116
|
+
return { automation: await client$1.pause((await resolve(context, args)).id) };
|
|
117
|
+
case "automation_resume":
|
|
118
|
+
return { automation: await client$1.resume((await resolve(context, args)).id) };
|
|
119
|
+
case "automation_delete": {
|
|
120
|
+
const target = await resolve(context, args);
|
|
121
|
+
await client$1.remove(target.id);
|
|
122
|
+
return { deleted: true, id: target.id, name: target.name };
|
|
123
|
+
}
|
|
124
|
+
case "automation_run":
|
|
125
|
+
return { run: await client$1.run((await resolve(context, args)).id, args.payload !== void 0 ? { payload: args.payload } : {}) };
|
|
126
|
+
case "automation_fire":
|
|
127
|
+
return client$1.fire(args.name, { ...args.payload !== void 0 ? { payload: args.payload } : {}, ...args.dedupeKey !== void 0 ? { dedupeKey: args.dedupeKey } : {} });
|
|
128
|
+
case "automation_runs": {
|
|
129
|
+
const automationId = args.id ?? (args.name ? (await client$1.getByName(args.name)).id : void 0);
|
|
130
|
+
return { runs: await client$1.runs({ automationId, status: args.status, attention: args.attention === true, limit: args.limit }) };
|
|
131
|
+
}
|
|
132
|
+
case "automation_report": {
|
|
133
|
+
const runId = args.runId ?? client.automationRunIdFromEnv(context.env ?? process.env);
|
|
134
|
+
if (!runId) throw new Error("No run id: pass runId (this session was not started by an automation)");
|
|
135
|
+
const report = {
|
|
136
|
+
status: args.status,
|
|
137
|
+
...args.summary !== void 0 ? { summary: args.summary } : {},
|
|
138
|
+
...args.error !== void 0 ? { error: args.error } : {},
|
|
139
|
+
...args.needsAttention !== void 0 ? { needsAttention: args.needsAttention } : {},
|
|
140
|
+
...args.attentionReason !== void 0 ? { attentionReason: args.attentionReason } : {}
|
|
141
|
+
};
|
|
142
|
+
return { run: await client$1.report(runId, report) };
|
|
143
|
+
}
|
|
144
|
+
case "automation_ack":
|
|
145
|
+
return { run: await client$1.ack(args.runId) };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function createAutomationToolExecutor() {
|
|
149
|
+
let context = null;
|
|
150
|
+
return async (name, args) => {
|
|
151
|
+
context ??= client.authenticatedAutomationsClient("mcp-auto").then(({ client, machineId }) => ({ client, machineId }));
|
|
152
|
+
let resolved;
|
|
153
|
+
try {
|
|
154
|
+
resolved = await context;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
context = null;
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
return executeAutomationTool(name, args, resolved);
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function registerAutomationTools(server, execute = createAutomationToolExecutor()) {
|
|
163
|
+
for (const name of AUTOMATION_TOOL_NAMES) {
|
|
164
|
+
const spec = AUTOMATION_TOOL_SCHEMAS[name];
|
|
165
|
+
server.registerTool(name, {
|
|
166
|
+
description: spec.description,
|
|
167
|
+
inputSchema: spec.inputSchema,
|
|
168
|
+
annotations: { readOnlyHint: spec.readOnly === true, idempotentHint: name !== "automation_run" && name !== "automation_create", openWorldHint: false, destructiveHint: spec.destructive === true }
|
|
169
|
+
}, async (args) => {
|
|
170
|
+
try {
|
|
171
|
+
return { content: [{ type: "text", text: JSON.stringify(await execute(name, args ?? {})) }], isError: false };
|
|
172
|
+
} catch (error) {
|
|
173
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Automation operation failed" }], isError: true };
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
exports.AUTOMATION_TOOL_NAMES = AUTOMATION_TOOL_NAMES;
|
|
180
|
+
exports.registerAutomationTools = registerAutomationTools;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var z = require('zod');
|
|
4
|
+
var client = require('./client-C_axwRry.cjs');
|
|
5
|
+
|
|
6
|
+
const TEAM_TOOL_NAMES = ["team_create", "team_join", "team_inspect", "team_delegate", "team_message", "team_submit", "team_accept", "team_return", "team_cancel", "team_handoff", "team_schedule_create", "team_schedule_pause", "team_schedule_resume", "team_schedule_cancel"];
|
|
7
|
+
const id = z.z.string().min(1).max(128);
|
|
8
|
+
const text = z.z.string().min(1).max(32e3);
|
|
9
|
+
const requestId = id.describe("Unique operation ID. Reuse the same ID and arguments after an uncertain response.");
|
|
10
|
+
function registerTeamsTools(server, sessionId, client$1 = client.createTeamsClient(sessionId)) {
|
|
11
|
+
const register = (name, description, inputSchema, execute) => {
|
|
12
|
+
server.registerTool(name, { description, inputSchema, annotations: { readOnlyHint: name === "team_inspect", idempotentHint: true, openWorldHint: false, destructiveHint: ["team_cancel", "team_handoff", "team_return", "team_schedule_cancel"].includes(name) } }, async (args) => {
|
|
13
|
+
try {
|
|
14
|
+
return { content: [{ type: "text", text: JSON.stringify(await execute(args)) }], isError: false };
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Teams operation failed" }], isError: true };
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
register(
|
|
21
|
+
"team_create",
|
|
22
|
+
"Create an official Very Happy team and join this session as its root bot. Does not grant access outside this account.",
|
|
23
|
+
{ name: id, machineId: id.optional(), requestId },
|
|
24
|
+
(args) => client$1.initialize(args)
|
|
25
|
+
);
|
|
26
|
+
register(
|
|
27
|
+
"team_join",
|
|
28
|
+
"Join an existing team as a root bot using this session owner\u2019s account. Scoped workers cannot elevate their role.",
|
|
29
|
+
{ teamId: id, name: id, botId: id.optional().describe("Existing root bot to reconnect; preserves its identity"), requestId },
|
|
30
|
+
(args) => client$1.initialize(args)
|
|
31
|
+
);
|
|
32
|
+
register("team_inspect", "Read your visible team tasks, attempts and messages. Inspect before decisions; submission is not acceptance.", {}, () => client$1.inspect());
|
|
33
|
+
const action = (name, description, fields) => register(
|
|
34
|
+
`team_${name}`,
|
|
35
|
+
description,
|
|
36
|
+
{ requestId, ...fields },
|
|
37
|
+
({ requestId: key, ...args }) => client$1.action({ type: name, ...args, ...name === "delegate" && args.directory === void 0 ? { directory: process.cwd() } : {} }, key)
|
|
38
|
+
);
|
|
39
|
+
action("delegate", "Delegate a goal with acceptance criteria. Use parentTaskId for subdelegation. Existing assigneeBotId or a managed worker may execute it.", {
|
|
40
|
+
goal: text,
|
|
41
|
+
acceptance: z.z.array(text).min(1).max(32),
|
|
42
|
+
parentTaskId: id.optional(),
|
|
43
|
+
assigneeBotId: id.optional(),
|
|
44
|
+
botName: id.optional(),
|
|
45
|
+
directory: z.z.string().min(1).optional(),
|
|
46
|
+
assistant: z.z.enum(["claude", "codex", "pi-acp"]).optional(),
|
|
47
|
+
model: z.z.string().trim().min(1).max(256).optional()
|
|
48
|
+
});
|
|
49
|
+
action("message", "Send a persistent task-related message. Delivery does not mean the model has read or acted on it.", { taskId: id, body: text, recipientBotId: id.optional() });
|
|
50
|
+
action("submit", "Submit evidence for your current attempt and goal version. The owner still has to accept it.", { taskId: id, attemptId: id, goalVersion: z.z.number().int().positive(), result: text });
|
|
51
|
+
const current = { attemptId: id, goalVersion: z.z.number().int().positive() };
|
|
52
|
+
action("accept", "Accept a task you own after checking its evidence. Resource cleanup is tracked separately.", { taskId: id, ...current });
|
|
53
|
+
action("return", "Return your task for further work with a concrete reason.", { taskId: id, reason: text, ...current });
|
|
54
|
+
action("cancel", "Cancel an owned task and its dependent work. Cleanup may remain pending.", { taskId: id, reason: text, ...current });
|
|
55
|
+
action("handoff", "Move an owned task to another bot; prior execution authority is superseded.", { taskId: id, assigneeBotId: id, ...current });
|
|
56
|
+
register("team_schedule_create", "Create a persistent one-time or fixed-interval reminder for your own root bot. Delivery wakes the bound session; it does not prove task completion. Use epoch milliseconds, and inspect before retrying.", { requestId, name: id, botId: id, body: text, runAt: z.z.number().int().nonnegative(), intervalMs: z.z.number().int().min(6e4).optional() }, ({ requestId: key, ...args }) => client$1.action({ type: "schedule-create", ...args }, key));
|
|
57
|
+
for (const operation of ["pause", "resume", "cancel"]) {
|
|
58
|
+
register(`team_schedule_${operation}`, `${operation} your root bot\u2019s schedule using its current version from team_inspect. An already in-flight message may still arrive.`, { requestId, scheduleId: id, version: z.z.number().int().positive() }, ({ requestId: key, ...args }) => client$1.action({ type: `schedule-${operation}`, ...args }, key));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exports.TEAM_TOOL_NAMES = TEAM_TOOL_NAMES;
|
|
63
|
+
exports.registerTeamsTools = registerTeamsTools;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function trimIdent(text) {
|
|
4
|
+
const lines = text.split("\n");
|
|
5
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
6
|
+
lines.shift();
|
|
7
|
+
}
|
|
8
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
9
|
+
lines.pop();
|
|
10
|
+
}
|
|
11
|
+
const minSpaces = lines.reduce((min, line) => {
|
|
12
|
+
if (line.trim() === "") {
|
|
13
|
+
return min;
|
|
14
|
+
}
|
|
15
|
+
const leadingSpaces = line.match(/^\s*/)[0].length;
|
|
16
|
+
return Math.min(min, leadingSpaces);
|
|
17
|
+
}, Infinity);
|
|
18
|
+
const trimmedLines = lines.map((line) => line.slice(minSpaces));
|
|
19
|
+
return trimmedLines.join("\n");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.trimIdent = trimIdent;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function trimIdent(text) {
|
|
2
|
+
const lines = text.split("\n");
|
|
3
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
4
|
+
lines.shift();
|
|
5
|
+
}
|
|
6
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
7
|
+
lines.pop();
|
|
8
|
+
}
|
|
9
|
+
const minSpaces = lines.reduce((min, line) => {
|
|
10
|
+
if (line.trim() === "") {
|
|
11
|
+
return min;
|
|
12
|
+
}
|
|
13
|
+
const leadingSpaces = line.match(/^\s*/)[0].length;
|
|
14
|
+
return Math.min(min, leadingSpaces);
|
|
15
|
+
}, Infinity);
|
|
16
|
+
const trimmedLines = lines.map((line) => line.slice(minSpaces));
|
|
17
|
+
return trimmedLines.join("\n");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { trimIdent as t };
|