@wellgrow/mcp 0.2.0 → 0.3.0
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/README.md +4 -0
- package/dist/index.js +77 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ WellGrow MCP Server — AI エージェントからユーザーのパーソナ
|
|
|
7
7
|
- **search_user_context** — 質問・回答をセマンティック検索
|
|
8
8
|
- **list_questions** — 質問一覧を取得(タグ・ステータスでフィルタ可)
|
|
9
9
|
- **answer_question** — 質問に対して回答を書き込む
|
|
10
|
+
- **save_feedback** — WellGrow 開発チームへフィードバックを送信
|
|
10
11
|
- **active-questions** リソース — アクティブな質問一覧(`@wellgrow` で参照)
|
|
11
12
|
|
|
12
13
|
## セットアップ
|
|
@@ -80,6 +81,9 @@ AI: → search_user_context → 検索結果を表示
|
|
|
80
81
|
|
|
81
82
|
ユーザー: 「この質問に『毎朝5分の瞑想から始める』と回答して」
|
|
82
83
|
AI: → answer_question → 回答を保存
|
|
84
|
+
|
|
85
|
+
ユーザー: 「WellGrowの検索、もっとタグでフィルタできるといいな」
|
|
86
|
+
AI: → save_feedback(improvement) → フィードバックを開発チームに送信
|
|
83
87
|
```
|
|
84
88
|
|
|
85
89
|
## 開発
|
package/dist/index.js
CHANGED
|
@@ -233,23 +233,25 @@ function registerAnswerQuestionTool(server2) {
|
|
|
233
233
|
async ({ question_id, answer, description }) => {
|
|
234
234
|
const supabase2 = await getSupabase();
|
|
235
235
|
const userId = await getUserId();
|
|
236
|
+
const { data: questionData, error: qError } = await supabase2.from("questions").select("question").eq("id", question_id).eq("user_id", userId).single();
|
|
237
|
+
if (qError || !questionData)
|
|
238
|
+
throw new Error(`\u8CEA\u554F\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${question_id}`);
|
|
236
239
|
const { error: insertError } = await supabase2.from("answers").insert({
|
|
237
240
|
question_id,
|
|
238
241
|
user_id: userId,
|
|
242
|
+
question: questionData.question,
|
|
239
243
|
answer,
|
|
240
244
|
description: description ?? null,
|
|
241
245
|
source: "mcp"
|
|
242
246
|
});
|
|
243
247
|
if (insertError)
|
|
244
248
|
throw new Error(`\u56DE\u7B54\u306E\u4FDD\u5B58\u306B\u5931\u6557: ${insertError.message}`);
|
|
245
|
-
const { data: questionData } = await supabase2.from("questions").select("question").eq("id", question_id).single();
|
|
246
|
-
const questionText = questionData?.question ?? question_id;
|
|
247
249
|
return {
|
|
248
250
|
content: [
|
|
249
251
|
{
|
|
250
252
|
type: "text",
|
|
251
253
|
text: `\u56DE\u7B54\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F:
|
|
252
|
-
\u8CEA\u554F: ${
|
|
254
|
+
\u8CEA\u554F: ${questionData.question}
|
|
253
255
|
\u56DE\u7B54: ${answer}`
|
|
254
256
|
}
|
|
255
257
|
]
|
|
@@ -304,6 +306,76 @@ answer_question \u3067\u56DE\u7B54\u3092\u66F8\u304D\u8FBC\u3080\u524D\u306B\u30
|
|
|
304
306
|
);
|
|
305
307
|
}
|
|
306
308
|
|
|
309
|
+
// src/tools/save-feedback.ts
|
|
310
|
+
import { z as z4 } from "zod";
|
|
311
|
+
var feedbackCategories = [
|
|
312
|
+
"bug",
|
|
313
|
+
"improvement",
|
|
314
|
+
"praise",
|
|
315
|
+
"question",
|
|
316
|
+
"other"
|
|
317
|
+
];
|
|
318
|
+
function registerSaveFeedbackTool(server2) {
|
|
319
|
+
server2.registerTool(
|
|
320
|
+
"save_feedback",
|
|
321
|
+
{
|
|
322
|
+
title: "\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u9001\u4FE1",
|
|
323
|
+
description: `WellGrow\u958B\u767A\u30C1\u30FC\u30E0\u3078\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002
|
|
324
|
+
|
|
325
|
+
\u4F7F\u7528\u3059\u308B\u5834\u9762:
|
|
326
|
+
- \u30E6\u30FC\u30B6\u30FC\u304CWellGrow\u3078\u306E\u6539\u5584\u63D0\u6848\u30FB\u30D0\u30B0\u5831\u544A\u30FB\u611F\u60F3\u3092\u4F1D\u3048\u305F\u3044\u3068\u304D
|
|
327
|
+
- WellGrow\u306E\u30C4\u30FC\u30EB\uFF08search_user_context\u7B49\uFF09\u3067\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u305F\u3068\u304D
|
|
328
|
+
- \u30E6\u30FC\u30B6\u30FC\u304CWellGrow\u306E\u4F53\u9A13\u306B\u3064\u3044\u3066\u8A00\u53CA\u3057\u305F\u3068\u304D
|
|
329
|
+
|
|
330
|
+
\u91CD\u8981: \u30E6\u30FC\u30B6\u30FC\u304C\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u306E\u9001\u4FE1\u3092\u610F\u56F3\u3057\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304B\u3089\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
331
|
+
\u30C4\u30FC\u30EB\u30A8\u30E9\u30FC\u306E\u5831\u544A\u3092\u9664\u304D\u3001\u30E6\u30FC\u30B6\u30FC\u306E\u627F\u8A8D\u306A\u304F\u9001\u4FE1\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
332
|
+
|
|
333
|
+
\u30AB\u30C6\u30B4\u30EA\u306E\u9078\u3073\u65B9:
|
|
334
|
+
- bug: \u30A8\u30E9\u30FC\u3084\u30D0\u30B0\u306B\u95A2\u3059\u308B\u3082\u306E
|
|
335
|
+
- improvement: \u6A5F\u80FD\u6539\u5584\u306E\u63D0\u6848\u3084\u30A2\u30A4\u30C7\u30A2
|
|
336
|
+
- praise: \u826F\u304B\u3063\u305F\u70B9\u3001\u6E80\u8DB3\u3057\u305F\u4F53\u9A13
|
|
337
|
+
- question: WellGrow\u306B\u95A2\u3059\u308B\u672A\u89E3\u6C7A\u306E\u8CEA\u554F
|
|
338
|
+
- other: \u4E0A\u8A18\u306B\u5F53\u3066\u306F\u307E\u3089\u306A\u3044\u3082\u306E`,
|
|
339
|
+
inputSchema: z4.object({
|
|
340
|
+
category: z4.enum(feedbackCategories).describe("\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u306E\u30AB\u30C6\u30B4\u30EA"),
|
|
341
|
+
message: z4.string().min(1).max(2e3).describe(
|
|
342
|
+
"\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u306E\u5185\u5BB9\u3002\u958B\u767A\u8005\u304C\u72B6\u6CC1\u3092\u7406\u89E3\u3067\u304D\u308B\u3088\u3046\u306B\u8981\u7D04"
|
|
343
|
+
),
|
|
344
|
+
user_message: z4.string().max(500).optional().describe("\u304D\u3063\u304B\u3051\u3068\u306A\u3063\u305F\u30E6\u30FC\u30B6\u30FC\u306E\u767A\u8A00\uFF08\u539F\u6587\u3092\u77ED\u304F\u5F15\u7528\uFF09")
|
|
345
|
+
}),
|
|
346
|
+
annotations: {
|
|
347
|
+
readOnlyHint: false,
|
|
348
|
+
destructiveHint: false,
|
|
349
|
+
idempotentHint: false
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
async ({ category, message, user_message }) => {
|
|
353
|
+
const supabase2 = await getSupabase();
|
|
354
|
+
const userId = await getUserId();
|
|
355
|
+
const context = {};
|
|
356
|
+
if (user_message) context.user_message = user_message;
|
|
357
|
+
const { error } = await supabase2.from("feedbacks").insert({
|
|
358
|
+
category,
|
|
359
|
+
message,
|
|
360
|
+
source: "mcp",
|
|
361
|
+
user_id: userId,
|
|
362
|
+
page_path: "mcp",
|
|
363
|
+
context: Object.keys(context).length > 0 ? context : null
|
|
364
|
+
});
|
|
365
|
+
if (error)
|
|
366
|
+
throw new Error(`\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u306E\u4FDD\u5B58\u306B\u5931\u6557: ${error.message}`);
|
|
367
|
+
return {
|
|
368
|
+
content: [
|
|
369
|
+
{
|
|
370
|
+
type: "text",
|
|
371
|
+
text: `\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F\uFF08${category}\uFF09`
|
|
372
|
+
}
|
|
373
|
+
]
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
307
379
|
// src/resources/questions.ts
|
|
308
380
|
function registerQuestionsResource(server2) {
|
|
309
381
|
server2.registerResource(
|
|
@@ -348,7 +420,7 @@ try {
|
|
|
348
420
|
process.exit(1);
|
|
349
421
|
}
|
|
350
422
|
var server = new McpServer(
|
|
351
|
-
{ name: "wellgrow", version: "0.
|
|
423
|
+
{ name: "wellgrow", version: "0.3.0" },
|
|
352
424
|
{
|
|
353
425
|
instructions: `WellGrow \u306E\u30E6\u30FC\u30B6\u30FC\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u306B\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u30B5\u30FC\u30D0\u30FC\u3067\u3059\u3002
|
|
354
426
|
\u30E6\u30FC\u30B6\u30FC\u306E\u8CEA\u554F\u30FB\u56DE\u7B54\u30C7\u30FC\u30BF\u306E\u691C\u7D22\u30FB\u95B2\u89A7\u30FB\u66F8\u304D\u8FBC\u307F\u304C\u3067\u304D\u307E\u3059\u3002
|
|
@@ -358,6 +430,7 @@ var server = new McpServer(
|
|
|
358
430
|
registerSearchContextTool(server);
|
|
359
431
|
registerAnswerQuestionTool(server);
|
|
360
432
|
registerListQuestionsTool(server);
|
|
433
|
+
registerSaveFeedbackTool(server);
|
|
361
434
|
registerQuestionsResource(server);
|
|
362
435
|
var transport = new StdioServerTransport();
|
|
363
436
|
await server.connect(transport);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/auth.ts","../src/tools/search-context.ts","../src/embedding.ts","../src/format.ts","../src/tools/answer-question.ts","../src/tools/list-questions.ts","../src/resources/questions.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { getSupabase } from \"./auth.js\";\nimport { registerSearchContextTool } from \"./tools/search-context.js\";\nimport { registerAnswerQuestionTool } from \"./tools/answer-question.js\";\nimport { registerListQuestionsTool } from \"./tools/list-questions.js\";\nimport { registerQuestionsResource } from \"./resources/questions.js\";\n\nconst required = [\"WELLGROW_EMAIL\", \"WELLGROW_PASSWORD\", \"OPENAI_API_KEY\"];\n\nfor (const key of required) {\n if (!process.env[key]) {\n console.error(`Error: ${key} is required`);\n process.exit(1);\n }\n}\n\ntry {\n await getSupabase();\n console.error(\"Authenticated successfully\");\n} catch (error) {\n console.error(\n \"Authentication failed:\",\n error instanceof Error ? error.message : error\n );\n process.exit(1);\n}\n\nconst server = new McpServer(\n { name: \"wellgrow\", version: \"0.2.0\" },\n {\n instructions: `WellGrow のユーザーナレッジベースにアクセスするサーバーです。\nユーザーの質問・回答データの検索・閲覧・書き込みができます。\nユーザーの考えや価値観を理解したい場面で活用してください。`,\n }\n);\n\nregisterSearchContextTool(server);\nregisterAnswerQuestionTool(server);\nregisterListQuestionsTool(server);\nregisterQuestionsResource(server);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\nconsole.error(\"WellGrow MCP server running on stdio\");\n","import { createClient, type SupabaseClient } from \"@supabase/supabase-js\";\n\nconst DEFAULT_SUPABASE_URL = \"https://rpywqbtporjdhwtmvwkf.supabase.co\";\nconst DEFAULT_SUPABASE_ANON_KEY =\n \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJweXdxYnRwb3JqZGh3dG12d2tmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njc4NjA4MDIsImV4cCI6MjA4MzQzNjgwMn0.1nn9F2y1JZBoSgB33CnP-k-6OM5HcEMdUs50RLJ89i4\";\n\nlet supabase: SupabaseClient | null = null;\n\nexport function getSupabaseUrl(): string {\n return process.env.WELLGROW_SUPABASE_URL ?? DEFAULT_SUPABASE_URL;\n}\n\nexport function getSupabaseAnonKey(): string {\n return process.env.WELLGROW_SUPABASE_ANON_KEY ?? DEFAULT_SUPABASE_ANON_KEY;\n}\n\nexport async function getSupabase(): Promise<SupabaseClient> {\n if (supabase) {\n const {\n data: { session },\n } = await supabase.auth.getSession();\n if (session) return supabase;\n }\n\n supabase = createClient(getSupabaseUrl(), getSupabaseAnonKey(), {\n auth: {\n autoRefreshToken: true,\n persistSession: false,\n },\n });\n\n const { error } = await supabase.auth.signInWithPassword({\n email: process.env.WELLGROW_EMAIL!,\n password: process.env.WELLGROW_PASSWORD!,\n });\n\n if (error) {\n throw new Error(`Authentication failed: ${error.message}`);\n }\n\n return supabase;\n}\n\nexport async function getUserId(): Promise<string> {\n const sb = await getSupabase();\n const {\n data: { user },\n } = await sb.auth.getUser();\n if (!user) throw new Error(\"Not authenticated\");\n return user.id;\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase, getUserId } from \"../auth.js\";\nimport { generateEmbedding } from \"../embedding.js\";\nimport {\n formatSearchResult,\n type QuestionHit,\n type AnswerHit,\n} from \"../format.js\";\n\nexport function registerSearchContextTool(server: McpServer): void {\n server.registerTool(\n \"search_user_context\",\n {\n title: \"ユーザーコンテキスト検索\",\n description: `ユーザーの質問と回答のデータベースを検索します。\nユーザーの考え・価値観・経験・知識を理解するために使います。\n\n使用場面:\n- アドバイスや提案をする前に、ユーザーの価値観・原則を確認したいとき\n- 意思決定の場面で、過去の判断基準や経験を参照したいとき\n- 「私のスタイルで」「私らしく」など、ユーザーの好みを把握したいとき\n- ユーザーの背景(専門分野、関心、目標)を理解したいとき\n\n検索戦略(組み合わせ可能):\n- query のみ: セマンティック検索(意味的に近い内容を幅広く取得)\n- keywords を追加: ハイブリッド検索(意味的類似 + キーワード一致で精度向上)\n- tags/statuses/pinned: フィルタで結果を絞り込み\n\ntarget の使い分け:\n- \"questions\": 質問の一覧を見たいとき(最新回答も付属)\n- \"answers\": 回答の内容を重点的に調べたいとき\n- \"all\": 幅広く情報を集めたいとき(デフォルト)`,\n inputSchema: z.object({\n query: z.string().describe(\"検索クエリ(セマンティック検索に使用)\"),\n keywords: z\n .array(z.string())\n .optional()\n .describe(\"キーワード部分一致\"),\n target: z\n .enum([\"questions\", \"answers\", \"all\"])\n .default(\"all\")\n .describe(\"検索対象\"),\n tags: z.array(z.string()).optional().describe(\"タグでフィルタ\"),\n statuses: z\n .array(z.string())\n .optional()\n .describe(\"ステータスでフィルタ(省略時: active, paused)\"),\n pinned: z.boolean().optional().describe(\"ピン留めされた質問のみ\"),\n limit: z\n .number()\n .min(1)\n .max(50)\n .default(10)\n .describe(\"取得件数上限\"),\n }),\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n },\n async ({ query, keywords, target, tags, statuses, pinned, limit }) => {\n const supabase = await getSupabase();\n const userId = await getUserId();\n const embeddingStr = await generateEmbedding(query);\n\n const questions: QuestionHit[] = [];\n const answers: AnswerHit[] = [];\n const promises: PromiseLike<void>[] = [];\n\n if (target !== \"answers\") {\n promises.push(\n supabase\n .rpc(\"search_questions\", {\n p_user_id: userId,\n p_keywords: keywords ?? null,\n p_embedding: embeddingStr,\n p_vector_threshold: 0.3,\n p_statuses: statuses ?? [\"active\", \"paused\"],\n p_tags: tags ?? null,\n p_date_from: null,\n p_date_to: null,\n p_pinned: pinned ?? null,\n p_limit: limit ?? 10,\n })\n .then(({ data }) => {\n if (data) questions.push(...data);\n })\n );\n }\n\n if (target !== \"questions\") {\n promises.push(\n supabase\n .rpc(\"search_answers\", {\n p_user_id: userId,\n p_keywords: keywords ?? null,\n p_embedding: embeddingStr,\n p_vector_threshold: 0.3,\n p_sources: null,\n p_date_from: null,\n p_date_to: null,\n p_exclude_question_ids: null,\n p_limit: limit ?? 10,\n })\n .then(({ data }) => {\n if (data) answers.push(...data);\n })\n );\n }\n\n await Promise.all(promises);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: formatSearchResult({ questions, answers }),\n },\n ],\n };\n }\n );\n}\n","import { embed } from \"ai\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\n\nconst openai = createOpenAI();\nconst embeddingModel = openai.embedding(\"text-embedding-3-small\");\n\nexport async function generateEmbedding(text: string): Promise<string> {\n const { embedding } = await embed({\n model: embeddingModel,\n value: text,\n });\n return JSON.stringify(embedding);\n}\n","export interface QuestionHit {\n id: string;\n question: string;\n tags: string[];\n importance: number | null;\n similarity: number | null;\n latest_answer: string | null;\n latest_answer_at: string | null;\n updated_at: string | null;\n}\n\nexport interface AnswerHit {\n answer_id: string;\n answer: string;\n answer_description: string | null;\n answer_source: string | null;\n similarity: number | null;\n answered_at: string;\n question_id: string;\n question: string;\n}\n\nexport interface QuestionListItem {\n id: string;\n question: string;\n tags: string[];\n status: string;\n importance: number | null;\n pinned: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport function formatSearchResult(result: {\n questions: QuestionHit[];\n answers: AnswerHit[];\n}): string {\n const parts: string[] = [];\n\n if (result.questions.length > 0) {\n parts.push(`## 質問 (${result.questions.length}件)`);\n for (const q of result.questions) {\n const tags = q.tags.length > 0 ? ` [${q.tags.join(\", \")}]` : \"\";\n const answer = q.latest_answer\n ? `\\n 最新回答: ${q.latest_answer}`\n : \"\";\n parts.push(`- **${q.question}**${tags}${answer}\\n ID: ${q.id}`);\n }\n }\n\n if (result.answers.length > 0) {\n parts.push(`## 回答 (${result.answers.length}件)`);\n for (const a of result.answers) {\n const desc = a.answer_description\n ? `\\n 説明: ${a.answer_description}`\n : \"\";\n parts.push(\n `- **${a.question}**\\n 回答: ${a.answer}${desc}\\n 回答日: ${a.answered_at}`\n );\n }\n }\n\n if (parts.length === 0) {\n return \"検索結果はありません。\";\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nexport function formatQuestionList(questions: QuestionListItem[]): string {\n if (questions.length === 0) {\n return \"質問はありません。\";\n }\n\n const lines: string[] = [`## 質問一覧 (${questions.length}件)`];\n\n for (const q of questions) {\n const tags = q.tags.length > 0 ? ` [${q.tags.join(\", \")}]` : \"\";\n const pinned = q.pinned ? \" 📌\" : \"\";\n const status = q.status !== \"active\" ? ` (${q.status})` : \"\";\n lines.push(\n `- **${q.question}**${tags}${pinned}${status}\\n ID: ${q.id} | 更新: ${q.updated_at}`\n );\n }\n\n return lines.join(\"\\n\\n\");\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase, getUserId } from \"../auth.js\";\n\nexport function registerAnswerQuestionTool(server: McpServer): void {\n server.registerTool(\n \"answer_question\",\n {\n title: \"質問への回答書き込み\",\n description: `ユーザーの質問に対して回答を書き込みます。\nユーザーとの会話で重要な気づきや洞察が生まれた時に使います。\n\n使用前に必ずユーザーの承認を得てください。\n\n【回答のルール】\n- answer は140文字以内で、端的に核心を突く回答にする\n- ユーザー自身の言葉を活かした回答にする\n- description には回答の背景・根拠・詳細な説明を書く\n- question_id は search_user_context や list_questions で取得した ID を使う`,\n inputSchema: z.object({\n question_id: z.string().describe(\"対象の質問 ID\"),\n answer: z.string().max(140).describe(\"回答(140文字以内)\"),\n description: z\n .string()\n .max(300)\n .optional()\n .describe(\"回答の詳細説明(300文字以内)\"),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n },\n async ({ question_id, answer, description }) => {\n const supabase = await getSupabase();\n const userId = await getUserId();\n\n const { error: insertError } = await supabase.from(\"answers\").insert({\n question_id,\n user_id: userId,\n answer,\n description: description ?? null,\n source: \"mcp\",\n });\n\n if (insertError)\n throw new Error(`回答の保存に失敗: ${insertError.message}`);\n\n const { data: questionData } = await supabase\n .from(\"questions\")\n .select(\"question\")\n .eq(\"id\", question_id)\n .single();\n\n const questionText = questionData?.question ?? question_id;\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `回答を保存しました:\\n質問: ${questionText}\\n回答: ${answer}`,\n },\n ],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase } from \"../auth.js\";\nimport { formatQuestionList } from \"../format.js\";\n\nexport function registerListQuestionsTool(server: McpServer): void {\n server.registerTool(\n \"list_questions\",\n {\n title: \"質問一覧取得\",\n description: `ユーザーの質問一覧を取得します。ステータスやタグでフィルタ可能。\n質問の ID を確認したいときや、ユーザーがどんな質問を持っているか把握したいときに使います。\nanswer_question で回答を書き込む前に、対象の question_id を確認する用途にも使えます。`,\n inputSchema: z.object({\n status: z\n .array(z.string())\n .optional()\n .default([\"active\", \"paused\"])\n .describe(\"ステータスでフィルタ\"),\n tags: z.array(z.string()).optional().describe(\"タグでフィルタ\"),\n pinned: z.boolean().optional().describe(\"ピン留めされた質問のみ\"),\n limit: z\n .number()\n .min(1)\n .max(50)\n .default(20)\n .describe(\"取得件数上限\"),\n }),\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n },\n async ({ status, tags, pinned, limit }) => {\n const supabase = await getSupabase();\n\n let query = supabase\n .from(\"questions\")\n .select(\n \"id, question, tags, status, importance, pinned, created_at, updated_at\"\n )\n .in(\"status\", status ?? [\"active\", \"paused\"])\n .order(\"updated_at\", { ascending: false })\n .limit(limit ?? 20);\n\n if (tags?.length) {\n query = query.overlaps(\"tags\", tags);\n }\n if (pinned !== undefined) {\n query = query.eq(\"pinned\", pinned);\n }\n\n const { data, error } = await query;\n if (error) throw new Error(`質問取得に失敗: ${error.message}`);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: formatQuestionList(data ?? []),\n },\n ],\n };\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase } from \"../auth.js\";\n\nexport function registerQuestionsResource(server: McpServer): void {\n server.registerResource(\n \"active-questions\",\n \"wellgrow://questions/active\",\n {\n title: \"アクティブな質問一覧\",\n description: \"ステータスが active の質問一覧。\",\n mimeType: \"application/json\",\n },\n async (uri) => {\n const supabase = await getSupabase();\n const { data } = await supabase\n .from(\"questions\")\n .select(\"id, question, tags, importance, pinned, updated_at\")\n .eq(\"status\", \"active\")\n .order(\"updated_at\", { ascending: false })\n .limit(50);\n\n return {\n contents: [\n {\n uri: uri.href,\n text: JSON.stringify(data ?? [], null, 2),\n },\n ],\n };\n }\n );\n}\n"],"mappings":";;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACDrC,SAAS,oBAAyC;AAElD,IAAM,uBAAuB;AAC7B,IAAM,4BACJ;AAEF,IAAI,WAAkC;AAE/B,SAAS,iBAAyB;AACvC,SAAO,QAAQ,IAAI,yBAAyB;AAC9C;AAEO,SAAS,qBAA6B;AAC3C,SAAO,QAAQ,IAAI,8BAA8B;AACnD;AAEA,eAAsB,cAAuC;AAC3D,MAAI,UAAU;AACZ,UAAM;AAAA,MACJ,MAAM,EAAE,QAAQ;AAAA,IAClB,IAAI,MAAM,SAAS,KAAK,WAAW;AACnC,QAAI,QAAS,QAAO;AAAA,EACtB;AAEA,aAAW,aAAa,eAAe,GAAG,mBAAmB,GAAG;AAAA,IAC9D,MAAM;AAAA,MACJ,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,EAAE,MAAM,IAAI,MAAM,SAAS,KAAK,mBAAmB;AAAA,IACvD,OAAO,QAAQ,IAAI;AAAA,IACnB,UAAU,QAAQ,IAAI;AAAA,EACxB,CAAC;AAED,MAAI,OAAO;AACT,UAAM,IAAI,MAAM,0BAA0B,MAAM,OAAO,EAAE;AAAA,EAC3D;AAEA,SAAO;AACT;AAEA,eAAsB,YAA6B;AACjD,QAAM,KAAK,MAAM,YAAY;AAC7B,QAAM;AAAA,IACJ,MAAM,EAAE,KAAK;AAAA,EACf,IAAI,MAAM,GAAG,KAAK,QAAQ;AAC1B,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,mBAAmB;AAC9C,SAAO,KAAK;AACd;;;AClDA,SAAS,SAAS;;;ACAlB,SAAS,aAAa;AACtB,SAAS,oBAAoB;AAE7B,IAAM,SAAS,aAAa;AAC5B,IAAM,iBAAiB,OAAO,UAAU,wBAAwB;AAEhE,eAAsB,kBAAkB,MAA+B;AACrE,QAAM,EAAE,UAAU,IAAI,MAAM,MAAM;AAAA,IAChC,OAAO;AAAA,IACP,OAAO;AAAA,EACT,CAAC;AACD,SAAO,KAAK,UAAU,SAAS;AACjC;;;ACqBO,SAAS,mBAAmB,QAGxB;AACT,QAAM,QAAkB,CAAC;AAEzB,MAAI,OAAO,UAAU,SAAS,GAAG;AAC/B,UAAM,KAAK,oBAAU,OAAO,UAAU,MAAM,SAAI;AAChD,eAAW,KAAK,OAAO,WAAW;AAChC,YAAM,OAAO,EAAE,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,MAAM;AAC7D,YAAM,SAAS,EAAE,gBACb;AAAA,8BAAa,EAAE,aAAa,KAC5B;AACJ,YAAM,KAAK,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM;AAAA,QAAW,EAAE,EAAE,EAAE;AAAA,IACjE;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,UAAM,KAAK,oBAAU,OAAO,QAAQ,MAAM,SAAI;AAC9C,eAAW,KAAK,OAAO,SAAS;AAC9B,YAAM,OAAO,EAAE,qBACX;AAAA,kBAAW,EAAE,kBAAkB,KAC/B;AACJ,YAAM;AAAA,QACJ,OAAO,EAAE,QAAQ;AAAA,kBAAa,EAAE,MAAM,GAAG,IAAI;AAAA,wBAAY,EAAE,WAAW;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAEO,SAAS,mBAAmB,WAAuC;AACxE,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB,CAAC,gCAAY,UAAU,MAAM,SAAI;AAEzD,aAAW,KAAK,WAAW;AACzB,UAAM,OAAO,EAAE,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,MAAM;AAC7D,UAAM,SAAS,EAAE,SAAS,eAAQ;AAClC,UAAM,SAAS,EAAE,WAAW,WAAW,KAAK,EAAE,MAAM,MAAM;AAC1D,UAAM;AAAA,MACJ,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,GAAG,MAAM;AAAA,QAAW,EAAE,EAAE,oBAAU,EAAE,UAAU;AAAA,IACnF;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;;;AF5EO,SAAS,0BAA0BA,SAAyB;AACjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkBb,aAAa,EAAE,OAAO;AAAA,QACpB,OAAO,EAAE,OAAO,EAAE,SAAS,oHAAqB;AAAA,QAChD,UAAU,EACP,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,wDAAW;AAAA,QACvB,QAAQ,EACL,KAAK,CAAC,aAAa,WAAW,KAAK,CAAC,EACpC,QAAQ,KAAK,EACb,SAAS,0BAAM;AAAA,QAClB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4CAAS;AAAA,QACvD,UAAU,EACP,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,4GAAiC;AAAA,QAC7C,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,oEAAa;AAAA,QACrD,OAAO,EACJ,OAAO,EACP,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,EAAE,EACV,SAAS,sCAAQ;AAAA,MACtB,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,OAAO,UAAU,QAAQ,MAAM,UAAU,QAAQ,MAAM,MAAM;AACpE,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,SAAS,MAAM,UAAU;AAC/B,YAAM,eAAe,MAAM,kBAAkB,KAAK;AAElD,YAAM,YAA2B,CAAC;AAClC,YAAM,UAAuB,CAAC;AAC9B,YAAM,WAAgC,CAAC;AAEvC,UAAI,WAAW,WAAW;AACxB,iBAAS;AAAA,UACPA,UACG,IAAI,oBAAoB;AAAA,YACvB,WAAW;AAAA,YACX,YAAY,YAAY;AAAA,YACxB,aAAa;AAAA,YACb,oBAAoB;AAAA,YACpB,YAAY,YAAY,CAAC,UAAU,QAAQ;AAAA,YAC3C,QAAQ,QAAQ;AAAA,YAChB,aAAa;AAAA,YACb,WAAW;AAAA,YACX,UAAU,UAAU;AAAA,YACpB,SAAS,SAAS;AAAA,UACpB,CAAC,EACA,KAAK,CAAC,EAAE,KAAK,MAAM;AAClB,gBAAI,KAAM,WAAU,KAAK,GAAG,IAAI;AAAA,UAClC,CAAC;AAAA,QACL;AAAA,MACF;AAEA,UAAI,WAAW,aAAa;AAC1B,iBAAS;AAAA,UACPA,UACG,IAAI,kBAAkB;AAAA,YACrB,WAAW;AAAA,YACX,YAAY,YAAY;AAAA,YACxB,aAAa;AAAA,YACb,oBAAoB;AAAA,YACpB,WAAW;AAAA,YACX,aAAa;AAAA,YACb,WAAW;AAAA,YACX,wBAAwB;AAAA,YACxB,SAAS,SAAS;AAAA,UACpB,CAAC,EACA,KAAK,CAAC,EAAE,KAAK,MAAM;AAClB,gBAAI,KAAM,SAAQ,KAAK,GAAG,IAAI;AAAA,UAChC,CAAC;AAAA,QACL;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,QAAQ;AAE1B,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,mBAAmB,EAAE,WAAW,QAAQ,CAAC;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AG3HA,SAAS,KAAAC,UAAS;AAIX,SAAS,2BAA2BC,SAAyB;AAClE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUb,aAAaC,GAAE,OAAO;AAAA,QACpB,aAAaA,GAAE,OAAO,EAAE,SAAS,mCAAU;AAAA,QAC3C,QAAQA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,qDAAa;AAAA,QAClD,aAAaA,GACV,OAAO,EACP,IAAI,GAAG,EACP,SAAS,EACT,SAAS,mFAAkB;AAAA,MAChC,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,aAAa,QAAQ,YAAY,MAAM;AAC9C,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,SAAS,MAAM,UAAU;AAE/B,YAAM,EAAE,OAAO,YAAY,IAAI,MAAMA,UAAS,KAAK,SAAS,EAAE,OAAO;AAAA,QACnE;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,aAAa,eAAe;AAAA,QAC5B,QAAQ;AAAA,MACV,CAAC;AAED,UAAI;AACF,cAAM,IAAI,MAAM,qDAAa,YAAY,OAAO,EAAE;AAEpD,YAAM,EAAE,MAAM,aAAa,IAAI,MAAMA,UAClC,KAAK,WAAW,EAChB,OAAO,UAAU,EACjB,GAAG,MAAM,WAAW,EACpB,OAAO;AAEV,YAAM,eAAe,cAAc,YAAY;AAE/C,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,gBAAmB,YAAY;AAAA,gBAAS,MAAM;AAAA,UACtD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACnEA,SAAS,KAAAC,UAAS;AAKX,SAAS,0BAA0BC,SAAyB;AACjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA,MAGb,aAAaC,GAAE,OAAO;AAAA,QACpB,QAAQA,GACL,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT,QAAQ,CAAC,UAAU,QAAQ,CAAC,EAC5B,SAAS,8DAAY;AAAA,QACxB,MAAMA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4CAAS;AAAA,QACvD,QAAQA,GAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,oEAAa;AAAA,QACrD,OAAOA,GACJ,OAAO,EACP,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,EAAE,EACV,SAAS,sCAAQ;AAAA,MACtB,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,QAAQ,MAAM,QAAQ,MAAM,MAAM;AACzC,YAAMC,YAAW,MAAM,YAAY;AAEnC,UAAI,QAAQA,UACT,KAAK,WAAW,EAChB;AAAA,QACC;AAAA,MACF,EACC,GAAG,UAAU,UAAU,CAAC,UAAU,QAAQ,CAAC,EAC3C,MAAM,cAAc,EAAE,WAAW,MAAM,CAAC,EACxC,MAAM,SAAS,EAAE;AAEpB,UAAI,MAAM,QAAQ;AAChB,gBAAQ,MAAM,SAAS,QAAQ,IAAI;AAAA,MACrC;AACA,UAAI,WAAW,QAAW;AACxB,gBAAQ,MAAM,GAAG,UAAU,MAAM;AAAA,MACnC;AAEA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM;AAC9B,UAAI,MAAO,OAAM,IAAI,MAAM,+CAAY,MAAM,OAAO,EAAE;AAEtD,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,mBAAmB,QAAQ,CAAC,CAAC;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC9DO,SAAS,0BAA0BC,SAAyB;AACjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AACb,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,EAAE,KAAK,IAAI,MAAMA,UACpB,KAAK,WAAW,EAChB,OAAO,oDAAoD,EAC3D,GAAG,UAAU,QAAQ,EACrB,MAAM,cAAc,EAAE,WAAW,MAAM,CAAC,EACxC,MAAM,EAAE;AAEX,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,KAAK,IAAI;AAAA,YACT,MAAM,KAAK,UAAU,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;APvBA,IAAM,WAAW,CAAC,kBAAkB,qBAAqB,gBAAgB;AAEzE,WAAW,OAAO,UAAU;AAC1B,MAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,YAAQ,MAAM,UAAU,GAAG,cAAc;AACzC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,IAAI;AACF,QAAM,YAAY;AAClB,UAAQ,MAAM,4BAA4B;AAC5C,SAAS,OAAO;AACd,UAAQ;AAAA,IACN;AAAA,IACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,EAC3C;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,IAAI;AAAA,EACjB,EAAE,MAAM,YAAY,SAAS,QAAQ;AAAA,EACrC;AAAA,IACE,cAAc;AAAA;AAAA;AAAA,EAGhB;AACF;AAEA,0BAA0B,MAAM;AAChC,2BAA2B,MAAM;AACjC,0BAA0B,MAAM;AAChC,0BAA0B,MAAM;AAEhC,IAAM,YAAY,IAAI,qBAAqB;AAC3C,MAAM,OAAO,QAAQ,SAAS;AAC9B,QAAQ,MAAM,sCAAsC;","names":["server","supabase","z","server","z","supabase","z","server","z","supabase","server","supabase"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/auth.ts","../src/tools/search-context.ts","../src/embedding.ts","../src/format.ts","../src/tools/answer-question.ts","../src/tools/list-questions.ts","../src/tools/save-feedback.ts","../src/resources/questions.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { getSupabase } from \"./auth.js\";\nimport { registerSearchContextTool } from \"./tools/search-context.js\";\nimport { registerAnswerQuestionTool } from \"./tools/answer-question.js\";\nimport { registerListQuestionsTool } from \"./tools/list-questions.js\";\nimport { registerSaveFeedbackTool } from \"./tools/save-feedback.js\";\nimport { registerQuestionsResource } from \"./resources/questions.js\";\n\nconst required = [\"WELLGROW_EMAIL\", \"WELLGROW_PASSWORD\", \"OPENAI_API_KEY\"];\n\nfor (const key of required) {\n if (!process.env[key]) {\n console.error(`Error: ${key} is required`);\n process.exit(1);\n }\n}\n\ntry {\n await getSupabase();\n console.error(\"Authenticated successfully\");\n} catch (error) {\n console.error(\n \"Authentication failed:\",\n error instanceof Error ? error.message : error\n );\n process.exit(1);\n}\n\nconst server = new McpServer(\n { name: \"wellgrow\", version: \"0.3.0\" },\n {\n instructions: `WellGrow のユーザーナレッジベースにアクセスするサーバーです。\nユーザーの質問・回答データの検索・閲覧・書き込みができます。\nユーザーの考えや価値観を理解したい場面で活用してください。`,\n }\n);\n\nregisterSearchContextTool(server);\nregisterAnswerQuestionTool(server);\nregisterListQuestionsTool(server);\nregisterSaveFeedbackTool(server);\nregisterQuestionsResource(server);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\nconsole.error(\"WellGrow MCP server running on stdio\");\n","import { createClient, type SupabaseClient } from \"@supabase/supabase-js\";\n\nconst DEFAULT_SUPABASE_URL = \"https://rpywqbtporjdhwtmvwkf.supabase.co\";\nconst DEFAULT_SUPABASE_ANON_KEY =\n \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJweXdxYnRwb3JqZGh3dG12d2tmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njc4NjA4MDIsImV4cCI6MjA4MzQzNjgwMn0.1nn9F2y1JZBoSgB33CnP-k-6OM5HcEMdUs50RLJ89i4\";\n\nlet supabase: SupabaseClient | null = null;\n\nexport function getSupabaseUrl(): string {\n return process.env.WELLGROW_SUPABASE_URL ?? DEFAULT_SUPABASE_URL;\n}\n\nexport function getSupabaseAnonKey(): string {\n return process.env.WELLGROW_SUPABASE_ANON_KEY ?? DEFAULT_SUPABASE_ANON_KEY;\n}\n\nexport async function getSupabase(): Promise<SupabaseClient> {\n if (supabase) {\n const {\n data: { session },\n } = await supabase.auth.getSession();\n if (session) return supabase;\n }\n\n supabase = createClient(getSupabaseUrl(), getSupabaseAnonKey(), {\n auth: {\n autoRefreshToken: true,\n persistSession: false,\n },\n });\n\n const { error } = await supabase.auth.signInWithPassword({\n email: process.env.WELLGROW_EMAIL!,\n password: process.env.WELLGROW_PASSWORD!,\n });\n\n if (error) {\n throw new Error(`Authentication failed: ${error.message}`);\n }\n\n return supabase;\n}\n\nexport async function getUserId(): Promise<string> {\n const sb = await getSupabase();\n const {\n data: { user },\n } = await sb.auth.getUser();\n if (!user) throw new Error(\"Not authenticated\");\n return user.id;\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase, getUserId } from \"../auth.js\";\nimport { generateEmbedding } from \"../embedding.js\";\nimport {\n formatSearchResult,\n type QuestionHit,\n type AnswerHit,\n} from \"../format.js\";\n\nexport function registerSearchContextTool(server: McpServer): void {\n server.registerTool(\n \"search_user_context\",\n {\n title: \"ユーザーコンテキスト検索\",\n description: `ユーザーの質問と回答のデータベースを検索します。\nユーザーの考え・価値観・経験・知識を理解するために使います。\n\n使用場面:\n- アドバイスや提案をする前に、ユーザーの価値観・原則を確認したいとき\n- 意思決定の場面で、過去の判断基準や経験を参照したいとき\n- 「私のスタイルで」「私らしく」など、ユーザーの好みを把握したいとき\n- ユーザーの背景(専門分野、関心、目標)を理解したいとき\n\n検索戦略(組み合わせ可能):\n- query のみ: セマンティック検索(意味的に近い内容を幅広く取得)\n- keywords を追加: ハイブリッド検索(意味的類似 + キーワード一致で精度向上)\n- tags/statuses/pinned: フィルタで結果を絞り込み\n\ntarget の使い分け:\n- \"questions\": 質問の一覧を見たいとき(最新回答も付属)\n- \"answers\": 回答の内容を重点的に調べたいとき\n- \"all\": 幅広く情報を集めたいとき(デフォルト)`,\n inputSchema: z.object({\n query: z.string().describe(\"検索クエリ(セマンティック検索に使用)\"),\n keywords: z\n .array(z.string())\n .optional()\n .describe(\"キーワード部分一致\"),\n target: z\n .enum([\"questions\", \"answers\", \"all\"])\n .default(\"all\")\n .describe(\"検索対象\"),\n tags: z.array(z.string()).optional().describe(\"タグでフィルタ\"),\n statuses: z\n .array(z.string())\n .optional()\n .describe(\"ステータスでフィルタ(省略時: active, paused)\"),\n pinned: z.boolean().optional().describe(\"ピン留めされた質問のみ\"),\n limit: z\n .number()\n .min(1)\n .max(50)\n .default(10)\n .describe(\"取得件数上限\"),\n }),\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n },\n async ({ query, keywords, target, tags, statuses, pinned, limit }) => {\n const supabase = await getSupabase();\n const userId = await getUserId();\n const embeddingStr = await generateEmbedding(query);\n\n const questions: QuestionHit[] = [];\n const answers: AnswerHit[] = [];\n const promises: PromiseLike<void>[] = [];\n\n if (target !== \"answers\") {\n promises.push(\n supabase\n .rpc(\"search_questions\", {\n p_user_id: userId,\n p_keywords: keywords ?? null,\n p_embedding: embeddingStr,\n p_vector_threshold: 0.3,\n p_statuses: statuses ?? [\"active\", \"paused\"],\n p_tags: tags ?? null,\n p_date_from: null,\n p_date_to: null,\n p_pinned: pinned ?? null,\n p_limit: limit ?? 10,\n })\n .then(({ data }) => {\n if (data) questions.push(...data);\n })\n );\n }\n\n if (target !== \"questions\") {\n promises.push(\n supabase\n .rpc(\"search_answers\", {\n p_user_id: userId,\n p_keywords: keywords ?? null,\n p_embedding: embeddingStr,\n p_vector_threshold: 0.3,\n p_sources: null,\n p_date_from: null,\n p_date_to: null,\n p_exclude_question_ids: null,\n p_limit: limit ?? 10,\n })\n .then(({ data }) => {\n if (data) answers.push(...data);\n })\n );\n }\n\n await Promise.all(promises);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: formatSearchResult({ questions, answers }),\n },\n ],\n };\n }\n );\n}\n","import { embed } from \"ai\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\n\nconst openai = createOpenAI();\nconst embeddingModel = openai.embedding(\"text-embedding-3-small\");\n\nexport async function generateEmbedding(text: string): Promise<string> {\n const { embedding } = await embed({\n model: embeddingModel,\n value: text,\n });\n return JSON.stringify(embedding);\n}\n","export interface QuestionHit {\n id: string;\n question: string;\n tags: string[];\n importance: number | null;\n similarity: number | null;\n latest_answer: string | null;\n latest_answer_at: string | null;\n updated_at: string | null;\n}\n\nexport interface AnswerHit {\n answer_id: string;\n answer: string;\n answer_description: string | null;\n answer_source: string | null;\n similarity: number | null;\n answered_at: string;\n question_id: string;\n question: string;\n}\n\nexport interface QuestionListItem {\n id: string;\n question: string;\n tags: string[];\n status: string;\n importance: number | null;\n pinned: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport function formatSearchResult(result: {\n questions: QuestionHit[];\n answers: AnswerHit[];\n}): string {\n const parts: string[] = [];\n\n if (result.questions.length > 0) {\n parts.push(`## 質問 (${result.questions.length}件)`);\n for (const q of result.questions) {\n const tags = q.tags.length > 0 ? ` [${q.tags.join(\", \")}]` : \"\";\n const answer = q.latest_answer\n ? `\\n 最新回答: ${q.latest_answer}`\n : \"\";\n parts.push(`- **${q.question}**${tags}${answer}\\n ID: ${q.id}`);\n }\n }\n\n if (result.answers.length > 0) {\n parts.push(`## 回答 (${result.answers.length}件)`);\n for (const a of result.answers) {\n const desc = a.answer_description\n ? `\\n 説明: ${a.answer_description}`\n : \"\";\n parts.push(\n `- **${a.question}**\\n 回答: ${a.answer}${desc}\\n 回答日: ${a.answered_at}`\n );\n }\n }\n\n if (parts.length === 0) {\n return \"検索結果はありません。\";\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nexport function formatQuestionList(questions: QuestionListItem[]): string {\n if (questions.length === 0) {\n return \"質問はありません。\";\n }\n\n const lines: string[] = [`## 質問一覧 (${questions.length}件)`];\n\n for (const q of questions) {\n const tags = q.tags.length > 0 ? ` [${q.tags.join(\", \")}]` : \"\";\n const pinned = q.pinned ? \" 📌\" : \"\";\n const status = q.status !== \"active\" ? ` (${q.status})` : \"\";\n lines.push(\n `- **${q.question}**${tags}${pinned}${status}\\n ID: ${q.id} | 更新: ${q.updated_at}`\n );\n }\n\n return lines.join(\"\\n\\n\");\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase, getUserId } from \"../auth.js\";\n\nexport function registerAnswerQuestionTool(server: McpServer): void {\n server.registerTool(\n \"answer_question\",\n {\n title: \"質問への回答書き込み\",\n description: `ユーザーの質問に対して回答を書き込みます。\nユーザーとの会話で重要な気づきや洞察が生まれた時に使います。\n\n使用前に必ずユーザーの承認を得てください。\n\n【回答のルール】\n- answer は140文字以内で、端的に核心を突く回答にする\n- ユーザー自身の言葉を活かした回答にする\n- description には回答の背景・根拠・詳細な説明を書く\n- question_id は search_user_context や list_questions で取得した ID を使う`,\n inputSchema: z.object({\n question_id: z.string().describe(\"対象の質問 ID\"),\n answer: z.string().max(140).describe(\"回答(140文字以内)\"),\n description: z\n .string()\n .max(300)\n .optional()\n .describe(\"回答の詳細説明(300文字以内)\"),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n },\n async ({ question_id, answer, description }) => {\n const supabase = await getSupabase();\n const userId = await getUserId();\n\n const { data: questionData, error: qError } = await supabase\n .from(\"questions\")\n .select(\"question\")\n .eq(\"id\", question_id)\n .eq(\"user_id\", userId)\n .single();\n\n if (qError || !questionData)\n throw new Error(`質問が見つかりません: ${question_id}`);\n\n const { error: insertError } = await supabase.from(\"answers\").insert({\n question_id,\n user_id: userId,\n question: questionData.question,\n answer,\n description: description ?? null,\n source: \"mcp\",\n });\n\n if (insertError)\n throw new Error(`回答の保存に失敗: ${insertError.message}`);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `回答を保存しました:\\n質問: ${questionData.question}\\n回答: ${answer}`,\n },\n ],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase } from \"../auth.js\";\nimport { formatQuestionList } from \"../format.js\";\n\nexport function registerListQuestionsTool(server: McpServer): void {\n server.registerTool(\n \"list_questions\",\n {\n title: \"質問一覧取得\",\n description: `ユーザーの質問一覧を取得します。ステータスやタグでフィルタ可能。\n質問の ID を確認したいときや、ユーザーがどんな質問を持っているか把握したいときに使います。\nanswer_question で回答を書き込む前に、対象の question_id を確認する用途にも使えます。`,\n inputSchema: z.object({\n status: z\n .array(z.string())\n .optional()\n .default([\"active\", \"paused\"])\n .describe(\"ステータスでフィルタ\"),\n tags: z.array(z.string()).optional().describe(\"タグでフィルタ\"),\n pinned: z.boolean().optional().describe(\"ピン留めされた質問のみ\"),\n limit: z\n .number()\n .min(1)\n .max(50)\n .default(20)\n .describe(\"取得件数上限\"),\n }),\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n },\n async ({ status, tags, pinned, limit }) => {\n const supabase = await getSupabase();\n\n let query = supabase\n .from(\"questions\")\n .select(\n \"id, question, tags, status, importance, pinned, created_at, updated_at\"\n )\n .in(\"status\", status ?? [\"active\", \"paused\"])\n .order(\"updated_at\", { ascending: false })\n .limit(limit ?? 20);\n\n if (tags?.length) {\n query = query.overlaps(\"tags\", tags);\n }\n if (pinned !== undefined) {\n query = query.eq(\"pinned\", pinned);\n }\n\n const { data, error } = await query;\n if (error) throw new Error(`質問取得に失敗: ${error.message}`);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: formatQuestionList(data ?? []),\n },\n ],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase, getUserId } from \"../auth.js\";\n\nconst feedbackCategories = [\n \"bug\",\n \"improvement\",\n \"praise\",\n \"question\",\n \"other\",\n] as const;\n\nexport function registerSaveFeedbackTool(server: McpServer): void {\n server.registerTool(\n \"save_feedback\",\n {\n title: \"フィードバック送信\",\n description: `WellGrow開発チームへフィードバックを送信します。\n\n使用する場面:\n- ユーザーがWellGrowへの改善提案・バグ報告・感想を伝えたいとき\n- WellGrowのツール(search_user_context等)でエラーが発生したとき\n- ユーザーがWellGrowの体験について言及したとき\n\n重要: ユーザーがフィードバックの送信を意図していることを確認してから使用してください。\nツールエラーの報告を除き、ユーザーの承認なく送信しないでください。\n\nカテゴリの選び方:\n- bug: エラーやバグに関するもの\n- improvement: 機能改善の提案やアイデア\n- praise: 良かった点、満足した体験\n- question: WellGrowに関する未解決の質問\n- other: 上記に当てはまらないもの`,\n inputSchema: z.object({\n category: z\n .enum(feedbackCategories)\n .describe(\"フィードバックのカテゴリ\"),\n message: z\n .string()\n .min(1)\n .max(2000)\n .describe(\n \"フィードバックの内容。開発者が状況を理解できるように要約\"\n ),\n user_message: z\n .string()\n .max(500)\n .optional()\n .describe(\"きっかけとなったユーザーの発言(原文を短く引用)\"),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n },\n async ({ category, message, user_message }) => {\n const supabase = await getSupabase();\n const userId = await getUserId();\n\n const context: Record<string, unknown> = {};\n if (user_message) context.user_message = user_message;\n\n const { error } = await supabase.from(\"feedbacks\").insert({\n category,\n message,\n source: \"mcp\",\n user_id: userId,\n page_path: \"mcp\",\n context: Object.keys(context).length > 0 ? context : null,\n });\n\n if (error)\n throw new Error(`フィードバックの保存に失敗: ${error.message}`);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `フィードバックを送信しました(${category})`,\n },\n ],\n };\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSupabase } from \"../auth.js\";\n\nexport function registerQuestionsResource(server: McpServer): void {\n server.registerResource(\n \"active-questions\",\n \"wellgrow://questions/active\",\n {\n title: \"アクティブな質問一覧\",\n description: \"ステータスが active の質問一覧。\",\n mimeType: \"application/json\",\n },\n async (uri) => {\n const supabase = await getSupabase();\n const { data } = await supabase\n .from(\"questions\")\n .select(\"id, question, tags, importance, pinned, updated_at\")\n .eq(\"status\", \"active\")\n .order(\"updated_at\", { ascending: false })\n .limit(50);\n\n return {\n contents: [\n {\n uri: uri.href,\n text: JSON.stringify(data ?? [], null, 2),\n },\n ],\n };\n }\n );\n}\n"],"mappings":";;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACDrC,SAAS,oBAAyC;AAElD,IAAM,uBAAuB;AAC7B,IAAM,4BACJ;AAEF,IAAI,WAAkC;AAE/B,SAAS,iBAAyB;AACvC,SAAO,QAAQ,IAAI,yBAAyB;AAC9C;AAEO,SAAS,qBAA6B;AAC3C,SAAO,QAAQ,IAAI,8BAA8B;AACnD;AAEA,eAAsB,cAAuC;AAC3D,MAAI,UAAU;AACZ,UAAM;AAAA,MACJ,MAAM,EAAE,QAAQ;AAAA,IAClB,IAAI,MAAM,SAAS,KAAK,WAAW;AACnC,QAAI,QAAS,QAAO;AAAA,EACtB;AAEA,aAAW,aAAa,eAAe,GAAG,mBAAmB,GAAG;AAAA,IAC9D,MAAM;AAAA,MACJ,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,EAAE,MAAM,IAAI,MAAM,SAAS,KAAK,mBAAmB;AAAA,IACvD,OAAO,QAAQ,IAAI;AAAA,IACnB,UAAU,QAAQ,IAAI;AAAA,EACxB,CAAC;AAED,MAAI,OAAO;AACT,UAAM,IAAI,MAAM,0BAA0B,MAAM,OAAO,EAAE;AAAA,EAC3D;AAEA,SAAO;AACT;AAEA,eAAsB,YAA6B;AACjD,QAAM,KAAK,MAAM,YAAY;AAC7B,QAAM;AAAA,IACJ,MAAM,EAAE,KAAK;AAAA,EACf,IAAI,MAAM,GAAG,KAAK,QAAQ;AAC1B,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,mBAAmB;AAC9C,SAAO,KAAK;AACd;;;AClDA,SAAS,SAAS;;;ACAlB,SAAS,aAAa;AACtB,SAAS,oBAAoB;AAE7B,IAAM,SAAS,aAAa;AAC5B,IAAM,iBAAiB,OAAO,UAAU,wBAAwB;AAEhE,eAAsB,kBAAkB,MAA+B;AACrE,QAAM,EAAE,UAAU,IAAI,MAAM,MAAM;AAAA,IAChC,OAAO;AAAA,IACP,OAAO;AAAA,EACT,CAAC;AACD,SAAO,KAAK,UAAU,SAAS;AACjC;;;ACqBO,SAAS,mBAAmB,QAGxB;AACT,QAAM,QAAkB,CAAC;AAEzB,MAAI,OAAO,UAAU,SAAS,GAAG;AAC/B,UAAM,KAAK,oBAAU,OAAO,UAAU,MAAM,SAAI;AAChD,eAAW,KAAK,OAAO,WAAW;AAChC,YAAM,OAAO,EAAE,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,MAAM;AAC7D,YAAM,SAAS,EAAE,gBACb;AAAA,8BAAa,EAAE,aAAa,KAC5B;AACJ,YAAM,KAAK,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM;AAAA,QAAW,EAAE,EAAE,EAAE;AAAA,IACjE;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,UAAM,KAAK,oBAAU,OAAO,QAAQ,MAAM,SAAI;AAC9C,eAAW,KAAK,OAAO,SAAS;AAC9B,YAAM,OAAO,EAAE,qBACX;AAAA,kBAAW,EAAE,kBAAkB,KAC/B;AACJ,YAAM;AAAA,QACJ,OAAO,EAAE,QAAQ;AAAA,kBAAa,EAAE,MAAM,GAAG,IAAI;AAAA,wBAAY,EAAE,WAAW;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAEO,SAAS,mBAAmB,WAAuC;AACxE,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB,CAAC,gCAAY,UAAU,MAAM,SAAI;AAEzD,aAAW,KAAK,WAAW;AACzB,UAAM,OAAO,EAAE,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,MAAM;AAC7D,UAAM,SAAS,EAAE,SAAS,eAAQ;AAClC,UAAM,SAAS,EAAE,WAAW,WAAW,KAAK,EAAE,MAAM,MAAM;AAC1D,UAAM;AAAA,MACJ,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,GAAG,MAAM;AAAA,QAAW,EAAE,EAAE,oBAAU,EAAE,UAAU;AAAA,IACnF;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;;;AF5EO,SAAS,0BAA0BA,SAAyB;AACjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkBb,aAAa,EAAE,OAAO;AAAA,QACpB,OAAO,EAAE,OAAO,EAAE,SAAS,oHAAqB;AAAA,QAChD,UAAU,EACP,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,wDAAW;AAAA,QACvB,QAAQ,EACL,KAAK,CAAC,aAAa,WAAW,KAAK,CAAC,EACpC,QAAQ,KAAK,EACb,SAAS,0BAAM;AAAA,QAClB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4CAAS;AAAA,QACvD,UAAU,EACP,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,4GAAiC;AAAA,QAC7C,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,oEAAa;AAAA,QACrD,OAAO,EACJ,OAAO,EACP,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,EAAE,EACV,SAAS,sCAAQ;AAAA,MACtB,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,OAAO,UAAU,QAAQ,MAAM,UAAU,QAAQ,MAAM,MAAM;AACpE,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,SAAS,MAAM,UAAU;AAC/B,YAAM,eAAe,MAAM,kBAAkB,KAAK;AAElD,YAAM,YAA2B,CAAC;AAClC,YAAM,UAAuB,CAAC;AAC9B,YAAM,WAAgC,CAAC;AAEvC,UAAI,WAAW,WAAW;AACxB,iBAAS;AAAA,UACPA,UACG,IAAI,oBAAoB;AAAA,YACvB,WAAW;AAAA,YACX,YAAY,YAAY;AAAA,YACxB,aAAa;AAAA,YACb,oBAAoB;AAAA,YACpB,YAAY,YAAY,CAAC,UAAU,QAAQ;AAAA,YAC3C,QAAQ,QAAQ;AAAA,YAChB,aAAa;AAAA,YACb,WAAW;AAAA,YACX,UAAU,UAAU;AAAA,YACpB,SAAS,SAAS;AAAA,UACpB,CAAC,EACA,KAAK,CAAC,EAAE,KAAK,MAAM;AAClB,gBAAI,KAAM,WAAU,KAAK,GAAG,IAAI;AAAA,UAClC,CAAC;AAAA,QACL;AAAA,MACF;AAEA,UAAI,WAAW,aAAa;AAC1B,iBAAS;AAAA,UACPA,UACG,IAAI,kBAAkB;AAAA,YACrB,WAAW;AAAA,YACX,YAAY,YAAY;AAAA,YACxB,aAAa;AAAA,YACb,oBAAoB;AAAA,YACpB,WAAW;AAAA,YACX,aAAa;AAAA,YACb,WAAW;AAAA,YACX,wBAAwB;AAAA,YACxB,SAAS,SAAS;AAAA,UACpB,CAAC,EACA,KAAK,CAAC,EAAE,KAAK,MAAM;AAClB,gBAAI,KAAM,SAAQ,KAAK,GAAG,IAAI;AAAA,UAChC,CAAC;AAAA,QACL;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,QAAQ;AAE1B,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,mBAAmB,EAAE,WAAW,QAAQ,CAAC;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AG3HA,SAAS,KAAAC,UAAS;AAIX,SAAS,2BAA2BC,SAAyB;AAClE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUb,aAAaC,GAAE,OAAO;AAAA,QACpB,aAAaA,GAAE,OAAO,EAAE,SAAS,mCAAU;AAAA,QAC3C,QAAQA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,qDAAa;AAAA,QAClD,aAAaA,GACV,OAAO,EACP,IAAI,GAAG,EACP,SAAS,EACT,SAAS,mFAAkB;AAAA,MAChC,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,aAAa,QAAQ,YAAY,MAAM;AAC9C,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,SAAS,MAAM,UAAU;AAE/B,YAAM,EAAE,MAAM,cAAc,OAAO,OAAO,IAAI,MAAMA,UACjD,KAAK,WAAW,EAChB,OAAO,UAAU,EACjB,GAAG,MAAM,WAAW,EACpB,GAAG,WAAW,MAAM,EACpB,OAAO;AAEV,UAAI,UAAU,CAAC;AACb,cAAM,IAAI,MAAM,iEAAe,WAAW,EAAE;AAE9C,YAAM,EAAE,OAAO,YAAY,IAAI,MAAMA,UAAS,KAAK,SAAS,EAAE,OAAO;AAAA,QACnE;AAAA,QACA,SAAS;AAAA,QACT,UAAU,aAAa;AAAA,QACvB;AAAA,QACA,aAAa,eAAe;AAAA,QAC5B,QAAQ;AAAA,MACV,CAAC;AAED,UAAI;AACF,cAAM,IAAI,MAAM,qDAAa,YAAY,OAAO,EAAE;AAEpD,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,gBAAmB,aAAa,QAAQ;AAAA,gBAAS,MAAM;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACtEA,SAAS,KAAAC,UAAS;AAKX,SAAS,0BAA0BC,SAAyB;AACjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA,MAGb,aAAaC,GAAE,OAAO;AAAA,QACpB,QAAQA,GACL,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT,QAAQ,CAAC,UAAU,QAAQ,CAAC,EAC5B,SAAS,8DAAY;AAAA,QACxB,MAAMA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4CAAS;AAAA,QACvD,QAAQA,GAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,oEAAa;AAAA,QACrD,OAAOA,GACJ,OAAO,EACP,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,EAAE,EACV,SAAS,sCAAQ;AAAA,MACtB,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,QAAQ,MAAM,QAAQ,MAAM,MAAM;AACzC,YAAMC,YAAW,MAAM,YAAY;AAEnC,UAAI,QAAQA,UACT,KAAK,WAAW,EAChB;AAAA,QACC;AAAA,MACF,EACC,GAAG,UAAU,UAAU,CAAC,UAAU,QAAQ,CAAC,EAC3C,MAAM,cAAc,EAAE,WAAW,MAAM,CAAC,EACxC,MAAM,SAAS,EAAE;AAEpB,UAAI,MAAM,QAAQ;AAChB,gBAAQ,MAAM,SAAS,QAAQ,IAAI;AAAA,MACrC;AACA,UAAI,WAAW,QAAW;AACxB,gBAAQ,MAAM,GAAG,UAAU,MAAM;AAAA,MACnC;AAEA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM;AAC9B,UAAI,MAAO,OAAM,IAAI,MAAM,+CAAY,MAAM,OAAO,EAAE;AAEtD,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,mBAAmB,QAAQ,CAAC,CAAC;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACjEA,SAAS,KAAAC,UAAS;AAIlB,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,yBAAyBC,SAAyB;AAChE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBb,aAAaC,GAAE,OAAO;AAAA,QACpB,UAAUA,GACP,KAAK,kBAAkB,EACvB,SAAS,0EAAc;AAAA,QAC1B,SAASA,GACN,OAAO,EACP,IAAI,CAAC,EACL,IAAI,GAAI,EACR;AAAA,UACC;AAAA,QACF;AAAA,QACF,cAAcA,GACX,OAAO,EACP,IAAI,GAAG,EACP,SAAS,EACT,SAAS,kJAA0B;AAAA,MACxC,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,IACA,OAAO,EAAE,UAAU,SAAS,aAAa,MAAM;AAC7C,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,SAAS,MAAM,UAAU;AAE/B,YAAM,UAAmC,CAAC;AAC1C,UAAI,aAAc,SAAQ,eAAe;AAEzC,YAAM,EAAE,MAAM,IAAI,MAAMA,UAAS,KAAK,WAAW,EAAE,OAAO;AAAA,QACxD;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,WAAW;AAAA,QACX,SAAS,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AAAA,MACvD,CAAC;AAED,UAAI;AACF,cAAM,IAAI,MAAM,mFAAkB,MAAM,OAAO,EAAE;AAEnD,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,6FAAkB,QAAQ;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AClFO,SAAS,0BAA0BC,SAAyB;AACjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AACb,YAAMC,YAAW,MAAM,YAAY;AACnC,YAAM,EAAE,KAAK,IAAI,MAAMA,UACpB,KAAK,WAAW,EAChB,OAAO,oDAAoD,EAC3D,GAAG,UAAU,QAAQ,EACrB,MAAM,cAAc,EAAE,WAAW,MAAM,CAAC,EACxC,MAAM,EAAE;AAEX,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,KAAK,IAAI;AAAA,YACT,MAAM,KAAK,UAAU,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ARtBA,IAAM,WAAW,CAAC,kBAAkB,qBAAqB,gBAAgB;AAEzE,WAAW,OAAO,UAAU;AAC1B,MAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,YAAQ,MAAM,UAAU,GAAG,cAAc;AACzC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,IAAI;AACF,QAAM,YAAY;AAClB,UAAQ,MAAM,4BAA4B;AAC5C,SAAS,OAAO;AACd,UAAQ;AAAA,IACN;AAAA,IACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,EAC3C;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,IAAI;AAAA,EACjB,EAAE,MAAM,YAAY,SAAS,QAAQ;AAAA,EACrC;AAAA,IACE,cAAc;AAAA;AAAA;AAAA,EAGhB;AACF;AAEA,0BAA0B,MAAM;AAChC,2BAA2B,MAAM;AACjC,0BAA0B,MAAM;AAChC,yBAAyB,MAAM;AAC/B,0BAA0B,MAAM;AAEhC,IAAM,YAAY,IAAI,qBAAqB;AAC3C,MAAM,OAAO,QAAQ,SAAS;AAC9B,QAAQ,MAAM,sCAAsC;","names":["server","supabase","z","server","z","supabase","z","server","z","supabase","z","server","z","supabase","server","supabase"]}
|