-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.js
More file actions
294 lines (288 loc) · 17.3 KB
/
Copy pathschema.js
File metadata and controls
294 lines (288 loc) · 17.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// Schema for the OpenAB config wizard.
// Derived from openabdev/openab config.toml.example.
// Field types: string | secret | bool | tristate | enum | number | list
// secret -> rendered in TOML as "${ENV_VAR}"; the actual value goes in the
// deployment secret artifact (as a placeholder), never typed here.
// list -> comma-separated string values
// Labels/help are human-facing questions, bilingual: { en, zh }.
// Enum options are { value, label: {en, zh} }.
const SCHEMA = {
platforms: [
{
id: "discord",
label: "Discord",
fields: [
{ key: "bot_token", type: "secret", env: "DISCORD_BOT_TOKEN", required: true,
label: { en: "Bot token", zh: "Bot 權杖" },
help: { en: "From the Discord Developer Portal. Never typed here — delivered as an environment variable.",
zh: "來自 Discord Developer Portal。不會在此輸入 — 以環境變數方式提供。" } },
{ key: "allowed_channels", type: "list",
label: { en: "Which channels may this bot speak in?", zh: "這個 bot 可以在哪些頻道發言?" },
help: { en: "Discord channel IDs, comma-separated. Leave empty to allow every channel.",
zh: "Discord 頻道 ID,以逗號分隔。留空 = 允許所有頻道。" } },
{ key: "allowed_users", type: "list",
label: { en: "Which users should this bot trust?", zh: "這個 bot 應該信任哪些使用者?" },
help: { en: "Discord user IDs, comma-separated. Leave empty to trust everyone.",
zh: "Discord 使用者 ID,以逗號分隔。留空 = 信任所有人。" } },
{ key: "allow_bot_messages", type: "enum", default: "off",
label: { en: "Should it listen to other bots?", zh: "要理會其他 bot 的訊息嗎?" },
options: [
{ value: "off", label: { en: "No — ignore all bots", zh: "不 — 忽略所有 bot" } },
{ value: "mentions", label: { en: "Only when they @mention it (best for multi-agent)", zh: "只在被 @提及 時(多代理協作建議)" } },
{ value: "all", label: { en: "Yes — listen to every bot message", zh: "是 — 接收所有 bot 訊息" } },
] },
{ key: "trusted_bot_ids", type: "list",
label: { en: "Which specific bots does it trust?", zh: "信任哪些特定的 bot?" },
help: { en: "Bot user IDs. Leave empty to trust any bot (per the setting above).",
zh: "Bot 的使用者 ID。留空 = 信任任何 bot(依上方設定)。" } },
{ key: "allowed_role_ids", type: "list",
label: { en: "Which roles can summon it?", zh: "哪些身分組可以呼叫它?" },
help: { en: "Members with these role IDs trigger the bot just like an @mention. Careful: bots sharing a role all respond at once.",
zh: "擁有這些身分組的成員可像 @提及 一樣觸發 bot。注意:共用同一身分組的多個 bot 會同時回應。" } },
{ key: "allow_user_messages", type: "enum", default: "multibot-mentions",
label: { en: "When should it reply without an @mention?", zh: "什麼情況下不需 @提及 也會回覆?" },
options: [
{ value: "multibot-mentions", label: { en: "In its own threads — until another bot joins, then require @mention", zh: "在自己的討論串中 — 有其他 bot 加入後需 @提及" } },
{ value: "involved", label: { en: "In any thread it owns or has participated in", zh: "在它建立或參與過的任何討論串" } },
{ value: "mentions", label: { en: "Never — always require an @mention", zh: "永不 — 一律需要 @提及" } },
] },
{ key: "allow_dm", type: "bool", default: false,
label: { en: "Reply to direct messages?", zh: "回覆私訊(DM)嗎?" },
help: { en: "The trusted-users list above still applies in DMs.",
zh: "上方的信任使用者清單在私訊中仍然有效。" } },
],
},
{
id: "slack",
label: "Slack",
fields: [
{ key: "bot_token", type: "secret", env: "SLACK_BOT_TOKEN", required: true,
label: { en: "Bot token", zh: "Bot 權杖" },
help: { en: "Bot User OAuth Token (xoxb-...)", zh: "Bot User OAuth Token(xoxb-...)" } },
{ key: "app_token", type: "secret", env: "SLACK_APP_TOKEN", required: true,
label: { en: "App token", zh: "App 權杖" },
help: { en: "App-Level Token (xapp-...) for Socket Mode", zh: "Socket Mode 用的 App-Level Token(xapp-...)" } },
{ key: "allowed_channels", type: "list",
label: { en: "Which channels may this bot speak in?", zh: "這個 bot 可以在哪些頻道發言?" },
help: { en: "Slack channel IDs (C…), comma-separated. Leave empty to allow every channel.",
zh: "Slack 頻道 ID(C…),以逗號分隔。留空 = 允許所有頻道。" } },
{ key: "allowed_users", type: "list",
label: { en: "Which users should this bot trust?", zh: "這個 bot 應該信任哪些使用者?" },
help: { en: "Slack user IDs (U…), comma-separated. Leave empty to trust everyone.",
zh: "Slack 使用者 ID(U…),以逗號分隔。留空 = 信任所有人。" } },
{ key: "allow_bot_messages", type: "enum", default: "off",
label: { en: "Should it listen to other bots?", zh: "要理會其他 bot 的訊息嗎?" },
options: [
{ value: "off", label: { en: "No — ignore all bots", zh: "不 — 忽略所有 bot" } },
{ value: "mentions", label: { en: "Only when they @mention it", zh: "只在被 @提及 時" } },
{ value: "all", label: { en: "Yes — listen to every bot message", zh: "是 — 接收所有 bot 訊息" } },
] },
{ key: "allow_user_messages", type: "enum", default: "multibot-mentions",
label: { en: "When should it reply without an @mention?", zh: "什麼情況下不需 @提及 也會回覆?" },
options: [
{ value: "multibot-mentions", label: { en: "In its own threads — until another bot joins, then require @mention", zh: "在自己的討論串中 — 有其他 bot 加入後需 @提及" } },
{ value: "involved", label: { en: "In any thread it has participated in", zh: "在它參與過的任何討論串" } },
{ value: "mentions", label: { en: "Never — always require an @mention", zh: "永不 — 一律需要 @提及" } },
] },
{ key: "max_bot_turns", type: "number", default: 100,
label: { en: "How many bot-to-bot turns before a human must step in?", zh: "bot 之間最多連續對話幾輪(需人類介入重置)?" },
help: { en: "Soft cap on consecutive bot turns per thread; a human message resets it.",
zh: "每個討論串連續 bot 回合的軟上限;人類訊息會重置計數。" } },
{ key: "assistant_mode", type: "bool", default: true,
label: { en: "Is this an AI Slack app (native streaming)?", zh: "這是 AI Slack app(原生串流)嗎?" },
help: { en: "Requires the assistant:write scope. Turn off for classic apps to use emoji reactions instead.",
zh: "需要 assistant:write scope。傳統 app 請關閉,改用 emoji 反應。" } },
{ key: "streaming", type: "bool", default: true,
label: { en: "Stream replies live as they're written?", zh: "即時串流顯示回覆內容嗎?" },
help: { en: "Off = post one final message. Useful in multi-agent threads.",
zh: "關閉 = 只發送最終訊息。適合多代理討論串。" } },
],
},
{
id: "telegram",
label: "Telegram",
fields: [
{ key: "bot_token", type: "secret", env: "TELEGRAM_BOT_TOKEN", required: true,
label: { en: "Bot token", zh: "Bot 權杖" },
help: { en: "From @BotFather", zh: "來自 @BotFather" } },
{ key: "secret_token", type: "secret", env: "TELEGRAM_SECRET_TOKEN",
label: { en: "Webhook secret token", zh: "Webhook 密鑰" },
help: { en: "Optional but recommended — lets the bot verify webhooks really come from Telegram.",
zh: "選用但建議 — 讓 bot 驗證 webhook 確實來自 Telegram。" } },
{ key: "trusted_source_only", type: "bool", default: false,
label: { en: "Only accept webhooks from Telegram's own IP ranges?", zh: "只接受來自 Telegram 官方 IP 範圍的 webhook?" } },
{ key: "rich_messages", type: "bool", default: true,
label: { en: "Use rich message rendering?", zh: "使用 Rich Message 渲染嗎?" } },
{ key: "webhook_path", type: "string", default: "/webhook/telegram",
label: { en: "Webhook path", zh: "Webhook 路徑" } },
],
},
{
id: "line",
label: "LINE",
fields: [
{ key: "channel_secret", type: "secret", env: "LINE_CHANNEL_SECRET", required: true,
label: { en: "Channel secret", zh: "Channel secret" },
help: { en: "Used to verify webhook signatures (HMAC).", zh: "用於驗證 webhook 簽章(HMAC)。" } },
{ key: "channel_access_token", type: "secret", env: "LINE_CHANNEL_ACCESS_TOKEN", required: true,
label: { en: "Channel access token", zh: "Channel access token" },
help: { en: "Used to call the Reply/Push API.", zh: "用於呼叫 Reply/Push API。" } },
{ key: "webhook_path", type: "string", default: "/webhook/line",
label: { en: "Webhook path", zh: "Webhook 路徑" } },
{ key: "allow_all_users", type: "bool", default: false,
label: { en: "Trust every LINE user?", zh: "信任所有 LINE 使用者嗎?" },
help: { en: "Off (recommended) = deny everyone except the users listed below.",
zh: "關閉(建議)= 只允許下方列出的使用者。" } },
{ key: "allowed_users", type: "list",
label: { en: "Which LINE users should this bot trust?", zh: "這個 bot 應該信任哪些 LINE 使用者?" },
help: { en: "LINE user IDs (U…, 33 chars), comma-separated.",
zh: "LINE 使用者 ID(U…,33 字元),以逗號分隔。" } },
],
},
],
// Feature sections — same shape as platforms, but emit `enabled = true`
// and don't count toward the "at least one adapter" requirement.
features: [
{
id: "stt",
feature: true,
emitEnabled: true,
label: { en: "Voice transcription (STT)", zh: "語音轉文字(STT)" },
fields: [
{ key: "api_key", type: "secret", env: "STT_API_KEY", required: true,
label: { en: "STT API key", zh: "STT API 金鑰" },
help: { en: "Groq or any OpenAI-compatible transcription endpoint.",
zh: "Groq 或任何 OpenAI 相容的語音轉文字服務。" } },
{ key: "model", type: "string", default: "whisper-large-v3-turbo",
label: { en: "Which transcription model?", zh: "使用哪個轉錄模型?" } },
{ key: "base_url", type: "string", default: "https://api.groq.com/openai/v1",
label: { en: "API base URL", zh: "API 基礎網址" } },
],
},
],
// Agent backend presets (from config.toml.example)
agents: [
{ id: "default", label: { en: "Auto-detect from docker image", zh: "從 Docker 映像自動偵測" },
command: "", args: [], working_dir: "" },
{ id: "kiro-cli", label: "Kiro CLI", command: "kiro-cli",
args: ["acp", "--trust-all-tools"], working_dir: "/home/agent" },
{ id: "claude", label: "Claude Code", command: "claude-agent-acp",
args: [], working_dir: "/home/node",
note: "Auth: kubectl exec -it <pod> -- claude auth login" },
{ id: "codex", label: "Codex", command: "codex-acp",
args: [], working_dir: "/home/node",
envKeys: ["OPENAI_API_KEY"] },
{ id: "gemini", label: "Gemini", command: "gemini",
args: ["--acp"], working_dir: "/home/node",
envKeys: ["GEMINI_API_KEY"] },
{ id: "copilot", label: "GitHub Copilot", command: "copilot",
args: ["--acp", "--stdio"], working_dir: "/home/node",
note: "Auth: kubectl exec -it <pod> -- gh auth login -p https -w" },
{ id: "opencode", label: "OpenCode", command: "opencode",
args: ["acp"], working_dir: "/home/node",
note: "Run `opencode auth login` once before starting openab." },
{ id: "cursor", label: "Cursor", command: "cursor-agent",
args: ["acp", "--model", "auto", "--workspace", "/home/agent"], working_dir: "/home/agent" },
{ id: "custom", label: { en: "Custom…", zh: "自訂…" }, command: "", args: [], working_dir: "" },
],
pool: [
{ key: "max_sessions", type: "number", default: 10,
label: { en: "How many conversations can run at once?", zh: "最多可同時進行幾個對話?" } },
{ key: "session_ttl_hours", type: "number", default: 24,
label: { en: "How long before an idle conversation expires? (hours)", zh: "閒置對話多久後過期?(小時)" } },
],
deployTargets: [
{ id: "k8s", label: "Kubernetes (Helm)" },
{ id: "docker", label: "Docker" },
{ id: "ecsctl", label: { en: "Amazon ECS (ecsctl)", zh: "Amazon ECS(ecsctl)" } },
],
};
// UI chrome strings
const UI_STRINGS = {
en: {
title: "OpenAB Setup Wizard",
tagline_1: "Configure your bot, preview ",
tagline_2: " live. Runs entirely in your browser — ",
tagline_3: "nothing is transmitted anywhere",
tagline_4: ". Never paste real secrets here; the wizard emits ",
tagline_5: " references only.",
general: "Basics",
botName: "What should we call this bot?",
botNameHelp: "Also the profile name — used to name generated resources (secrets, containers).",
deployTarget: "Where will this bot run?",
agent: "Agent",
agentBackend: "Which coding agent powers this bot?",
command: "Command",
argsLabel: "Args (space-separated)",
workingDir: "Working directory",
pool: "Sessions",
required: "required",
use: "use",
yes: "Yes",
copy: "Copy",
copied: "Copied!",
download: "Download",
secretRefs: "Secret refs",
secretRefsHelp: "Define named secret refs (name = source URI), then drag a name into a 🔒 field below. They land in [secrets.refs] in the config — values never appear anywhere.",
refSchemes: "Sources: aws-sm://<secret-id>#<json-key> · exec://<script> <args>",
noRefs: 'No refs defined yet — e.g. github_token = "aws-sm://oab#GITHUB_TOKEN"',
dropHint: "drag a secret ref here",
dragHint: "Drag into a 🔒 field",
pickerUnset: "— not set —",
clear: "Remove",
edit: "Edit",
add: "Add",
agentEnv: "Environment variables for the agent",
agentEnvHelp: "⚠ Any variable listed here is visible to the agent — a prompt-injected user could trick it into leaking values. Prefer OAuth logins over API keys; use secret refs for anything sensitive.",
addVar: "+ Add variable",
addEntry: "+ Add a new entry",
cancel: "Cancel",
insertRef: "Insert a secret ref",
profileNamePrompt: "New profile name (e.g. the bot's name):",
deleteProfileConfirm: "Delete profile \"{name}\"? This cannot be undone.",
overwriteProfileConfirm: "A profile named \"{name}\" already exists. Overwrite it?",
},
zh: {
title: "OpenAB 設定精靈",
tagline_1: "設定你的 bot,即時預覽 ",
tagline_2: "。完全在瀏覽器中執行 — ",
tagline_3: "不會傳送任何資料",
tagline_4: "。請勿在此貼上真實密鑰;精靈只會產生 ",
tagline_5: " 參照。",
general: "基本設定",
botName: "這個 bot 要叫什麼名字?",
botNameHelp: "同時是設定檔名稱 — 用於命名產生的資源(secrets、容器)。",
deployTarget: "這個 bot 會在哪裡執行?",
agent: "代理",
agentBackend: "由哪個 coding agent 驅動這個 bot?",
command: "指令",
argsLabel: "參數(以空格分隔)",
workingDir: "工作目錄",
pool: "工作階段",
required: "必填",
use: "使用",
yes: "是",
copy: "複製",
copied: "已複製!",
download: "下載",
secretRefs: "密鑰參照",
secretRefsHelp: "定義具名密鑰參照(名稱 = 來源 URI),再將名稱拖曳到下方的 🔒 欄位。它們會寫入設定檔的 [secrets.refs] — 實際密鑰值不會出現在任何地方。",
refSchemes: "來源格式:aws-sm://<secret-id>#<json-key> · exec://<script> <args>",
noRefs: '尚未定義任何參照 — 例如 github_token = "aws-sm://oab#GITHUB_TOKEN"',
dropHint: "將密鑰參照拖曳到這裡",
dragHint: "拖曳到 🔒 欄位",
pickerUnset: "— 未設定 —",
clear: "移除",
edit: "編輯",
add: "新增",
agentEnv: "傳給 agent 的環境變數",
agentEnvHelp: "⚠ 此處列出的變數 agent 都能讀取 — 惡意提示注入可能誘使 agent 洩漏這些值。建議優先使用 OAuth 登入而非 API 金鑰;敏感值請使用密鑰參照。",
addVar: "+ 新增變數",
addEntry: "+ 新增項目",
cancel: "取消",
insertRef: "插入密鑰參照",
profileNamePrompt: "新設定檔名稱(例如 bot 的名字):",
deleteProfileConfirm: "刪除設定檔「{name}」?此操作無法復原。",
overwriteProfileConfirm: "已存在名為「{name}」的設定檔,要覆蓋它嗎?",
},
};