@0xmaxma/claude-gateway 1.7.10 → 1.8.1

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.
Files changed (177) hide show
  1. package/README.md +167 -41
  2. package/dist/agent/builtin-commands.js +2 -2
  3. package/dist/agent/builtin-commands.js.map +1 -1
  4. package/dist/agent/knowledge/config.d.ts.map +1 -1
  5. package/dist/agent/knowledge/config.js +2 -9
  6. package/dist/agent/knowledge/config.js.map +1 -1
  7. package/dist/agent/model-catalog.d.ts +62 -0
  8. package/dist/agent/model-catalog.d.ts.map +1 -0
  9. package/dist/agent/model-catalog.js +304 -0
  10. package/dist/agent/model-catalog.js.map +1 -0
  11. package/dist/agent/runner.d.ts +76 -0
  12. package/dist/agent/runner.d.ts.map +1 -1
  13. package/dist/agent/runner.js +212 -41
  14. package/dist/agent/runner.js.map +1 -1
  15. package/dist/api/cron-router.d.ts +12 -8
  16. package/dist/api/cron-router.d.ts.map +1 -1
  17. package/dist/api/cron-router.js +82 -16
  18. package/dist/api/cron-router.js.map +1 -1
  19. package/dist/api/gateway-router.d.ts +4 -0
  20. package/dist/api/gateway-router.d.ts.map +1 -1
  21. package/dist/api/gateway-router.js +14 -0
  22. package/dist/api/gateway-router.js.map +1 -1
  23. package/dist/api/manifest-sources.d.ts +15 -0
  24. package/dist/api/manifest-sources.d.ts.map +1 -0
  25. package/dist/api/manifest-sources.js +27 -0
  26. package/dist/api/manifest-sources.js.map +1 -0
  27. package/dist/api/meta-router.d.ts +13 -0
  28. package/dist/api/meta-router.d.ts.map +1 -0
  29. package/dist/api/meta-router.js +26 -0
  30. package/dist/api/meta-router.js.map +1 -0
  31. package/dist/api/packages.d.ts.map +1 -1
  32. package/dist/api/packages.js +18 -198
  33. package/dist/api/packages.js.map +1 -1
  34. package/dist/api/route-registry.d.ts +81 -0
  35. package/dist/api/route-registry.d.ts.map +1 -0
  36. package/dist/api/route-registry.js +44 -0
  37. package/dist/api/route-registry.js.map +1 -0
  38. package/dist/api/router.d.ts.map +1 -1
  39. package/dist/api/router.js +21 -3
  40. package/dist/api/router.js.map +1 -1
  41. package/dist/apps/installer.d.ts +73 -5
  42. package/dist/apps/installer.d.ts.map +1 -1
  43. package/dist/apps/installer.js +237 -22
  44. package/dist/apps/installer.js.map +1 -1
  45. package/dist/cli/args.d.ts +25 -0
  46. package/dist/cli/args.d.ts.map +1 -0
  47. package/dist/cli/args.js +55 -0
  48. package/dist/cli/args.js.map +1 -0
  49. package/dist/cli/colors.d.ts +37 -0
  50. package/dist/cli/colors.d.ts.map +1 -0
  51. package/dist/cli/colors.js +63 -0
  52. package/dist/cli/colors.js.map +1 -0
  53. package/dist/cli/command-names.d.ts +98 -0
  54. package/dist/cli/command-names.d.ts.map +1 -0
  55. package/dist/cli/command-names.js +109 -0
  56. package/dist/cli/command-names.js.map +1 -0
  57. package/dist/cli/commands/agents.d.ts +28 -0
  58. package/dist/cli/commands/agents.d.ts.map +1 -0
  59. package/dist/cli/commands/agents.js +321 -0
  60. package/dist/cli/commands/agents.js.map +1 -0
  61. package/dist/cli/commands/channels.d.ts +17 -0
  62. package/dist/cli/commands/channels.d.ts.map +1 -0
  63. package/dist/cli/commands/channels.js +101 -0
  64. package/dist/cli/commands/channels.js.map +1 -0
  65. package/dist/cli/commands/debug-bundle.d.ts +6 -0
  66. package/dist/cli/commands/debug-bundle.d.ts.map +1 -0
  67. package/dist/cli/commands/debug-bundle.js +220 -0
  68. package/dist/cli/commands/debug-bundle.js.map +1 -0
  69. package/dist/cli/commands/doctor.d.ts +3 -0
  70. package/dist/cli/commands/doctor.d.ts.map +1 -0
  71. package/dist/cli/commands/doctor.js +104 -0
  72. package/dist/cli/commands/doctor.js.map +1 -0
  73. package/dist/cli/commands/gateway.d.ts +12 -0
  74. package/dist/cli/commands/gateway.d.ts.map +1 -0
  75. package/dist/cli/commands/gateway.js +145 -0
  76. package/dist/cli/commands/gateway.js.map +1 -0
  77. package/dist/cli/commands/service.d.ts +33 -0
  78. package/dist/cli/commands/service.d.ts.map +1 -0
  79. package/dist/cli/commands/service.js +513 -0
  80. package/dist/cli/commands/service.js.map +1 -0
  81. package/dist/cli/commands/update.d.ts +16 -0
  82. package/dist/cli/commands/update.d.ts.map +1 -0
  83. package/dist/cli/commands/update.js +149 -0
  84. package/dist/cli/commands/update.js.map +1 -0
  85. package/dist/cli/commands.generated.d.ts +4 -0
  86. package/dist/cli/commands.generated.d.ts.map +1 -0
  87. package/dist/cli/commands.generated.js +220 -0
  88. package/dist/cli/commands.generated.js.map +1 -0
  89. package/dist/cli/health.d.ts +31 -0
  90. package/dist/cli/health.d.ts.map +1 -0
  91. package/dist/cli/health.js +49 -0
  92. package/dist/cli/health.js.map +1 -0
  93. package/dist/cli/http-client.d.ts +140 -0
  94. package/dist/cli/http-client.d.ts.map +1 -0
  95. package/dist/cli/http-client.js +332 -0
  96. package/dist/cli/http-client.js.map +1 -0
  97. package/dist/cli/index.d.ts +27 -0
  98. package/dist/cli/index.d.ts.map +1 -0
  99. package/dist/cli/index.js +372 -0
  100. package/dist/cli/index.js.map +1 -0
  101. package/dist/cli/manager.d.ts +64 -0
  102. package/dist/cli/manager.d.ts.map +1 -0
  103. package/dist/cli/manager.js +181 -0
  104. package/dist/cli/manager.js.map +1 -0
  105. package/dist/cli/output.d.ts +49 -0
  106. package/dist/cli/output.d.ts.map +1 -0
  107. package/dist/cli/output.js +101 -0
  108. package/dist/cli/output.js.map +1 -0
  109. package/dist/cli/prompt.d.ts +29 -0
  110. package/dist/cli/prompt.d.ts.map +1 -0
  111. package/dist/cli/prompt.js +154 -0
  112. package/dist/cli/prompt.js.map +1 -0
  113. package/dist/cli/redact.d.ts +3 -0
  114. package/dist/cli/redact.d.ts.map +1 -0
  115. package/dist/cli/redact.js +33 -0
  116. package/dist/cli/redact.js.map +1 -0
  117. package/dist/cli/types.d.ts +22 -0
  118. package/dist/cli/types.d.ts.map +1 -0
  119. package/dist/cli/types.js +4 -0
  120. package/dist/cli/types.js.map +1 -0
  121. package/dist/config/bootstrap.d.ts +33 -0
  122. package/dist/config/bootstrap.d.ts.map +1 -0
  123. package/dist/config/bootstrap.js +117 -0
  124. package/dist/config/bootstrap.js.map +1 -0
  125. package/dist/config/loader.d.ts.map +1 -1
  126. package/dist/config/loader.js +5 -1
  127. package/dist/config/loader.js.map +1 -1
  128. package/dist/config/watcher.d.ts.map +1 -1
  129. package/dist/config/watcher.js +2 -35
  130. package/dist/config/watcher.js.map +1 -1
  131. package/dist/discord/receiver.d.ts +6 -1
  132. package/dist/discord/receiver.d.ts.map +1 -1
  133. package/dist/discord/receiver.js +9 -1
  134. package/dist/discord/receiver.js.map +1 -1
  135. package/dist/entry.d.ts +3 -0
  136. package/dist/entry.d.ts.map +1 -0
  137. package/dist/entry.js +83 -0
  138. package/dist/entry.js.map +1 -0
  139. package/dist/index.js +160 -46
  140. package/dist/index.js.map +1 -1
  141. package/dist/load-dotenv.d.ts +2 -0
  142. package/dist/load-dotenv.d.ts.map +1 -0
  143. package/dist/load-dotenv.js +68 -0
  144. package/dist/load-dotenv.js.map +1 -0
  145. package/dist/packages/registry.d.ts +50 -0
  146. package/dist/packages/registry.d.ts.map +1 -0
  147. package/dist/packages/registry.js +209 -0
  148. package/dist/packages/registry.js.map +1 -0
  149. package/dist/session/process.d.ts +14 -5
  150. package/dist/session/process.d.ts.map +1 -1
  151. package/dist/session/process.js +155 -26
  152. package/dist/session/process.js.map +1 -1
  153. package/dist/shutdown-signals.d.ts +47 -0
  154. package/dist/shutdown-signals.d.ts.map +1 -0
  155. package/dist/shutdown-signals.js +62 -0
  156. package/dist/shutdown-signals.js.map +1 -0
  157. package/dist/telegram/receiver.d.ts +6 -1
  158. package/dist/telegram/receiver.d.ts.map +1 -1
  159. package/dist/telegram/receiver.js +9 -1
  160. package/dist/telegram/receiver.js.map +1 -1
  161. package/dist/utils/orphan-receivers.d.ts +90 -0
  162. package/dist/utils/orphan-receivers.d.ts.map +1 -0
  163. package/dist/utils/orphan-receivers.js +218 -0
  164. package/dist/utils/orphan-receivers.js.map +1 -0
  165. package/dist/utils/paths.d.ts +16 -0
  166. package/dist/utils/paths.d.ts.map +1 -0
  167. package/dist/utils/paths.js +60 -0
  168. package/dist/utils/paths.js.map +1 -0
  169. package/dist/utils/stop-child.d.ts +21 -0
  170. package/dist/utils/stop-child.d.ts.map +1 -0
  171. package/dist/utils/stop-child.js +64 -0
  172. package/dist/utils/stop-child.js.map +1 -0
  173. package/lib/pairing.ts +1 -1
  174. package/mcp/tools/agent/handlers.ts +1 -1
  175. package/mcp/tools/discord/receiver-server.ts +4 -0
  176. package/mcp/tools/telegram/receiver-server.ts +152 -29
  177. package/package.json +6 -4
@@ -878,10 +878,12 @@ const BOT_COMMANDS = [
878
878
  { command: 'help', description: 'What this bot can do' },
879
879
  ]
880
880
 
881
- // Available AI models for /models command. Fallback only — the picker normally
882
- // uses the live list from the gateway (get_models); this is shown if that call
883
- // fails. Keep in sync with DEFAULT_MODELS (src/agent/runner.ts) and
884
- // config.template.json gateway.models.
881
+ // Available AI models for /models command. Last-resort fallback: the picker
882
+ // normally uses get_models, which itself resolves the live catalog and only
883
+ // then falls back to config.json's gateway.models (issue #409). This copy is
884
+ // reached only when the gateway call itself fails, so it is two fallbacks deep
885
+ // and will drift — keep it roughly in step with DEFAULT_MODELS
886
+ // (src/agent/runner.ts) and config.template.json gateway.models.
885
887
  const AVAILABLE_MODELS = [
886
888
  { id: 'claude-fable-5[1m]', label: 'Fable 5 (1M)', alias: 'fable[1m]' },
887
889
  { id: 'claude-opus-5[1m]', label: 'Opus 5 (1M)', alias: 'opus[1m]' },
@@ -1196,6 +1198,62 @@ bot.command('model', async ctx => {
1196
1198
  }
1197
1199
  })
1198
1200
 
1201
+ /** Fetches current model + configured/live model lists. Shared by /models, models:back and models:more so all three agree on fallback behavior. */
1202
+ async function fetchModelMenuData(chatId: string): Promise<{
1203
+ currentModel: string
1204
+ configuredModels: Array<{ id: string; label: string }>
1205
+ liveModels: Array<{ id: string; label: string }>
1206
+ } | null> {
1207
+ if (!CALLBACK_URL_BASE) return null
1208
+ const [modelRes, modelsRes] = await Promise.all([
1209
+ fetch(CALLBACK_URL_BASE + '/command', {
1210
+ method: 'POST',
1211
+ headers: { 'Content-Type': 'application/json' },
1212
+ body: JSON.stringify({ command: 'get_model', chat_id: chatId }),
1213
+ }),
1214
+ fetch(CALLBACK_URL_BASE + '/command', {
1215
+ method: 'POST',
1216
+ headers: { 'Content-Type': 'application/json' },
1217
+ body: JSON.stringify({ command: 'get_models' }),
1218
+ }),
1219
+ ])
1220
+ if (!modelRes.ok || !modelsRes.ok) throw new Error('model request failed')
1221
+ const modelData = (await modelRes.json()) as { model?: string }
1222
+ const modelsData = (await modelsRes.json()) as {
1223
+ models?: unknown
1224
+ configuredModels?: unknown
1225
+ liveModels?: unknown
1226
+ }
1227
+ const currentModel = typeof modelData.model === 'string' ? modelData.model : ''
1228
+ const availableRaw = validModelRows(modelsData.models)
1229
+ const availableModels = availableRaw.length ? availableRaw : validModelRows(AVAILABLE_MODELS)
1230
+ const configuredModels = Array.isArray(modelsData.configuredModels)
1231
+ ? validModelRows(modelsData.configuredModels)
1232
+ : availableModels
1233
+ const liveModels = Array.isArray(modelsData.liveModels)
1234
+ ? validModelRows(modelsData.liveModels)
1235
+ : availableModels.filter(m => !configuredModels.some(c => c.id === m.id))
1236
+ return { currentModel, configuredModels, liveModels }
1237
+ }
1238
+
1239
+ /** Builds the root /models keyboard: one row per configured model, plus "More models..." when live-only models exist. */
1240
+ function buildModelsRootKeyboard(
1241
+ currentModel: string,
1242
+ configuredModels: Array<{ id: string; label: string }>,
1243
+ liveModels: Array<{ id: string; label: string }>,
1244
+ ): InlineKeyboard {
1245
+ const keyboard = new InlineKeyboard()
1246
+ for (const m of configuredModels) {
1247
+ const id = safeModelId(m.id)
1248
+ if (!id) continue
1249
+ const prefix = m.id === currentModel ? '\u2705 ' : ''
1250
+ keyboard.text(`${prefix}${m.label}`, `model:${id}`).row()
1251
+ }
1252
+ if (liveModels.length) keyboard.text('More models...', 'models:more:0').row()
1253
+ keyboard.text('Dismiss', 'models:dismiss')
1254
+ return keyboard
1255
+ }
1256
+
1199
1257
  // /models — show model selection keyboard (receiver mode only)
1200
1258
  bot.command('models', async ctx => {
1201
1259
  if (ctx.chat?.type !== 'private') return
@@ -1204,31 +1262,10 @@ bot.command('models', async ctx => {
1204
1262
  if (!CALLBACK_URL_BASE) return
1205
1263
 
1206
1264
  try {
1207
- const [modelRes, modelsRes] = await Promise.all([
1208
- fetch(CALLBACK_URL_BASE + '/command', {
1209
- method: 'POST',
1210
- headers: { 'Content-Type': 'application/json' },
1211
- body: JSON.stringify({ command: 'get_model', chat_id: String(ctx.chat.id) }),
1212
- }),
1213
- fetch(CALLBACK_URL_BASE + '/command', {
1214
- method: 'POST',
1215
- headers: { 'Content-Type': 'application/json' },
1216
- body: JSON.stringify({ command: 'get_models' }),
1217
- }),
1218
- ])
1219
- const modelData = (await modelRes.json()) as { model?: string }
1220
- const modelsData = (await modelsRes.json()) as { models?: { id: string; label: string }[] }
1221
- const currentModel = modelData.model ?? ''
1222
- const availableModels = modelsData.models ?? AVAILABLE_MODELS
1223
-
1224
- const keyboard = new InlineKeyboard()
1225
- for (const m of availableModels) {
1226
- const prefix = m.id === currentModel ? '\u2705 ' : ''
1227
- keyboard.text(`${prefix}${m.label}`, `model:${m.id}`).row()
1228
- }
1229
- keyboard.text('Dismiss', 'models:dismiss')
1230
-
1231
- await ctx.reply(`Current model: ${currentModel}\nSelect a model:`, {
1265
+ const menu = await fetchModelMenuData(String(ctx.chat.id))
1266
+ if (!menu) return
1267
+ const keyboard = buildModelsRootKeyboard(menu.currentModel, menu.configuredModels, menu.liveModels)
1268
+ await ctx.reply(`Current model: ${menu.currentModel}\nSelect a model:`, {
1232
1269
  reply_markup: keyboard,
1233
1270
  })
1234
1271
  } catch (err) {
@@ -1401,6 +1438,26 @@ function isCallbackAuthorized(ctx: Context): boolean {
1401
1438
  return access.allowFrom.includes(String(ctx.from?.id ?? ''))
1402
1439
  }
1403
1440
 
1441
+ /** Telegram callback_data is capped at 64 UTF-8 bytes; reject untrusted ids safely. */
1442
+ function safeModelId(value: unknown): string | null {
1443
+ if (typeof value !== 'string') return null
1444
+ const id = value.trim()
1445
+ return id && Buffer.byteLength(`model:${id}`, 'utf8') <= 64 ? id : null
1446
+ }
1447
+
1448
+ function validModelRows(value: unknown): Array<{ id: string; label: string }> {
1449
+ if (!Array.isArray(value)) return []
1450
+ const rows: Array<{ id: string; label: string }> = []
1451
+ for (const item of value) {
1452
+ if (typeof item !== 'object' || item === null) continue
1453
+ const row = item as { id?: unknown; model_id?: unknown; label?: unknown; display_name?: unknown; name?: unknown }
1454
+ const id = safeModelId(row.id) ?? safeModelId(row.model_id)
1455
+ const labelValue = [row.label, row.display_name, row.name].find(v => typeof v === 'string' && v.trim())
1456
+ if (id && typeof labelValue === 'string') rows.push({ id, label: labelValue.trim() })
1457
+ }
1458
+ return rows
1459
+ }
1460
+
1404
1461
  // Inline-button handler for permission requests. Callback data is
1405
1462
  // `perm:allow:<id>`, `perm:deny:<id>`, or `perm:more:<id>`.
1406
1463
  // Security mirrors the text-reply path: allowFrom must contain the sender.
@@ -1487,6 +1544,72 @@ bot.on('callback_query:data', async ctx => {
1487
1544
  return
1488
1545
  }
1489
1546
 
1547
+ const moreMatch = /^models:more:(\d+)$/.exec(data)
1548
+ if (moreMatch) {
1549
+ if (!isCallbackAuthorized(ctx)) {
1550
+ await ctx.answerCallbackQuery({ text: 'Not authorized.' }).catch(() => {})
1551
+ return
1552
+ }
1553
+ if (!CALLBACK_URL_BASE) {
1554
+ await ctx.answerCallbackQuery({ text: 'Not available.' }).catch(() => {})
1555
+ return
1556
+ }
1557
+ try {
1558
+ const chatId = String(ctx.callbackQuery.message?.chat.id ?? ctx.from.id)
1559
+ const menu = await fetchModelMenuData(chatId)
1560
+ if (!menu) {
1561
+ await ctx.answerCallbackQuery({ text: 'Not available.' }).catch(() => {})
1562
+ return
1563
+ }
1564
+ const { currentModel, liveModels } = menu
1565
+ const page = Number(moreMatch[1])
1566
+ const pageSize = 16
1567
+ const totalPages = Math.max(1, Math.ceil(liveModels.length / pageSize))
1568
+ const safePage = Math.min(page, totalPages - 1)
1569
+ const keyboard = new InlineKeyboard()
1570
+ for (const [index, m] of liveModels.slice(safePage * pageSize, (safePage + 1) * pageSize).entries()) {
1571
+ const modelCallback = safeModelId(m.id)
1572
+ if (!modelCallback) continue
1573
+ keyboard.text(`${m.id === currentModel ? '\u2705 ' : ''}${m.id}`, `model:${modelCallback}`)
1574
+ if (index % 2 === 1) keyboard.row()
1575
+ }
1576
+ if (liveModels.slice(safePage * pageSize, (safePage + 1) * pageSize).length % 2 === 1) keyboard.row()
1577
+ keyboard.text('«', safePage === 0 ? 'models:back' : `models:more:${safePage - 1}`)
1578
+ if (safePage < totalPages - 1) keyboard.text('»', `models:more:${safePage + 1}`)
1579
+ keyboard.row().text('Dismiss', 'models:dismiss')
1580
+ await ctx.answerCallbackQuery().catch(() => {})
1581
+ await ctx.editMessageText(`More models (live) — page ${safePage + 1}/${totalPages}:`, { reply_markup: keyboard })
1582
+ } catch {
1583
+ await ctx.answerCallbackQuery({ text: 'Request failed' }).catch(() => {})
1584
+ }
1585
+ return
1586
+ }
1587
+
1588
+ if (data === 'models:back') {
1589
+ if (!isCallbackAuthorized(ctx)) {
1590
+ await ctx.answerCallbackQuery({ text: 'Not authorized.' }).catch(() => {})
1591
+ return
1592
+ }
1593
+ if (!CALLBACK_URL_BASE) {
1594
+ await ctx.answerCallbackQuery({ text: 'Not available.' }).catch(() => {})
1595
+ return
1596
+ }
1597
+ try {
1598
+ const chatId = String(ctx.callbackQuery.message?.chat.id ?? ctx.from.id)
1599
+ const menu = await fetchModelMenuData(chatId)
1600
+ if (!menu) {
1601
+ await ctx.answerCallbackQuery({ text: 'Not available.' }).catch(() => {})
1602
+ return
1603
+ }
1604
+ const keyboard = buildModelsRootKeyboard(menu.currentModel, menu.configuredModels, menu.liveModels)
1605
+ await ctx.answerCallbackQuery().catch(() => {})
1606
+ await ctx.editMessageText(`Current model: ${menu.currentModel}\nSelect a model:`, { reply_markup: keyboard })
1607
+ } catch {
1608
+ await ctx.answerCallbackQuery({ text: 'Request failed' }).catch(() => {})
1609
+ }
1610
+ return
1611
+ }
1612
+
1490
1613
  // Handle model selection callback: model:<model_id>
1491
1614
  const modelMatch = /^model:(.+)$/.exec(data)
1492
1615
  if (modelMatch) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xmaxma/claude-gateway",
3
- "version": "1.7.10",
3
+ "version": "1.8.1",
4
4
  "description": "Multi-agent gateway for Claude",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "main": "dist/index.js",
10
10
  "bin": {
11
- "claude-gateway": "./dist/index.js"
11
+ "claude-gateway": "./dist/entry.js"
12
12
  },
13
13
  "engines": {
14
14
  "node": ">=22"
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "scripts": {
30
30
  "build": "tsc",
31
- "start": "node --no-warnings=ExperimentalWarning --env-file-if-exists=.env dist/index.js",
31
+ "start": "node --no-warnings=ExperimentalWarning --env-file-if-exists=.env dist/entry.js gateway start",
32
32
  "postinstall": "if command -v bun >/dev/null 2>&1; then bun install --cwd mcp; else echo 'Warning: bun not found. Run `cd mcp && bun install` manually to enable MCP tools.'; fi",
33
33
  "pretest": "npm run build",
34
34
  "test": "NODE_OPTIONS=--max-old-space-size=2560 jest",
@@ -40,7 +40,9 @@
40
40
  "test:manual": "jest --testPathPattern=phase-manual --testTimeout=15000",
41
41
  "integration:hb": "jest --testPathPattern=heartbeat-e2e --testTimeout=15000",
42
42
  "integration:cs": "jest --testPathPattern=character-system --testTimeout=15000",
43
- "typecheck": "tsc --noEmit"
43
+ "typecheck": "tsc --noEmit",
44
+ "gen-cli": "ts-node scripts/gen-cli.ts",
45
+ "gen-cli:check": "ts-node scripts/gen-cli.ts --check"
44
46
  },
45
47
  "dependencies": {
46
48
  "@line/bot-sdk": "^11.0.2",