@funny-booth/agent-core 0.1.50 → 0.1.52
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/LICENSE +39 -0
- package/dist/approval.js +1 -219
- package/dist/extraMcps.js +1 -1
- package/dist/feedback.js +1 -1
- package/dist/fillSecretHelper.js +1 -51
- package/dist/index.js +1 -1
- package/dist/knowledgeForMod.js +1 -31
- package/dist/launcher.js +1 -1
- package/dist/mcpPackages.js +1 -1
- package/dist/mod/hooks/knowledgeText.js +1 -0
- package/dist/mod/hooks/look.js +1 -0
- package/dist/mod/hooks/redact.js +1 -0
- package/dist/mod/hooks/register.js +1 -0
- package/dist/mod/hooks/vaultGate.js +1 -0
- package/dist/mod/hooks/words.js +1 -0
- package/dist/portalClient.d.ts +1 -2
- package/dist/portalClient.js +1 -117
- package/dist/prompt.js +1 -65
- package/dist/secretExec.js +1 -174
- package/dist/secretInput.js +1 -198
- package/dist/secretNames.js +1 -52
- package/dist/secretPrints.js +1 -72
- package/dist/secretSites.js +1 -53
- package/dist/secretTools.js +1 -156
- package/dist/vault.d.ts +1 -15
- package/dist/vault.js +1 -565
- package/dist/waitingHook.js +1 -101
- package/package.json +5 -5
- package/mod/hooks/knowledgeText.js +0 -13
- package/mod/hooks/look.js +0 -81
- package/mod/hooks/redact.js +0 -98
- package/mod/hooks/register.js +0 -340
- package/mod/hooks/vaultGate.js +0 -54
- package/mod/hooks/words.js +0 -125
- package/mod/tsconfig.json +0 -3
- /package/{mod → dist/mod}/.claude-plugin/plugin.json +0 -0
- /package/{mod → dist/mod}/hooks/hooks.json +0 -0
- /package/{mod → dist/mod}/package.json +0 -0
package/dist/waitingHook.js
CHANGED
|
@@ -1,101 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// ============================================================================
|
|
3
|
-
// 返事を待っている会話(VS Code 拡張の状態バーとサイドバーに出す)
|
|
4
|
-
//
|
|
5
|
-
// 起動プログラム(launcher.ts)が Claude Code にフックとして登録し、会話の節目ごとに呼ばれる。
|
|
6
|
-
// 会話ごとに1行の状態ファイル ~/.funny-booth/waiting/<session_id>.json を書き換え、拡張がそれを見張って一覧にする。
|
|
7
|
-
// 置くのは「状態・最後の返事の書き出し(80 字まで)・フォルダ・時刻・ターミナルの印」だけで、会話の中身は保存しない。
|
|
8
|
-
// 会話が終わると消す。拡張が開いたターミナル(FB_TERMINAL_KEY がある)の会話だけを扱う。
|
|
9
|
-
// フックが失敗しても Claude Code を止めない(常に終了コード 0)。
|
|
10
|
-
// ============================================================================
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.HOOK_EVENTS = void 0;
|
|
13
|
-
exports.waitingDir = waitingDir;
|
|
14
|
-
exports.waitingUpdate = waitingUpdate;
|
|
15
|
-
exports.applyWaitingUpdate = applyWaitingUpdate;
|
|
16
|
-
exports.hookSettings = hookSettings;
|
|
17
|
-
const fs_1 = require("fs");
|
|
18
|
-
const os_1 = require("os");
|
|
19
|
-
const path_1 = require("path");
|
|
20
|
-
const SID = /^[A-Za-z0-9-]{1,128}$/;
|
|
21
|
-
const KEY = /^[A-Za-z0-9-]{8,64}$/;
|
|
22
|
-
const HEAD_MAX = 80;
|
|
23
|
-
const ANSI = /\x1b(?:\[[0-?]*[ -/]*[@-~]|[@-Z\\-_])?/g;
|
|
24
|
-
/** 会話のフックの名前(launcher がこの順で登録する)。PreToolUse は AskUserQuestion(質問)のときだけ。 */
|
|
25
|
-
exports.HOOK_EVENTS = ["UserPromptSubmit", "PostToolUse", "Stop", "Notification", "PreToolUse", "SessionEnd"];
|
|
26
|
-
function waitingDir(home = (0, os_1.homedir)()) {
|
|
27
|
-
return (0, path_1.join)(home, ".funny-booth", "waiting");
|
|
28
|
-
}
|
|
29
|
-
function headOf(text) {
|
|
30
|
-
if (typeof text !== "string")
|
|
31
|
-
return undefined;
|
|
32
|
-
const one = text.replace(ANSI, "").replace(/\s+/gu, " ").trim();
|
|
33
|
-
return one ? Array.from(one).slice(0, HEAD_MAX).join("") : undefined;
|
|
34
|
-
}
|
|
35
|
-
/** フックの入力から、状態ファイルへの書き込みを決める。関係の無いもの・印の無いターミナルは null。 */
|
|
36
|
-
function waitingUpdate(input, env, now) {
|
|
37
|
-
const key = env.FB_TERMINAL_KEY;
|
|
38
|
-
const sid = input.session_id;
|
|
39
|
-
const cwd = input.cwd;
|
|
40
|
-
if (typeof key !== "string" || !KEY.test(key) || typeof sid !== "string" || !SID.test(sid) || typeof cwd !== "string")
|
|
41
|
-
return null;
|
|
42
|
-
const event = input.hook_event_name;
|
|
43
|
-
if (event === "SessionEnd")
|
|
44
|
-
return { kind: "clear", sid };
|
|
45
|
-
let state;
|
|
46
|
-
let head;
|
|
47
|
-
if (event === "UserPromptSubmit" || event === "PostToolUse") {
|
|
48
|
-
state = "working";
|
|
49
|
-
}
|
|
50
|
-
else if (event === "Stop") {
|
|
51
|
-
state = "reply";
|
|
52
|
-
head = headOf(input.last_assistant_message);
|
|
53
|
-
}
|
|
54
|
-
else if (event === "PreToolUse" && input.tool_name === "AskUserQuestion") {
|
|
55
|
-
state = "question";
|
|
56
|
-
const qs = input.tool_input?.questions;
|
|
57
|
-
head = headOf(Array.isArray(qs) ? qs[0]?.question : undefined);
|
|
58
|
-
}
|
|
59
|
-
else if (event === "Notification" && input.notification_type === "permission_prompt") {
|
|
60
|
-
state = "permission";
|
|
61
|
-
head = headOf(input.message);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
return { kind: "put", row: { v: 1, sid, key, cwd, ts: now.toISOString(), state, ...(head ? { head } : {}) } };
|
|
67
|
-
}
|
|
68
|
-
function applyWaitingUpdate(update, home = (0, os_1.homedir)()) {
|
|
69
|
-
const file = (0, path_1.join)(waitingDir(home), `${update.kind === "put" ? update.row.sid : update.sid}.json`);
|
|
70
|
-
if (update.kind === "clear") {
|
|
71
|
-
(0, fs_1.rmSync)(file, { force: true });
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
(0, fs_1.mkdirSync)(waitingDir(home), { recursive: true, mode: 0o700 });
|
|
75
|
-
const tmp = `${file}.${process.pid}.tmp`;
|
|
76
|
-
(0, fs_1.writeFileSync)(tmp, `${JSON.stringify(update.row)}\n`, { encoding: "utf-8", mode: 0o600 });
|
|
77
|
-
(0, fs_1.renameSync)(tmp, file);
|
|
78
|
-
}
|
|
79
|
-
/** Claude Code の --settings に渡すフックの設定(このファイルを node で動かす)。 */
|
|
80
|
-
function hookSettings(nodePath, scriptPath) {
|
|
81
|
-
const command = `"${nodePath}" "${scriptPath}"`;
|
|
82
|
-
const hooks = {};
|
|
83
|
-
for (const event of exports.HOOK_EVENTS) {
|
|
84
|
-
hooks[event] = [{ ...(event === "PreToolUse" ? { matcher: "AskUserQuestion" } : {}), hooks: [{ type: "command", command }] }];
|
|
85
|
-
}
|
|
86
|
-
return JSON.stringify({ hooks });
|
|
87
|
-
}
|
|
88
|
-
function main() {
|
|
89
|
-
try {
|
|
90
|
-
const update = waitingUpdate(JSON.parse((0, fs_1.readFileSync)(0, "utf-8")), process.env, new Date());
|
|
91
|
-
if (update)
|
|
92
|
-
applyWaitingUpdate(update);
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
// 一覧に出ないだけで、会話は止めない
|
|
96
|
-
}
|
|
97
|
-
process.exit(0);
|
|
98
|
-
}
|
|
99
|
-
if (require.main === module)
|
|
100
|
-
main();
|
|
101
|
-
//# sourceMappingURL=waitingHook.js.map
|
|
1
|
+
'use strict';const _0xb69974=_0xe649;(function(_0x536e42,_0xf87c44){const _0x4d4c7c=_0xe649,_0x4262e1=_0x536e42();while(!![]){try{const _0x5f4812=parseInt(_0x4d4c7c(0xcc))/0x1*(-parseInt(_0x4d4c7c(0xaa))/0x2)+parseInt(_0x4d4c7c(0xac))/0x3*(-parseInt(_0x4d4c7c(0xae))/0x4)+parseInt(_0x4d4c7c(0x95))/0x5+parseInt(_0x4d4c7c(0xc7))/0x6+-parseInt(_0x4d4c7c(0x99))/0x7*(parseInt(_0x4d4c7c(0x9d))/0x8)+parseInt(_0x4d4c7c(0x9b))/0x9*(-parseInt(_0x4d4c7c(0x9f))/0xa)+-parseInt(_0x4d4c7c(0x84))/0xb*(-parseInt(_0x4d4c7c(0xab))/0xc);if(_0x5f4812===_0xf87c44)break;else _0x4262e1['push'](_0x4262e1['shift']());}catch(_0x1c34d8){_0x4262e1['push'](_0x4262e1['shift']());}}}(_0x44e3,0x25698));Object[_0xb69974(0x80)](exports,_0xb69974(0xb2),{'value':!![]}),exports[_0xb69974(0xc4)]=void 0x0,exports[_0xb69974(0xb5)]=_0x45bc21,exports['waitingUpdate']=_0x268357,exports[_0xb69974(0xaf)]=_0x122473,exports[_0xb69974(0x92)]=_0x5031db;function _0xe649(_0x2171a5,_0xfeed8e){_0x2171a5=_0x2171a5-0x7e;const _0x44e3e2=_0x44e3();let _0xe64929=_0x44e3e2[_0x2171a5];if(_0xe649['VvPMJx']===undefined){var _0x4a532f=function(_0x4c0f19){const _0x5dc8d5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x53dc7f='',_0x5ae4ac='';for(let _0x359505=0x0,_0x38661b,_0x39416b,_0x118671=0x0;_0x39416b=_0x4c0f19['charAt'](_0x118671++);~_0x39416b&&(_0x38661b=_0x359505%0x4?_0x38661b*0x40+_0x39416b:_0x39416b,_0x359505++%0x4)?_0x53dc7f+=String['fromCharCode'](0xff&_0x38661b>>(-0x2*_0x359505&0x6)):0x0){_0x39416b=_0x5dc8d5['indexOf'](_0x39416b);}for(let _0x1acbf7=0x0,_0x3df093=_0x53dc7f['length'];_0x1acbf7<_0x3df093;_0x1acbf7++){_0x5ae4ac+='%'+('00'+_0x53dc7f['charCodeAt'](_0x1acbf7)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5ae4ac);};_0xe649['DzPQAn']=_0x4a532f,_0xe649['FpnzFT']={},_0xe649['VvPMJx']=!![];}const _0x5a10c2=_0x44e3e2[0x0],_0x2353ad=_0x2171a5+_0x5a10c2,_0xa6df3e=_0xe649['FpnzFT'][_0x2353ad];return!_0xa6df3e?(_0xe64929=_0xe649['DzPQAn'](_0xe64929),_0xe649['FpnzFT'][_0x2353ad]=_0xe64929):_0xe64929=_0xa6df3e,_0xe64929;}const _0x10cc37=require('fs'),_0x475943=require('os'),_0x4ce2fc=require('path'),_0x4ad7d3=/^[A-Za-z0-9-]{1,128}$/,_0x24a502=/^[A-Za-z0-9-]{8,64}$/,_0x3c6407=0x50,_0x379159=/\x1b(?:\[[0-?]*[ -/]*[@-~]|[@-Z\\-_])?/g;exports[_0xb69974(0xc4)]=['UserPromptSubmit',_0xb69974(0x8f),_0xb69974(0xa3),'Notification','PreToolUse','SessionEnd'];function _0x45bc21(_0x4d9736=(0x0,_0x475943['homedir'])()){const _0x22a475=_0xb69974,_0xb20ef1={'pVdtn':_0x22a475(0xc8)};return(0x0,_0x4ce2fc['join'])(_0x4d9736,_0xb20ef1['pVdtn'],_0x22a475(0xa6));}function _0x21577b(_0x43e6cb){const _0x1da082=_0xb69974;if(typeof _0x43e6cb!==_0x1da082(0xcf))return undefined;const _0x52e735=_0x43e6cb[_0x1da082(0x9c)](_0x379159,'')['replace'](/\s+/gu,'\x20')[_0x1da082(0xad)]();return _0x52e735?Array[_0x1da082(0xca)](_0x52e735)[_0x1da082(0x9e)](0x0,_0x3c6407)[_0x1da082(0xa2)](''):undefined;}function _0x268357(_0x22661b,_0x551215,_0x2fe86d){const _0x58c218=_0xb69974,_0x56719e={'CeePI':function(_0x1b015a,_0x7a1fe){return _0x1b015a!==_0x7a1fe;},'aZdrW':_0x58c218(0xcf),'pitoD':function(_0x52c271,_0x53d6d1){return _0x52c271===_0x53d6d1;},'GIKrk':_0x58c218(0xa8),'ybwUQ':'UserPromptSubmit','EjqNc':function(_0x459b75,_0xa57651){return _0x459b75===_0xa57651;},'PVOYM':_0x58c218(0xbb),'dWyCH':function(_0x83a4dc,_0x25b1f0){return _0x83a4dc===_0x25b1f0;},'UUSgJ':_0x58c218(0xa3),'FzEBX':_0x58c218(0xa4),'WMqSB':function(_0x23f3e9,_0x16d123){return _0x23f3e9(_0x16d123);},'ZNyqE':_0x58c218(0xa9),'UDBKC':'question','XWYCd':'Notification','QEnQF':_0x58c218(0x88),'PjPDI':_0x58c218(0x8c)},_0x1040e3=_0x551215['FB_TERMINAL_KEY'],_0x5c9953=_0x22661b[_0x58c218(0xc1)],_0x116ee3=_0x22661b[_0x58c218(0x89)];if(typeof _0x1040e3!=='string'||!_0x24a502[_0x58c218(0xbe)](_0x1040e3)||_0x56719e[_0x58c218(0xa0)](typeof _0x5c9953,_0x56719e[_0x58c218(0xb3)])||!_0x4ad7d3[_0x58c218(0xbe)](_0x5c9953)||_0x56719e[_0x58c218(0xa0)](typeof _0x116ee3,'string'))return null;const _0x54e2dd=_0x22661b['hook_event_name'];if(_0x56719e[_0x58c218(0xcb)](_0x54e2dd,_0x56719e[_0x58c218(0x93)]))return{'kind':_0x58c218(0xb1),'sid':_0x5c9953};let _0x114d5b,_0x2f1935;if(_0x56719e[_0x58c218(0xcb)](_0x54e2dd,_0x56719e[_0x58c218(0x81)])||_0x56719e[_0x58c218(0x8d)](_0x54e2dd,_0x58c218(0x8f)))_0x114d5b=_0x56719e['PVOYM'];else{if(_0x56719e[_0x58c218(0xb4)](_0x54e2dd,_0x56719e['UUSgJ']))_0x114d5b=_0x56719e[_0x58c218(0xcd)],_0x2f1935=_0x56719e[_0x58c218(0xba)](_0x21577b,_0x22661b[_0x58c218(0x85)]);else{if(_0x56719e[_0x58c218(0x8d)](_0x54e2dd,_0x58c218(0xc0))&&_0x56719e[_0x58c218(0xb4)](_0x22661b[_0x58c218(0x8e)],_0x56719e['ZNyqE'])){_0x114d5b=_0x56719e[_0x58c218(0xa1)];const _0x5e74cd=_0x22661b[_0x58c218(0x83)]?.[_0x58c218(0x7f)];_0x2f1935=_0x21577b(Array[_0x58c218(0xc5)](_0x5e74cd)?_0x5e74cd[0x0]?.[_0x58c218(0xc9)]:undefined);}else{if(_0x54e2dd===_0x56719e[_0x58c218(0xce)]&&_0x22661b[_0x58c218(0xb6)]===_0x56719e[_0x58c218(0x90)])_0x114d5b=_0x58c218(0x97),_0x2f1935=_0x21577b(_0x22661b['message']);else return null;}}}return{'kind':_0x56719e[_0x58c218(0xb0)],'row':{'v':0x1,'sid':_0x5c9953,'key':_0x1040e3,'cwd':_0x116ee3,'ts':_0x2fe86d[_0x58c218(0xa7)](),'state':_0x114d5b,..._0x2f1935?{'head':_0x2f1935}:{}}};}function _0x122473(_0x256abf,_0x204a66=(0x0,_0x475943[_0xb69974(0x8a)])()){const _0x3e18be=_0xb69974,_0x3c700a={'VbjQd':function(_0x2dc857,_0x3f5e7a){return _0x2dc857(_0x3f5e7a);},'UjwFI':_0x3e18be(0xb1),'wuFKs':_0x3e18be(0x8b)},_0x571c88=(0x0,_0x4ce2fc[_0x3e18be(0xa2)])(_0x3c700a[_0x3e18be(0xb9)](_0x45bc21,_0x204a66),(_0x256abf['kind']===_0x3e18be(0x8c)?_0x256abf['row'][_0x3e18be(0x82)]:_0x256abf['sid'])+_0x3e18be(0x87));if(_0x256abf[_0x3e18be(0x98)]===_0x3c700a[_0x3e18be(0xc2)]){(0x0,_0x10cc37['rmSync'])(_0x571c88,{'force':!![]});return;}(0x0,_0x10cc37[_0x3e18be(0x91)])(_0x45bc21(_0x204a66),{'recursive':!![],'mode':0x1c0});const _0x487eda=_0x571c88+'.'+process[_0x3e18be(0xbd)]+_0x3e18be(0xc6);(0x0,_0x10cc37[_0x3e18be(0xbc)])(_0x487eda,JSON[_0x3e18be(0xa5)](_0x256abf[_0x3e18be(0x86)])+'\x0a',{'encoding':_0x3c700a[_0x3e18be(0x96)],'mode':0x180}),(0x0,_0x10cc37['renameSync'])(_0x487eda,_0x571c88);}function _0x5031db(_0x1eb67d,_0x3dfb48){const _0x43ba09=_0xb69974,_0x19a6c9={'DTIQi':function(_0x3ebfc0,_0x115150){return _0x3ebfc0===_0x115150;},'bXXfJ':_0x43ba09(0xc0),'NlaqA':'AskUserQuestion'},_0x17b740='\x22'+_0x1eb67d+_0x43ba09(0xb8)+_0x3dfb48+'\x22',_0x29cbe7={};for(const _0x1d6ae1 of exports[_0x43ba09(0xc4)]){_0x29cbe7[_0x1d6ae1]=[{..._0x19a6c9[_0x43ba09(0x94)](_0x1d6ae1,_0x19a6c9[_0x43ba09(0x7e)])?{'matcher':_0x19a6c9[_0x43ba09(0xb7)]}:{},'hooks':[{'type':_0x43ba09(0xc3),'command':_0x17b740}]}];}return JSON[_0x43ba09(0xa5)]({'hooks':_0x29cbe7});}function _0x51e4a4(){const _0x3acd56=_0xb69974;try{const _0x230497=_0x268357(JSON['parse']((0x0,_0x10cc37['readFileSync'])(0x0,_0x3acd56(0x8b))),process.env,new Date());if(_0x230497)_0x122473(_0x230497);}catch{}process[_0x3acd56(0xbf)](0x0);}function _0x44e3(){const _0x59b922=['iIaI','vMjQuwq','v01Xu0i','D29YA2LUzW','D3jPDgvgAwXLu3LUyW','CgLK','DgvZDa','zxHPDa','uhjLvg9VBfvZzq','C2vZC2LVBL9Pza','vwP3rKK','y29TBwfUza','se9ps19fvKvovfm','AxnbCNjHEq','lNrTCa','ode0mZHdEfndBMu','lMz1BM55lwjVB3rO','CxvLC3rPB24','zNjVBq','CgL0B0q','mJi5ofzirfPsAa','rNPfqLG','wfDzq2q','C3rYAw5N','yLHyzKO','CxvLC3rPB25Z','zgvMAw5LuhjVCgvYDhK','Ewj3vve','C2LK','Dg9VBf9PBNb1Da','mtG3Eu94tLPX','BgfZDf9HC3nPC3rHBNrFBwvZC2fNzq','CM93','lMPZB24','CgvYBwLZC2LVBL9WCM9TChq','y3DK','Ag9TzwrPCG','DxrMltG','Chv0','rwPXtMm','Dg9VBf9Uyw1L','ug9ZDfrVB2XvC2u','uuvUuuy','BwTKAxjtEw5J','Ag9VA1nLDhrPBMDZ','r0LlCMS','rfrjuwK','mZC3nJKWzMzMvePz','D3vgs3m','CgvYBwLZC2LVBG','A2LUza','mZa1ntu3DLLIzu10','BwfPBG','mZC3nJeZCMPSrwTP','CMvWBgfJzq','mJryteHgBKy','C2XPy2u','mJbMqvvoteS','q2vLueK','vurcs0m','AM9PBG','u3rVCa','CMvWBhK','C3rYAw5NAwz5','D2fPDgLUzW','Dg9ju09tDhjPBMC','u2vZC2LVBKvUza','qxnRvxnLCLf1zxn0Aw9U','mZH5BePRzMq','ndqZmtq4zxrQzffA','ote1nda1sNzIt01c','DhjPBq','neHdtxjRsG','yxbWBhLxywL0Aw5NvxbKyxrL','ugPqreK','y2XLyxi','x19LC01VzhvSzq','yvPKCLC','zfD5q0G','D2fPDgLUz0rPCG','BM90AwzPy2f0Aw9Ux3r5Cgu','tMXHCue'];_0x44e3=function(){return _0x59b922;};return _0x44e3();}if(require[_0xb69974(0x9a)]===module)_0x51e4a4();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funny-booth/agent-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"description": "AIエージェント起動CLI(共有ランチャー + MCPサーバー)",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -12,12 +12,11 @@
|
|
|
12
12
|
"agent-core": "dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
|
-
"dist"
|
|
16
|
-
"mod"
|
|
15
|
+
"dist"
|
|
17
16
|
],
|
|
18
17
|
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
20
|
-
"build:publish": "
|
|
18
|
+
"build": "tsc && node scripts/copyMod.mjs",
|
|
19
|
+
"build:publish": "npm run build && node scripts/obfuscate.mjs",
|
|
21
20
|
"prepublishOnly": "npm run build:publish",
|
|
22
21
|
"dev": "tsc --watch",
|
|
23
22
|
"start": "node dist/index.js",
|
|
@@ -31,6 +30,7 @@
|
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"@types/node": "^22.0.0",
|
|
33
|
+
"esbuild": "^0.25.12",
|
|
34
34
|
"javascript-obfuscator": "^5.4.7",
|
|
35
35
|
"typescript": "^5.0.0"
|
|
36
36
|
},
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// システムの指示に入れる手順書の節の文(register.js から使う・テストしやすいよう純粋関数に分けた)。
|
|
2
|
-
// お客さんの画面には出ないが、製品の名前は入れない(どのツールのお客さんにも同じ文が届くため)。
|
|
3
|
-
|
|
4
|
-
/** カードの節。起動したエージェントのカードには「最初のメッセージからこれに従う」を添える */
|
|
5
|
-
export function knowledgeSection(keyword, text, isStart) {
|
|
6
|
-
const lead = isStart ? 'このセッションのエージェントの手順書です。最初のメッセージを受け取ったら、この手順書に従って始めてください。\n\n' : ''
|
|
7
|
-
return `# 手順書 ${keyword}\n\n${lead}${text}`
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/** カードを受け取れなかったとき。load_knowledge で読んでから始めるよう頼む */
|
|
11
|
-
export function loadRequest(keyword) {
|
|
12
|
-
return `# 手順書 ${keyword}\n\nこのセッションのエージェントの手順書は、load_knowledge ツールで "${keyword}" を読み込んでから、それに従って始めてください。`
|
|
13
|
-
}
|
package/mod/hooks/look.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// FUNNY BOOTH の見た目の計算(画面に描くのは register.js。Mod の決まりで、$ と on は入口のファイルの中でしか使えない)
|
|
2
|
-
// 入力欄の上の帯の中身・道具の行の日本語・あいさつ・雷くんの表情を決める。言葉は words.js
|
|
3
|
-
import { TOOL_LABELS, TOOL_VERBS, TOOL_FALLBACK, GREETINGS, FACES } from './words.js'
|
|
4
|
-
|
|
5
|
-
export const BOLT = '#F5C542'
|
|
6
|
-
export const FLASH = ['#FFFFFF', '#5A4A14', '#FFFFFF', '#5A4A14', '#FFFFFF', '#F5C542']
|
|
7
|
-
export const DONE_MS = 5000
|
|
8
|
-
export const TIP_AFTER_MS = 10000
|
|
9
|
-
export const TOAST_AFTER_MS = 30000
|
|
10
|
-
const BATTERY = 5
|
|
11
|
-
const TIRED_BELOW = 20
|
|
12
|
-
|
|
13
|
-
// 画面での幅(全角は2)
|
|
14
|
-
export function cells(s) {
|
|
15
|
-
let n = 0
|
|
16
|
-
for (const ch of s) n += /[ᄀ-ᅟ⺀-가-힣豈-︰-﹏-⦆¢-₩]/.test(ch) ? 2 : 1
|
|
17
|
-
return n
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function greetingAt(hour) {
|
|
21
|
-
let text = GREETINGS[0][1]
|
|
22
|
-
for (const [from, words] of GREETINGS) if (hour >= from) text = words
|
|
23
|
-
return text
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// 道具の名前(mcp__<サーバー>__<名前> を含む)→ 日本語の見出し
|
|
27
|
-
export function toolLabel(tool) {
|
|
28
|
-
const name = String(tool).split('__').pop()
|
|
29
|
-
if (TOOL_LABELS[tool]) return TOOL_LABELS[tool]
|
|
30
|
-
if (TOOL_LABELS[name]) return TOOL_LABELS[name]
|
|
31
|
-
if (String(tool).startsWith('mcp__')) for (const [re, verb] of TOOL_VERBS) if (re.test(name)) return verb
|
|
32
|
-
return TOOL_FALLBACK
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// 見出しの横に添える短い説明(コマンドの説明・ファイル名・調べる言葉など)
|
|
36
|
-
export function toolDetail(input) {
|
|
37
|
-
const i = input && typeof input === 'object' ? input : {}
|
|
38
|
-
const base = (p) => String(p).split(/[\\/]/).pop()
|
|
39
|
-
const pick =
|
|
40
|
-
i.description ?? i.command ??
|
|
41
|
-
(i.file_path ? base(i.file_path) : undefined) ?? (i.notebook_path ? base(i.notebook_path) : undefined) ??
|
|
42
|
-
i.pattern ?? i.query ?? i.url ?? (i.keyword ? String(i.keyword).replace(/^@/, '') : undefined) ?? i.name
|
|
43
|
-
if (pick == null) return ''
|
|
44
|
-
const one = String(pick).replace(/\s+/g, ' ').trim()
|
|
45
|
-
return [...one].length > 60 ? [...one].slice(0, 59).join('') + '…' : one
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// まとめて表示された道具(「Read 3 files」など)→「ファイルを読む 3件・ファイルを探す 1件」
|
|
49
|
-
export function groupSummary(calls) {
|
|
50
|
-
const counts = new Map()
|
|
51
|
-
for (const c of calls) { const l = toolLabel(c.tool); counts.set(l, (counts.get(l) ?? 0) + 1) }
|
|
52
|
-
return [...counts].map(([l, n]) => `${l} ${n}件`).join('・')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function duration(ms) {
|
|
56
|
-
const s = Math.round(ms / 1000)
|
|
57
|
-
return s < 60 ? `${s}秒` : `${Math.floor(s / 60)}分${s % 60}秒`
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 雷くんの表情。済んだ顔は DONE_MS だけ見せて、うとうとに戻す。待っている間に余裕が少ないと疲れた顔
|
|
61
|
-
export function faceOf(face, doneUntil, left, now) {
|
|
62
|
-
const f = face === 'done' && now >= doneUntil ? 'idle' : face
|
|
63
|
-
if (f === 'idle' && left != null && left < TIRED_BELOW) return FACES.tired
|
|
64
|
-
return FACES[f]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 帯に何を出すか。幅が足りなければ 雷くん → 電池 → フォルダ の順に省く(名札は最後まで残す)
|
|
68
|
-
export function bandParts({ label, agent, folder, left, face }, columns) {
|
|
69
|
-
const name = agent ? `${label} / ${agent}` : label
|
|
70
|
-
const folderText = folder ? ` [${folder}]` : ''
|
|
71
|
-
const filled = left == null ? 0 : Math.round(left / (100 / BATTERY))
|
|
72
|
-
const battery = left == null ? null : { filled, empty: BATTERY - filled, text: ` 残り ${left}%`, low: left <= 30 }
|
|
73
|
-
const batteryCells = battery ? BATTERY + cells(battery.text) + 4 : 0
|
|
74
|
-
let room = columns - 8 - cells(`ϟ ${name}`)
|
|
75
|
-
const showFolder = !!folderText && room >= cells(folderText)
|
|
76
|
-
if (showFolder) room -= cells(folderText)
|
|
77
|
-
const showBattery = !!battery && room >= batteryCells
|
|
78
|
-
if (showBattery) room -= batteryCells
|
|
79
|
-
const showFace = showBattery && room >= cells(face) + 2
|
|
80
|
-
return { folder: showFolder ? folderText : '', battery: showBattery ? battery : null, face: showFace ? face : '' }
|
|
81
|
-
}
|
package/mod/hooks/redact.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// 道具の結果から金庫の秘密の値を伏せる計算(register.js から使う。Mod の外の Node.js でもテストできるよう、Mod の $ は使わない)。
|
|
2
|
-
//
|
|
3
|
-
// Mod は値そのものを持たない。agent-core の secretPrints.js から受け取った「指紋」(名前・長さ・pre・fp)だけで探す:
|
|
4
|
-
// 1. 秘密の長さごとに、文を1文字ずつずらしながら pre(多項式の値を PRE_MOD で割った余り)を計算する(転がし計算で速い)
|
|
5
|
-
// 2. pre が合った所だけ、key とその部分をつないだ SHA-256 を計算し、fp と同じなら秘密(偶然 pre が合っただけなら伏せない)
|
|
6
|
-
// 3. 重なったら長い秘密を優先する(短い値が長い値の一部でも取りこぼさない)
|
|
7
|
-
// PRE_MOD・preBase は agent-core の secretPrints.ts と同じ計算(test/redact.test.mjs で一致を確かめる)。
|
|
8
|
-
|
|
9
|
-
export const PRE_MOD = 65521
|
|
10
|
-
|
|
11
|
-
export function preBase(key) {
|
|
12
|
-
return 256 + (parseInt(key.slice(0, 8), 16) % (PRE_MOD - 256))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** このセッションだけの key(64 桁の 16 進数)。 */
|
|
16
|
-
export function newKey(random) {
|
|
17
|
-
return [...random(new Uint8Array(32))].map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** 指紋から探すための表(長さ → pre → 指紋の一覧)を作る。 */
|
|
21
|
-
export function buildTable(prints) {
|
|
22
|
-
const table = new Map()
|
|
23
|
-
for (const p of prints) {
|
|
24
|
-
if (!table.has(p.len)) table.set(p.len, new Map())
|
|
25
|
-
const byPre = table.get(p.len)
|
|
26
|
-
if (!byPre.has(p.pre)) byPre.set(p.pre, [])
|
|
27
|
-
byPre.get(p.pre).push(p)
|
|
28
|
-
}
|
|
29
|
-
return table
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function sha256Hex(digest, text) {
|
|
33
|
-
const buf = await digest(new TextEncoder().encode(text))
|
|
34
|
-
return [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** 文の中の秘密の場所(重ならない。長い秘密が先)。digest は SHA-256 を返す関数(Mod では crypto.subtle.digest)。 */
|
|
38
|
-
export async function findSecrets(text, table, key, digest) {
|
|
39
|
-
const base = preBase(key)
|
|
40
|
-
const found = []
|
|
41
|
-
for (const [len, byPre] of table) {
|
|
42
|
-
if (text.length < len) continue
|
|
43
|
-
let pow = 1 // base^(len-1)
|
|
44
|
-
for (let i = 1; i < len; i++) pow = (pow * base) % PRE_MOD
|
|
45
|
-
let h = 0
|
|
46
|
-
for (let i = 0; i < len; i++) h = (h * base + text.charCodeAt(i)) % PRE_MOD
|
|
47
|
-
for (let i = 0; ; i++) {
|
|
48
|
-
const candidates = byPre.get(h)
|
|
49
|
-
if (candidates) {
|
|
50
|
-
const fp = await sha256Hex(digest, key + text.slice(i, i + len))
|
|
51
|
-
const hit = candidates.find((c) => c.fp === fp)
|
|
52
|
-
if (hit) found.push({ start: i, end: i + len, name: hit.name })
|
|
53
|
-
}
|
|
54
|
-
if (i + len >= text.length) break
|
|
55
|
-
h = (((h - ((text.charCodeAt(i) * pow) % PRE_MOD) + PRE_MOD) * base) + text.charCodeAt(i + len)) % PRE_MOD
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
found.sort((a, b) => (b.end - b.start) - (a.end - a.start) || a.start - b.start)
|
|
59
|
-
const taken = []
|
|
60
|
-
for (const f of found) if (!taken.some((t) => f.start < t.end && t.start < f.end)) taken.push(f)
|
|
61
|
-
return taken.sort((a, b) => a.start - b.start)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** 秘密を ●●●●(名前) に置き換えた文。 */
|
|
65
|
-
export async function redactText(text, table, key, digest) {
|
|
66
|
-
if (table.size === 0 || typeof text !== 'string' || text === '') return text
|
|
67
|
-
const hits = await findSecrets(text, table, key, digest)
|
|
68
|
-
if (!hits.length) return text
|
|
69
|
-
let out = ''
|
|
70
|
-
let at = 0
|
|
71
|
-
for (const h of hits) { out += text.slice(at, h.start) + `●●●●(${h.name})`; at = h.end }
|
|
72
|
-
return out + text.slice(at)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** 入れ子の値の中の文をすべて伏せる。changed は1か所でも伏せたか。 */
|
|
76
|
-
export async function redactDeep(value, table, key, digest) {
|
|
77
|
-
let changed = false
|
|
78
|
-
const walk = async (v) => {
|
|
79
|
-
if (typeof v === 'string') {
|
|
80
|
-
const r = await redactText(v, table, key, digest)
|
|
81
|
-
if (r !== v) changed = true
|
|
82
|
-
return r
|
|
83
|
-
}
|
|
84
|
-
if (Array.isArray(v)) {
|
|
85
|
-
const out = []
|
|
86
|
-
for (const x of v) out.push(await walk(x))
|
|
87
|
-
return out
|
|
88
|
-
}
|
|
89
|
-
if (v && typeof v === 'object') {
|
|
90
|
-
const out = {}
|
|
91
|
-
for (const [k, x] of Object.entries(v)) out[k] = await walk(x)
|
|
92
|
-
return out
|
|
93
|
-
}
|
|
94
|
-
return v
|
|
95
|
-
}
|
|
96
|
-
const result = await walk(value)
|
|
97
|
-
return { value: result, changed }
|
|
98
|
-
}
|