@funny-booth/agent-core 0.1.51 → 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.
@@ -1,340 +0,0 @@
1
- // FUNNY BOOTH の Mod(Claude Code の Mods。agent-core に同梱し、起動プログラム launcher.ts が --plugin-dir で読み込ませる)
2
- //
3
- // 1. エージェントの手順書(カード)を会話の記録に残さない
4
- // 会話が始まるとき(session.start)に、agent-core の knowledgeForMod.js でカードの本文を受け取り、
5
- // システムの指示(prompt.compose の節)に入れる。起動プログラムが --system-prompt-snapshot off で起動するので、
6
- // システムの指示は記録に保存されない。本文はこのセッションの間、ここ(メモリ)にだけ持つ。
7
- // 同じカードを load_knowledge で読もうとしたら、本文は返さず「システムの指示に入っている」とだけ返す(記録に残さない)。
8
- // 途中で読む補助の手順書・サブエージェントの読み込みは、今まで通り道具の結果で渡る(記録に残る)。
9
- // (prompt.compose は会話の途中で組み直せないため、途中で読んだものはシステムの指示に入れられない)
10
- // 2. 秘密の値を伏せる
11
- // 金庫の秘密の値(6 文字以上)が道具の結果に出ていれば、記録にも AI にも渡る前に伏せる。
12
- // 道具の結果は2か所に残るので両方で伏せる: 道具の詳しい記録(記録の toolUseResult)は tool.call で、
13
- // AI が読む文(tool_result)とその他の行は session.append で。
14
- // 値そのものは受け取らない。agent-core の secretPrints.js から、このセッションだけの key で作った指紋を受け取り、
15
- // 指紋で探す(redact.js)。金庫のファイルが書き換わったら(途中で秘密を足した等)指紋を取り直す。
16
- // 3. 金庫・鍵に触る道具の呼び出しを止める(vaultGate.js。関所であって壁ではない。サブエージェントにも効かせる)
17
- // 4. 見た目(入力欄の上の帯・道具の行と作業中の行の日本語化・起動のあいさつと雷の光・豆知識・終わったときのお知らせ)
18
- // どれも表示だけで、描くのに失敗したら Claude Code の元の表示に戻す(会話は止めない)。
19
- // 何を出すかの計算は look.js、言葉は words.js。
20
-
21
- import { BOLT, FLASH, DONE_MS, TIP_AFTER_MS, TOAST_AFTER_MS, greetingAt, toolLabel, toolDetail, groupSummary, duration, faceOf, bandParts } from './look.js'
22
- import { knowledgeSection, loadRequest } from './knowledgeText.js'
23
- import { SPINNER_WORD, GROUP_HINT, TOAST_DONE, TOAST_ASK, TIPS } from './words.js'
24
- import { buildTable, newKey, redactDeep, redactText } from './redact.js'
25
- import { GATE_REASON, vaultTouch } from './vaultGate.js'
26
-
27
- const LOAD = /^mcp__[a-z0-9-]+__load_knowledge$/
28
- const knowledge = new Map() // キーワード → 本文(読み込んだ順)
29
- // 実際にシステムの指示(prompt.compose の節)に本文を入れたキーワード。ここにあるものだけ、load_knowledge で本文を返さない。
30
- // 本文を受け取れても節に入らなかったとき(節を組む前に受け取った等)は本文を返す
31
- const injected = new Set()
32
- // 節に入れたのに AI が見当たらないと言うことがある(受付箱 cc03280f)。同じカードを2回目に読まれたら本文を返す
33
- const stubbed = new Set()
34
- // 伏せるための指紋(値は持たない)。key はこのセッションだけの乱数。file・mtime で金庫の書き換わりを見る
35
- const prints = { key: newKey((a) => crypto.getRandomValues(a)), table: new Map(), file: '', mtime: -1, loading: null, failedAt: 0 }
36
- const digest = (bytes) => crypto.subtle.digest('SHA-256', bytes)
37
- let startKeyword = '' // 起動プログラムが渡したカードのキーワード(公式のエージェントのときだけ)
38
-
39
- function stub(keyword) {
40
- return `手順書 ${keyword} は、システムの指示の「手順書 ${keyword}」の節に入っています。それに従って作業してください。` +
41
- `(その節が見当たらないときは、もう一度 load_knowledge で "${keyword}" を読むと本文を返します)`
42
- }
43
-
44
- const redact = (text) => redactText(text, prints.table, prints.key, digest)
45
-
46
- async function redactBlocks(content) {
47
- const out = []
48
- for (const b of content) {
49
- if (b.type === 'text' && typeof b.text === 'string') out.push({ ...b, text: await redact(b.text) })
50
- else if (b.type === 'tool_result' && typeof b.content === 'string') out.push({ ...b, content: await redact(b.content) })
51
- else if (b.type === 'tool_result' && Array.isArray(b.content)) {
52
- const inner = []
53
- for (const c of b.content) inner.push(c.type === 'text' ? { ...c, text: await redact(c.text) } : c)
54
- out.push({ ...b, content: inner })
55
- } else out.push(b)
56
- }
57
- return out
58
- }
59
-
60
- // agent-core の小さな入口を動かし、標準出力の JSON を返す。失敗したら理由(標準エラー)を添えて例外にする
61
- async function runJson($, script, stdin) {
62
- const r = await $.process.run(['node', `${$.plugin.root}/../dist/${script}`], stdin === undefined ? undefined : { stdin })
63
- if (r.exitCode !== 0) throw new Error((r.stderr || `終了コード ${r.exitCode}`).trim())
64
- return JSON.parse(r.stdout)
65
- }
66
-
67
- async function vaultMtime($) {
68
- if (!prints.file) return -1
69
- try { return (await $.fs.stat(prints.file)).mtimeMs } catch { return 0 } // まだ金庫が無い
70
- }
71
-
72
- // 指紋を取る(起動時と、金庫のファイルが書き換わったとき)。読めなければ理由を画面に残し、1分は取り直さない(会話は止めない)
73
- async function loadPrints($) {
74
- if (prints.loading) return prints.loading
75
- prints.loading = (async () => {
76
- try {
77
- const r = await runJson($, 'secretPrints.js', JSON.stringify({ key: prints.key }))
78
- prints.file = r.file
79
- prints.table = buildTable(r.prints)
80
- prints.mtime = await vaultMtime($)
81
- } catch (err) {
82
- prints.failedAt = Date.now()
83
- $.ui.log(`秘密を伏せる準備ができませんでした: ${err.message}`)
84
- } finally { prints.loading = null }
85
- })()
86
- return prints.loading
87
- }
88
-
89
- async function freshPrints($) {
90
- if (!prints.file) {
91
- if (Date.now() - prints.failedAt > 60_000) await loadPrints($)
92
- return
93
- }
94
- if ((await vaultMtime($)) !== prints.mtime) await loadPrints($)
95
- }
96
-
97
- // 見た目の状態(このセッションの間だけ)
98
- const look = { label: '', agent: '', folder: '', greeting: '', submits: 0, flash: -1, face: 'idle', doneUntil: 0, left: null, turnStart: 0, tip: '' }
99
-
100
- async function refreshLeft($) {
101
- try {
102
- const u = await $.session.usage()
103
- if (u?.context?.percent != null) look.left = Math.max(0, 100 - Math.round(u.context.percent))
104
- } catch { /* 余裕が分からないときは電池を出さない */ }
105
- }
106
-
107
- function setFace($, face) {
108
- look.face = face
109
- $.ui.invalidate('ui.render')
110
- }
111
-
112
- async function startLook($) {
113
- try {
114
- const tool = (await $.env.get('FB_TOOL_NAME')) ?? ''
115
- look.label = tool
116
- look.agent = (await $.env.get('FB_AGENT_NAME')) ?? ''
117
- look.folder = (await $.session.cwd()).split(/[\\/]/).pop() ?? ''
118
- look.greeting = greetingAt(new Date().getHours())
119
- // 起動のとき雷を光らせる(1秒ほど)
120
- look.flash = 0
121
- const timer = $.clock.every(200, () => {
122
- look.flash += 1
123
- if (look.flash >= FLASH.length) { look.flash = -1; timer.cancel() }
124
- $.ui.invalidate('ui.render')
125
- })
126
- // ツールの表示名(開発エージェント など)。取れなければ内部の名前のまま
127
- const portal = await $.env.get('FB_PORTAL_URL')
128
- if (portal && tool) {
129
- void $.http.fetch(`${portal}/api/tools/public?toolName=${encodeURIComponent(tool)}`)
130
- .then((res) => {
131
- const name = res.ok ? JSON.parse(res.text)?.display_name : undefined
132
- if (name) { look.label = name; $.ui.invalidate('ui.render') }
133
- })
134
- .catch(() => { /* 内部の名前のまま */ })
135
- }
136
- } catch (err) {
137
- $.ui.log(`帯の準備ができませんでした: ${err.message}`)
138
- }
139
- }
140
-
141
- export function register(on) {
142
- on('session.start', async ($, e, next) => {
143
- // 帯の名札と雷の光は、手順書を受け取るのを待たずに始める
144
- await startLook($)
145
- // 起動プログラムがカードの名前を渡したとき(公式のエージェント)だけ取る。自作エージェントには無い
146
- const keyword = await $.env.get('FB_KNOWLEDGE_KEYWORD')
147
- if (keyword) {
148
- startKeyword = keyword
149
- try {
150
- const card = await runJson($, 'knowledgeForMod.js')
151
- if (card?.keyword && card?.content) knowledge.set(card.keyword, card.content)
152
- } catch (err) {
153
- // 受け取れなければ、エージェントは load_knowledge で読む(システムの指示でそう頼む・prompt.compose)。理由は画面に残す
154
- $.ui.log(`手順書をシステムの指示に入れられませんでした(load_knowledge で読みます): ${err.message}`)
155
- }
156
- }
157
- await loadPrints($)
158
- return next(e)
159
- })
160
-
161
- on('tool.call', { tool: LOAD }, async ($, e, next) => {
162
- // システムの指示に入れたカードは、1回目は本文を返さない(記録に残さない)。2回目は本文を返す(stubbed の説明)
163
- const keyword = String(e.keyword ?? '')
164
- if (!e.agentId && injected.has(keyword) && !stubbed.has(keyword)) {
165
- stubbed.add(keyword)
166
- return { result: stub(keyword) }
167
- }
168
- return next(e)
169
- })
170
-
171
- // 金庫・鍵に触る呼び出しは、道具を動かす前に断る(AI には短い理由だけ。何に触ったかは画面に残す。サブエージェントも同じ)。
172
- // 秘密が出た道具の結果は、詳しい記録ごと伏せた形で返す(伏せたものを Claude Code が記録し、AI に渡す)
173
- on('tool.call', async ($, e, next) => {
174
- const what = vaultTouch(e)
175
- if (what) {
176
- $.ui.log(`金庫・鍵に触る呼び出しを止めました(${e.tool}・${what})`)
177
- return { deny: GATE_REASON }
178
- }
179
- // 雷くん: 質問のときは首をかしげ(お知らせも出す)、失敗したら頭をかく
180
- const mine = !e.agentId
181
- if (mine && e.tool === 'AskUserQuestion') { setFace($, 'ask'); $.ui.toast(TOAST_ASK) }
182
- const r = await next(e)
183
- if (mine) setFace($, r?.isError ? 'fail' : 'work')
184
- if (r.deny) return r
185
- await freshPrints($)
186
- if (prints.table.size === 0) return r
187
- const red = await redactDeep(r.result, prints.table, prints.key, digest)
188
- if (!red.changed) return r
189
- return { result: red.value, ...(r.context ? { context: r.context } : {}) }
190
- })
191
-
192
- // 起動のあいさつ(お客さんの画面に出る)には AI への指示を書かないので、「この手順書で始める」はここで伝える
193
- on('prompt.compose', async ($, e, next) => {
194
- const out = await next(e)
195
- if (!startKeyword) return out
196
- let i = 0
197
- const sections = knowledge.size > 0
198
- ? [...knowledge].map(([keyword, text]) => {
199
- injected.add(keyword)
200
- return { id: `funny-booth-knowledge-${++i}`, text: knowledgeSection(keyword, text, keyword === startKeyword), scope: 'session' }
201
- })
202
- : [{ id: 'funny-booth-knowledge-1', text: loadRequest(startKeyword), scope: 'session' }]
203
- return { ...out, sections: [...out.sections, ...sections] }
204
- })
205
-
206
- on('session.append', { door: 'tool-result' }, async ($, e, next) => {
207
- await freshPrints($)
208
- if (prints.table.size === 0) return next(e)
209
- return next({ ...e, message: { ...e.message, content: await redactBlocks(e.message.content) } })
210
- })
211
-
212
- // あいさつは、お客さんが最初に打つまで出しておく(1回目は起動プログラムが送る最初の一言)
213
- on('prompt.submit', async ($, e, next) => {
214
- look.submits += 1
215
- if (look.submits >= 2) look.greeting = ''
216
- return next(e)
217
- })
218
-
219
- on('turn.start', async ($, e, next) => {
220
- if (!e.agentId) {
221
- look.turnStart = Date.now()
222
- look.tip = TIPS[Math.floor(Math.random() * TIPS.length)]
223
- setFace($, 'work')
224
- }
225
- return next(e)
226
- })
227
-
228
- // 作業が済んだら雷くんがばんざい(DONE_MS で戻す)。時間のかかった作業はお知らせも出す
229
- on('turn.complete', async ($, e, next) => {
230
- const r = await next(e)
231
- if (e.agentId) return r
232
- await refreshLeft($)
233
- if (e.isAborted) { setFace($, 'idle'); return r }
234
- look.doneUntil = Date.now() + DONE_MS
235
- setFace($, 'done')
236
- $.clock.after(DONE_MS + 50, () => $.ui.invalidate('ui.render'))
237
- if (e.durationMs >= TOAST_AFTER_MS) $.ui.toast(TOAST_DONE(duration(e.durationMs)))
238
- return r
239
- })
240
-
241
- // 入力欄の上の帯: 左に名札と作業フォルダ、右に会話の余裕と雷くん。起動直後は上にあいさつ
242
- on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
243
- try {
244
- const { Box, Text } = $.ui.resolve(e)
245
- if (look.left == null) await refreshLeft($)
246
- const face = faceOf(look.face, look.doneUntil, look.left, Date.now())
247
- const parts = bandParts({ ...look, face }, e.viewport?.columns ?? 80)
248
- const left = Text({
249
- wrap: 'truncate-end',
250
- children: [
251
- Text({ color: look.flash >= 0 ? FLASH[look.flash] : BOLT, bold: true, children: ['ϟ '] }),
252
- Text({ bold: true, children: [look.label] }),
253
- ...(look.agent ? [Text({ dimColor: true, children: [' / '] }), Text({ bold: true, children: [look.agent] })] : []),
254
- ...(parts.folder ? [Text({ dimColor: true, children: [parts.folder] })] : []),
255
- ],
256
- })
257
- const b = parts.battery
258
- const right = Text({
259
- wrap: 'truncate-end',
260
- children: [
261
- ...(b ? [Text({ color: b.low ? '#F2B84B' : '#6FD3A0', children: ['■'.repeat(b.filled)] }), Text({ dimColor: true, children: ['□'.repeat(b.empty) + b.text] })] : []),
262
- ...(parts.face ? [Text({ color: BOLT, children: [` ${parts.face}`] })] : []),
263
- ],
264
- })
265
- const theirs = await next(e)
266
- return Box({
267
- flexDirection: 'column',
268
- children: [
269
- ...(look.greeting ? [Box({ paddingX: 1, children: [Text({ dimColor: true, children: [look.greeting] })] })] : []),
270
- Box({ flexDirection: 'row', justifyContent: 'space-between', paddingX: 1, children: [left, right] }),
271
- ...(theirs ? [theirs] : []),
272
- ],
273
- })
274
- } catch (err) {
275
- $.ui.log(`帯を描けませんでした: ${err.message}`)
276
- return next(e)
277
- }
278
- })
279
-
280
- // 作業中の行: 「Thinking…」などを「作業中…」に。10秒を超えたら豆知識を1つ添える
281
- on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
282
- try {
283
- const theirs = await next({ ...e, props: { ...e.props, word: SPINNER_WORD } })
284
- if (!look.tip || !look.turnStart || Date.now() - look.turnStart < TIP_AFTER_MS) return theirs
285
- const { Box, Text } = $.ui.resolve(e)
286
- return Box({ flexDirection: 'column', children: [theirs, Text({ dimColor: true, wrap: 'truncate-end', children: [` 豆知識: ${look.tip}`] })] })
287
- } catch {
288
- return next(e)
289
- }
290
- })
291
-
292
- // 道具を使っている行: 英語・内部の名前を日本語の見出しに
293
- on('ui.render', { component: 'ToolUse' }, async ($, e, next) => {
294
- try {
295
- const { tool, input, isRunning, isErrored } = e.props
296
- const { Box, Text } = $.ui.resolve(e)
297
- const detail = toolDetail(input)
298
- return Box({
299
- children: [Text({
300
- wrap: 'truncate-end',
301
- children: [
302
- Text({ color: isErrored ? '#F07178' : isRunning ? BOLT : '#6FD3A0', children: ['⏺ '] }),
303
- Text({ bold: true, children: [toolLabel(tool)] }),
304
- ...(detail ? [Text({ dimColor: true, children: [` ${detail}`] })] : []),
305
- ],
306
- })],
307
- })
308
- } catch {
309
- return next(e)
310
- }
311
- })
312
-
313
- // まとめて表示された道具の行(「Read 3 files (ctrl+o to expand)」)。開いたときは1つずつの行(上の ToolUse)で出る
314
- on('ui.render', { component: 'ToolGroup' }, async ($, e, next) => {
315
- try {
316
- if (e.props.isExpanded || !e.props.calls?.length) return next(e)
317
- const { Text } = $.ui.resolve(e)
318
- return Text({
319
- wrap: 'truncate-end',
320
- children: [
321
- Text({ color: e.props.isActive ? BOLT : '#6FD3A0', children: ['⏺ '] }),
322
- Text({ bold: true, children: [groupSummary(e.props.calls)] }),
323
- Text({ dimColor: true, children: [` ${GROUP_HINT}`] }),
324
- ],
325
- })
326
- } catch {
327
- return next(e)
328
- }
329
- })
330
-
331
- // 作業が済んだ行(「Churned for 27s · done 16:19」など)は出さない
332
- on('ui.render', { component: 'TurnDuration' }, async ($, e, next) => {
333
- try {
334
- const { Box } = $.ui.resolve(e)
335
- return Box({ children: [] })
336
- } catch {
337
- return next(e)
338
- }
339
- })
340
- }
@@ -1,54 +0,0 @@
1
- // 金庫・鍵に触る道具の呼び出しを止める関所(register.js の tool.call から使う。サブエージェントの呼び出しにも効かせる)。
2
- //
3
- // これは「関所」であって「壁」ではない。AI は同じ PC の同じ利用者として動くので、名前を組み立て直す・別の書き方をする
4
- // (例: パスの一部を変数や * に分ける、別のプログラムを書いて動かす)と、ここをすり抜けられる。
5
- // 狙いは、ページや文書に仕込まれた指示に従って AI が素直に金庫を読みに行く、よくある形を止めることと、
6
- // 止めたことを画面に残して気づけるようにすること。秘密の値そのものの守りは、金庫の暗号化・人が入れた秘密を返さない
7
- // get_secret・ブラウザへ入れる前の本人の確認(agent-core)が受け持つ。
8
- //
9
- // 調べるのは、ファイルやコマンドを扱う組み込みの道具の入力の文字列すべて(Bash のコマンド・Read のパス・Edit の中身など)。
10
- // 普段の開発(npm test・git status・プロジェクトのファイルを読む)は止めない(test/vaultGate.test.mjs)。
11
-
12
- export const GATE_REASON = '金庫・鍵に触るコマンドは使えません。秘密は金庫の道具(list_secrets・get_secret・ask_secret・browser_fill_secret など)で扱ってください。'
13
-
14
- const GATED_TOOLS = new Set(['Bash', 'PowerShell', 'Monitor', 'Read', 'Grep', 'Glob', 'LS', 'Edit', 'MultiEdit', 'Write', 'NotebookEdit', 'NotebookRead'])
15
-
16
- // tool.call の入力のうち、道具の引数ではないもの
17
- const NOT_INPUT = new Set(['tool', 'tool_use_id', 'consent', 'agentId'])
18
-
19
- // [何に触るか, 見分け方]。金庫の置き場所は agent-core の vault.ts(~/.funny-booth/vault・Windows は %USERPROFILE%\.funny-booth\vault)
20
- const RULES = [
21
- ['金庫のフォルダ', /\.funny-booth[\\/]+vault/i],
22
- ['金庫のファイル', /\b(secrets\.enc|vault\.key|secret-sites\.json)\b/i],
23
- ['ログインの保存先', /\bportal-token(\.[a-z0-9-]+)?\.enc\b/i],
24
- ['追加した MCP に渡す秘密の一覧', /\bextra-mcps\.json\b/i],
25
- // OS の鍵保管庫に置いた金庫の鍵(サービス funny-booth・アカウント vault-key)と、鍵保管庫を読むコマンド
26
- ['金庫の鍵', /\bvault-key\b/i],
27
- ['macOS のキーチェーン', /\bsecurity\s+(find-generic-password|find-internet-password|dump-keychain|export)\b/i],
28
- ['Linux の鍵保管庫', /\bsecret-tool\b/i],
29
- ['Windows の資格情報', /\bcmdkey\b|CredentialManager|Get-StoredCredential|PasswordVault|\bCredRead|Windows\.Security\.Credentials/i],
30
- ['鍵保管庫の部品', /napi-rs[\\/]+keyring/i],
31
- // agent-core の中の、金庫を開く部品(伏せるための指紋の入口を含む)
32
- ['金庫を開く部品', /\b(vault|fillSecretHelper|secretPrints)\.js\b/i],
33
- // 端末の secret コマンドで、AI が秘密を入れ替える・消す・金庫を作り直す(人が端末で打つのは止めない)
34
- ['金庫を書き換えるコマンド', /\b[a-z0-9-]*(agent(os)?|agent-core|index)(\.js)?\s+secret\s+(set|rm|delete|reset)\b/i],
35
- ]
36
-
37
- function strings(value, out = []) {
38
- if (typeof value === 'string') out.push(value)
39
- else if (Array.isArray(value)) for (const v of value) strings(v, out)
40
- else if (value && typeof value === 'object') for (const v of Object.values(value)) strings(v, out)
41
- return out
42
- }
43
-
44
- /** 金庫・鍵に触る呼び出しなら、何に触るか(画面に残す短い言葉)。触らなければ null。 */
45
- export function vaultTouch(e) {
46
- if (!GATED_TOOLS.has(e.tool)) return null
47
- const texts = strings(Object.fromEntries(Object.entries(e).filter(([k]) => !NOT_INPUT.has(k))))
48
- for (const t of texts) {
49
- // フォルダと名前を分けて書いても(cd ~/.funny-booth && cat vault/…)止める
50
- if (/\.funny-booth/i.test(t) && /vault/i.test(t)) return '金庫のフォルダ'
51
- for (const [what, re] of RULES) if (re.test(t)) return what
52
- }
53
- return null
54
- }
@@ -1,125 +0,0 @@
1
- // FUNNY BOOTH の見た目(look.js)が画面に出す言葉。言葉を変えるときはここだけを直す
2
-
3
- // 道具の名前 → 日本語。Claude Code にもともとある道具と、FUNNY BOOTH の道具(mcp__<サーバー>__<名前> の <名前>)
4
- export const TOOL_LABELS = {
5
- Bash: 'コマンドを実行',
6
- Read: 'ファイルを読む',
7
- Write: 'ファイルを作る',
8
- Edit: 'ファイルを直す',
9
- MultiEdit: 'ファイルを直す',
10
- NotebookEdit: 'ファイルを直す',
11
- Grep: 'ファイルを探す',
12
- Glob: 'ファイルを探す',
13
- WebSearch: 'ウェブで調べる',
14
- WebFetch: 'ウェブのページを読む',
15
- Agent: '手伝い役に頼む',
16
- Task: '手伝い役に頼む',
17
- TodoWrite: 'やることを整理',
18
- AskUserQuestion: '質問',
19
- load_knowledge: '手順書を読んでいます',
20
- get_secret: '金庫から取り出す',
21
- store_secret: '金庫にしまう',
22
- ask_secret: 'パスワードを入れてもらう',
23
- list_secrets: '金庫の中を見る',
24
- delete_secret: '金庫から消す',
25
- set_secret_sites: '金庫の秘密を入れてよいサイトを決める',
26
- set_secret_human_step: 'ログインで人の手が要る所を書き留める',
27
- install_mcp: '道具を入れる',
28
- uninstall_mcp: '道具を外す',
29
- list_mcps: '道具の一覧',
30
- add_local_mcp: '自作の道具を入れる',
31
- send_feedback: '改善の要望を送る',
32
- browser_navigate: 'ページを開く',
33
- browser_click: '押す',
34
- browser_type: '入力する',
35
- browser_snapshot: '画面を読む',
36
- browser_take_screenshot: '画面を撮る',
37
- browser_fill_secret: '金庫の値を入力欄に入れる',
38
- spawn_wizard: '作業役を立ち上げる',
39
- send_to_wizard: '作業役に伝える',
40
- get_wizard_events: '作業役の様子を見る',
41
- query_wizard: '作業役の様子を見る',
42
- stop_wizard: '作業役を止める',
43
- search_memory: '覚えていることを探す',
44
- search_memory_text: '覚えていることを探す',
45
- add_memory: '覚えておく',
46
- generate_video: '動画を作る',
47
- generate_speech: '声を作る',
48
- ads_latest_briefing: '朝の報告を確認',
49
- ads_alert_state: '注意を確認',
50
- ads_my_requests: '出した依頼を確認',
51
- video_productions: '制作中の動画を確認',
52
- video_request: '動画を依頼する',
53
- video_appeals: '選べる訴求軸を確認',
54
- }
55
-
56
- // 経営ボードなど、表に無い道具は名前の頭で言い分ける(get_tasks → 確認)
57
- export const TOOL_VERBS = [
58
- [/^(get|list|search|query|check)_/, '確認'],
59
- [/^(create|add|upsert|log|record|invite)_/, '記録'],
60
- [/^(update|complete|reject|mark)_/, '更新'],
61
- [/^(delete|forget|remove)_/, '削除'],
62
- ]
63
-
64
- export const TOOL_FALLBACK = '道具を使っています'
65
-
66
- // 起動したときのあいさつ([始まりの時, 言葉]。時刻が始まりの時以上の最後の行を使う)
67
- export const GREETINGS = [
68
- [0, '遅くまでお疲れさまです。無理せずいきましょう'],
69
- [5, 'おはようございます。今日もよろしくお願いします'],
70
- [10, 'こんにちは。さあ始めましょう'],
71
- [17, 'こんばんは。もうひと仕事ですね'],
72
- [22, '遅くまでお疲れさまです。無理せずいきましょう'],
73
- ]
74
-
75
- export const SPINNER_WORD = '作業中'
76
- export const GROUP_HINT = '(ctrl+o で詳しく)'
77
-
78
- // 雷くんの表情
79
- export const FACES = {
80
- idle: '(-_-) zzz',
81
- work: 'ϟ(`・ω・)ϟ',
82
- done: '\(^▽^)/',
83
- fail: '(;´・ω・)ゞ',
84
- ask: '(・ω・)?',
85
- tired: '(´・ω・`)',
86
- }
87
-
88
- export const TOAST_DONE = (time) => `完了 ${time}`
89
- export const TOAST_ASK = 'お返事を待っています'
90
-
91
- // 待ち時間の豆知識
92
- export const TIPS = [
93
- '「この部分だけ直して」と範囲を言うと、早く確実に直ります',
94
- 'うまくいった頼み方は、スキルにして残せます',
95
- '迷ったら「選択肢を3つ出して」と頼むと決めやすくなります',
96
- '画面のスクショを貼ると、言葉より早く伝わります',
97
- '長い会話は、区切りのいいところで新しい会話にすると精度が戻ります',
98
- '「理由も教えて」と添えると、判断の根拠が分かります',
99
- '期限や目的を先に伝えると、段取りが良くなります',
100
- '大事なパスワードは、会話に書かず金庫にしまいましょう',
101
- '「まず計画だけ見せて」と頼むと、作る前に確認できます',
102
- '「何が分からない?」と聞き返すと、AI が確認したいことを教えてくれます',
103
- 'うまくいかないときは、やり方を変えるよう頼んでみましょう',
104
- '「今どこまで進んだ?」と聞くと、進み具合を教えてくれます',
105
- '直してほしい所は、「どうなってほしいか」で伝えると早く直ります',
106
- '一度に1つずつ頼むと、確実に仕上がります',
107
- '「確認してから進めて」と言えば、大事な所で止まってくれます',
108
- 'VS Code のスキルのタブから、よく使う頼み方を押すだけで呼べます',
109
- '左の列の雷のアイコンで、返事を待っている会話が分かります',
110
- '完成の形をできるだけ具体的に話すと、やり直しが減ります',
111
- '不具合や不便を見つけたら、エージェントに言えば改善の要望を送ってくれます',
112
- '会話の余裕の電池が減ってきたら、新しい会話に切り替えどきです',
113
- '数字や事実は「どこで確かめた?」と聞くと、根拠が分かります',
114
- '作業の前に「何を変えるか先に教えて」と言えば、予想外の変更を防げます',
115
- 'Esc を押すと、作業をいつでも止められます',
116
- '/model で AI の種類を切り替えられます。軽い作業は速いモデルにすると早く済みます',
117
- '/usage で、今の使用量と上限までの余裕が分かります',
118
- '/rewind で、少し前の状態まで巻き戻せます。「やっぱり元に戻したい」ときに',
119
- '/resume で、前の会話を選んで続きから再開できます',
120
- '/compact で会話を縮めると、会話の余裕が戻ります。電池が減ってきたときに',
121
- '/context で、会話の余裕が何に使われているかを見られます',
122
- '/status で、今の設定やログインの状態を確かめられます',
123
- '/help で、使えるコマンドの一覧が出ます',
124
- '「/」を打つと、使えるコマンドやスキルの候補が出てきます',
125
- ]
package/mod/tsconfig.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "extends": "./.claude-plugin/types/tsconfig.json"
3
- }
File without changes
File without changes
File without changes