responses-proxy 0.1.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.
Files changed (161) hide show
  1. package/README.md +56 -0
  2. package/cli.js +118 -0
  3. package/dist/anthropic-messages.js +383 -0
  4. package/dist/anthropic-messages.test.js +209 -0
  5. package/dist/audit-log.js +138 -0
  6. package/dist/audit-log.test.js +480 -0
  7. package/dist/billing-expiration.js +70 -0
  8. package/dist/billing-expiration.test.js +114 -0
  9. package/dist/billing.js +716 -0
  10. package/dist/billing.test.js +228 -0
  11. package/dist/chatgpt-oauth-store.js +240 -0
  12. package/dist/chatgpt-oauth-store.test.js +88 -0
  13. package/dist/chatgpt-oauth.js +118 -0
  14. package/dist/chatgpt-oauth.test.js +63 -0
  15. package/dist/chatgpt-provider-auth.js +60 -0
  16. package/dist/chatgpt-provider-auth.test.js +101 -0
  17. package/dist/client/app-icon.svg +17 -0
  18. package/dist/client/assets/index-C7Vvhst8.js +14 -0
  19. package/dist/client/assets/index-DpqgYK3L.css +1 -0
  20. package/dist/client/favicon.svg +17 -0
  21. package/dist/client/index.html +31 -0
  22. package/dist/client-config-apply.js +345 -0
  23. package/dist/client-config-apply.test.js +185 -0
  24. package/dist/client-token-limits.js +111 -0
  25. package/dist/client-token-limits.test.js +129 -0
  26. package/dist/codex-config.js +47 -0
  27. package/dist/codex-setup.js +87 -0
  28. package/dist/codex-setup.test.js +30 -0
  29. package/dist/config.js +314 -0
  30. package/dist/cost-analytics.js +31 -0
  31. package/dist/cost-analytics.test.js +38 -0
  32. package/dist/customer-key-access.js +126 -0
  33. package/dist/customer-key-access.test.js +178 -0
  34. package/dist/customer-keys.js +209 -0
  35. package/dist/customer-keys.test.js +68 -0
  36. package/dist/customer-usage.js +18 -0
  37. package/dist/customer-usage.test.js +55 -0
  38. package/dist/dashboard-auth.js +318 -0
  39. package/dist/dashboard-auth.test.js +133 -0
  40. package/dist/dashboard-serving.test.js +235 -0
  41. package/dist/error-response.js +174 -0
  42. package/dist/error-response.test.js +88 -0
  43. package/dist/forward.js +357 -0
  44. package/dist/health-websocket-manager.js +174 -0
  45. package/dist/http-rate-limit.js +36 -0
  46. package/dist/http-rate-limit.test.js +62 -0
  47. package/dist/kiro-auth.js +136 -0
  48. package/dist/kiro-auth.test.js +234 -0
  49. package/dist/kiro-codewhisperer.js +646 -0
  50. package/dist/kiro-codewhisperer.test.js +219 -0
  51. package/dist/kiro-device-login.js +338 -0
  52. package/dist/kiro-eventstream.js +219 -0
  53. package/dist/kiro-eventstream.test.js +79 -0
  54. package/dist/kiro-forward.js +401 -0
  55. package/dist/kiro-import-cli.js +69 -0
  56. package/dist/kiro-import.js +94 -0
  57. package/dist/kiro-import.test.js +125 -0
  58. package/dist/kiro-token-store.js +196 -0
  59. package/dist/kiro-token-store.test.js +207 -0
  60. package/dist/krouter-usage.js +243 -0
  61. package/dist/model-combo-repository.js +147 -0
  62. package/dist/model-routing.js +69 -0
  63. package/dist/model-routing.test.js +41 -0
  64. package/dist/normalize-request.js +531 -0
  65. package/dist/normalize-request.test.js +277 -0
  66. package/dist/omv-public-firewall.test.js +11 -0
  67. package/dist/package.json +17 -0
  68. package/dist/prompt-cache-state.js +146 -0
  69. package/dist/prompt-cache-state.test.js +71 -0
  70. package/dist/prompt-cache.js +229 -0
  71. package/dist/provider-health-service.js +404 -0
  72. package/dist/provider-request-parameters.js +107 -0
  73. package/dist/provider-request-parameters.test.js +26 -0
  74. package/dist/provider-routing.js +114 -0
  75. package/dist/provider-routing.test.js +64 -0
  76. package/dist/provider-usage.js +314 -0
  77. package/dist/request-timeout-policy.js +61 -0
  78. package/dist/request-timeout-policy.test.js +40 -0
  79. package/dist/response-cache.js +69 -0
  80. package/dist/response-cache.test.js +28 -0
  81. package/dist/routing-combo-repository.js +300 -0
  82. package/dist/routing-engine.js +377 -0
  83. package/dist/routing-integration.js +155 -0
  84. package/dist/routing-simulation-engine.js +326 -0
  85. package/dist/rtk-layer.js +483 -0
  86. package/dist/rtk-layer.test.js +198 -0
  87. package/dist/runtime-provider-repository.js +1742 -0
  88. package/dist/runtime-provider-repository.test.js +1177 -0
  89. package/dist/schema.js +118 -0
  90. package/dist/schema.test.js +16 -0
  91. package/dist/sepay-webhook.js +87 -0
  92. package/dist/sepay-webhook.test.js +142 -0
  93. package/dist/server-body-limit.test.js +35 -0
  94. package/dist/server-client-token-limits.test.js +161 -0
  95. package/dist/server-codex-config-setup.test.js +76 -0
  96. package/dist/server-http-rate-limit.test.js +80 -0
  97. package/dist/server-response-cache.test.js +105 -0
  98. package/dist/server-routes-alias.test.js +39 -0
  99. package/dist/server-sepay-webhook-security.test.js +59 -0
  100. package/dist/server.js +5906 -0
  101. package/dist/session-log.js +178 -0
  102. package/dist/tailnet-funnel-script.test.js +33 -0
  103. package/dist/telegram-bot/actions.js +118 -0
  104. package/dist/telegram-bot/admin-actions.js +103 -0
  105. package/dist/telegram-bot/auth.js +46 -0
  106. package/dist/telegram-bot/auth.test.js +1 -0
  107. package/dist/telegram-bot/bot-identity-repository.js +189 -0
  108. package/dist/telegram-bot/bot-identity-repository.test.js +78 -0
  109. package/dist/telegram-bot/callbacks.js +30 -0
  110. package/dist/telegram-bot/codex-config-delivery.js +38 -0
  111. package/dist/telegram-bot/codex-config-delivery.test.js +75 -0
  112. package/dist/telegram-bot/commands/accounts.js +140 -0
  113. package/dist/telegram-bot/commands/apikey.js +737 -0
  114. package/dist/telegram-bot/commands/apply.js +265 -0
  115. package/dist/telegram-bot/commands/clients.js +13 -0
  116. package/dist/telegram-bot/commands/customer-billing.test.js +271 -0
  117. package/dist/telegram-bot/commands/grant.js +138 -0
  118. package/dist/telegram-bot/commands/grant.test.js +217 -0
  119. package/dist/telegram-bot/commands/help.js +52 -0
  120. package/dist/telegram-bot/commands/me.js +53 -0
  121. package/dist/telegram-bot/commands/models.js +6 -0
  122. package/dist/telegram-bot/commands/oauth.js +64 -0
  123. package/dist/telegram-bot/commands/plans.js +96 -0
  124. package/dist/telegram-bot/commands/providers.js +27 -0
  125. package/dist/telegram-bot/commands/quota.js +10 -0
  126. package/dist/telegram-bot/commands/renew-user.js +139 -0
  127. package/dist/telegram-bot/commands/renew-user.test.js +184 -0
  128. package/dist/telegram-bot/commands/renew.js +1369 -0
  129. package/dist/telegram-bot/commands/renew.test.js +1633 -0
  130. package/dist/telegram-bot/commands/start.js +212 -0
  131. package/dist/telegram-bot/commands/start.test.js +280 -0
  132. package/dist/telegram-bot/commands/status.js +6 -0
  133. package/dist/telegram-bot/commands/tailscale.js +15 -0
  134. package/dist/telegram-bot/commands/tailscale.test.js +76 -0
  135. package/dist/telegram-bot/commands/test.js +51 -0
  136. package/dist/telegram-bot/commands/test.test.js +14 -0
  137. package/dist/telegram-bot/commands/usage.js +10 -0
  138. package/dist/telegram-bot/config.js +98 -0
  139. package/dist/telegram-bot/config.test.js +42 -0
  140. package/dist/telegram-bot/customer-actions.js +160 -0
  141. package/dist/telegram-bot/customer-api-keys.js +68 -0
  142. package/dist/telegram-bot/customer-billing.js +72 -0
  143. package/dist/telegram-bot/customer-workspace-repository.js +134 -0
  144. package/dist/telegram-bot/customer-workspace-repository.test.js +47 -0
  145. package/dist/telegram-bot/dashboard-login.js +39 -0
  146. package/dist/telegram-bot/format.js +140 -0
  147. package/dist/telegram-bot/grants.js +370 -0
  148. package/dist/telegram-bot/grants.test.js +290 -0
  149. package/dist/telegram-bot/index.js +85 -0
  150. package/dist/telegram-bot/message-cleanup.js +55 -0
  151. package/dist/telegram-bot/message-cleanup.test.js +77 -0
  152. package/dist/telegram-bot/message-format.js +45 -0
  153. package/dist/telegram-bot/message-format.test.js +10 -0
  154. package/dist/telegram-bot/proxy-client.js +174 -0
  155. package/dist/telegram-bot/rate-limit.js +95 -0
  156. package/dist/telegram-bot/rate-limit.test.js +58 -0
  157. package/dist/telegram-bot/sessions.js +171 -0
  158. package/dist/telegram-bot/sessions.test.js +107 -0
  159. package/dist/telegram-bot/telegram-adapter.js +126 -0
  160. package/dist/telegram-bot/worker.js +63 -0
  161. package/package.json +39 -0
@@ -0,0 +1,126 @@
1
+ import { Bot } from "grammy";
2
+ import { createAllowlistMiddleware, createCustomerCommandMiddleware } from "./auth.js";
3
+ import { BotIdentityRepository } from "./bot-identity-repository.js";
4
+ import { CustomerWorkspaceRepository } from "./customer-workspace-repository.js";
5
+ import { CustomerKeyRepository } from "../customer-keys.js";
6
+ import { BillingRepository } from "../billing.js";
7
+ import { AuditLogRepository } from "../audit-log.js";
8
+ import { registerCustomerActionCallbacks } from "./customer-actions.js";
9
+ import { registerAccountsCommand } from "./commands/accounts.js";
10
+ import { registerApiKeyCommand } from "./commands/apikey.js";
11
+ import { registerApplyCommand } from "./commands/apply.js";
12
+ import { registerClientsCommand } from "./commands/clients.js";
13
+ import { registerGrantCommand } from "./commands/grant.js";
14
+ import { registerHelpCommand } from "./commands/help.js";
15
+ import { registerMeCommand } from "./commands/me.js";
16
+ import { registerModelsCommand } from "./commands/models.js";
17
+ import { registerOauthCommand } from "./commands/oauth.js";
18
+ import { registerPlansCommand } from "./commands/plans.js";
19
+ import { registerProvidersCommand } from "./commands/providers.js";
20
+ import { registerQuotaCommand } from "./commands/quota.js";
21
+ import { registerRenewCommand } from "./commands/renew.js";
22
+ import { registerRenewUserCommand } from "./commands/renew-user.js";
23
+ import { registerStartCommand } from "./commands/start.js";
24
+ import { registerStatusCommand } from "./commands/status.js";
25
+ import { registerTailscaleCommand } from "./commands/tailscale.js";
26
+ import { registerTestCommand } from "./commands/test.js";
27
+ import { registerUsageCommand } from "./commands/usage.js";
28
+ import { createRateLimitMiddleware, SqliteRateLimiter } from "./rate-limit.js";
29
+ import { SqliteSessionStore } from "./sessions.js";
30
+ import { createCustomerMessageCleanupMiddleware } from "./message-cleanup.js";
31
+ import { DashboardAuthRepository } from "../dashboard-auth.js";
32
+ import { registerDashboardLoginCallbacks } from "./dashboard-login.js";
33
+ export function createTelegramBot(deps) {
34
+ const bot = new Bot(deps.config.telegramBotToken);
35
+ const identities = BotIdentityRepository.create(deps.config.sessionDbPath);
36
+ const workspaces = CustomerWorkspaceRepository.create(deps.config.sessionDbPath);
37
+ const sessions = SqliteSessionStore.create(deps.config.sessionDbPath, deps.config.sessionTtlMs);
38
+ const customerKeys = CustomerKeyRepository.create(deps.config.sessionDbPath);
39
+ const billing = BillingRepository.create(deps.config.sessionDbPath);
40
+ const auditLog = AuditLogRepository.create(deps.config.sessionDbPath);
41
+ const dashboardAuth = DashboardAuthRepository.create(deps.config.sessionDbPath);
42
+ const rateLimiter = SqliteRateLimiter.create(deps.config.sessionDbPath, {
43
+ windowMs: deps.config.rateLimitWindowMs,
44
+ maxRequests: deps.config.rateLimitMaxRequests,
45
+ });
46
+ bot.use(createAllowlistMiddleware(deps.config));
47
+ bot.use(async (ctx, next) => {
48
+ const fromId = ctx.from?.id?.toString();
49
+ const chatId = ctx.chat?.id?.toString();
50
+ if (fromId) {
51
+ identities.upsertUser({
52
+ telegramUserId: fromId,
53
+ username: ctx.from?.username,
54
+ firstName: ctx.from?.first_name,
55
+ lastName: ctx.from?.last_name,
56
+ languageCode: ctx.from?.language_code,
57
+ defaultRole: deps.config.ownerUserIds.has(fromId) ? "owner" : "customer",
58
+ defaultStatus: deps.config.requireAdminApproval ? "pending_approval" : "active",
59
+ });
60
+ }
61
+ if (chatId && ctx.chat) {
62
+ identities.upsertChat({
63
+ telegramChatId: chatId,
64
+ chatType: ctx.chat.type,
65
+ title: "title" in ctx.chat ? ctx.chat.title : undefined,
66
+ });
67
+ }
68
+ if (fromId && chatId) {
69
+ identities.upsertMembership({
70
+ telegramUserId: fromId,
71
+ telegramChatId: chatId,
72
+ });
73
+ }
74
+ await next();
75
+ });
76
+ bot.use(createCustomerCommandMiddleware(deps.config));
77
+ bot.use(createRateLimitMiddleware(rateLimiter));
78
+ bot.use(createCustomerMessageCleanupMiddleware(deps.config));
79
+ registerStartCommand(bot, deps, identities, workspaces, customerKeys, billing);
80
+ registerCustomerActionCallbacks(bot, workspaces, customerKeys, billing, auditLog);
81
+ registerHelpCommand(bot, deps);
82
+ registerMeCommand(bot, identities, workspaces, customerKeys, auditLog);
83
+ registerPlansCommand(bot, deps, billing);
84
+ registerApiKeyCommand(bot, deps, customerKeys, workspaces, billing, auditLog);
85
+ registerTailscaleCommand(bot, deps);
86
+ registerUsageCommand(bot, workspaces, customerKeys, billing);
87
+ registerQuotaCommand(bot, workspaces, customerKeys, billing);
88
+ registerRenewCommand(bot, deps, sessions, identities, workspaces, customerKeys, billing, auditLog);
89
+ registerGrantCommand(bot, deps, identities, workspaces, customerKeys, billing, auditLog);
90
+ registerRenewUserCommand(bot, deps, identities, workspaces, customerKeys, billing, auditLog);
91
+ registerStatusCommand(bot, deps);
92
+ registerProvidersCommand(bot, deps);
93
+ registerClientsCommand(bot, deps);
94
+ registerModelsCommand(bot, deps);
95
+ registerApplyCommand(bot, deps, sessions);
96
+ registerOauthCommand(bot, deps, sessions);
97
+ registerAccountsCommand(bot, deps, sessions);
98
+ registerTestCommand(bot, deps, sessions);
99
+ registerDashboardLoginCallbacks(bot, deps.config, dashboardAuth);
100
+ bot.catch((error) => {
101
+ const ctx = error.ctx;
102
+ console.error("telegram bot error", {
103
+ error: error.error instanceof Error
104
+ ? {
105
+ name: error.error.name,
106
+ message: error.error.message,
107
+ stack: error.error.stack,
108
+ }
109
+ : error.error,
110
+ updateType: resolveUpdateType(ctx.update),
111
+ chatId: ctx.chat?.id,
112
+ fromId: ctx.from?.id,
113
+ callbackData: ctx.callbackQuery?.data,
114
+ messageText: ctx.message && "text" in ctx.message ? ctx.message.text : undefined,
115
+ });
116
+ });
117
+ return bot;
118
+ }
119
+ function resolveUpdateType(update) {
120
+ for (const key of Object.keys(update)) {
121
+ if (key !== "update_id") {
122
+ return key;
123
+ }
124
+ }
125
+ return "unknown";
126
+ }
@@ -0,0 +1,63 @@
1
+ import { Bot } from "grammy";
2
+ import path from "node:path";
3
+ import { AuditLogRepository } from "../audit-log.js";
4
+ import { runBillingExpiration } from "../billing-expiration.js";
5
+ import { BillingRepository } from "../billing.js";
6
+ import { CustomerKeyRepository } from "../customer-keys.js";
7
+ import { CustomerWorkspaceRepository } from "./customer-workspace-repository.js";
8
+ import { readTelegramBotConfig } from "./config.js";
9
+ const config = readTelegramBotConfig(process.env);
10
+ const dbFile = path.resolve(config.sessionDbPath);
11
+ const billing = BillingRepository.create(dbFile);
12
+ const customerKeys = CustomerKeyRepository.create(dbFile);
13
+ const workspaces = CustomerWorkspaceRepository.create(dbFile);
14
+ const auditLog = AuditLogRepository.create(dbFile);
15
+ const bot = new Bot(config.telegramBotToken);
16
+ const intervalMs = readPositiveInteger(process.env.BOT_WORKER_INTERVAL_MS) ?? 60_000;
17
+ const runOnceOnly = readEnvBoolean(process.env.BOT_WORKER_ONCE);
18
+ let stopping = false;
19
+ process.once("SIGINT", () => {
20
+ stopping = true;
21
+ });
22
+ process.once("SIGTERM", () => {
23
+ stopping = true;
24
+ });
25
+ while (!stopping) {
26
+ const startedAt = Date.now();
27
+ const summary = await runBillingExpiration({
28
+ billing,
29
+ customerKeys,
30
+ workspaces,
31
+ auditLog,
32
+ notifyCustomer: async ({ telegramUserId, text }) => {
33
+ await bot.api.sendMessage(Number(telegramUserId), text);
34
+ },
35
+ });
36
+ console.info("telegram billing worker cycle completed", {
37
+ expiredEntitlements: summary.expiredEntitlements,
38
+ suspendedWorkspaces: summary.suspendedWorkspaces,
39
+ suspendedKeys: summary.suspendedKeys,
40
+ notificationsSent: summary.notificationsSent,
41
+ notificationsFailed: summary.notificationsFailed,
42
+ totalMs: Date.now() - startedAt,
43
+ });
44
+ if (runOnceOnly || stopping) {
45
+ break;
46
+ }
47
+ await sleep(intervalMs);
48
+ }
49
+ console.info("telegram billing worker stopped");
50
+ function sleep(ms) {
51
+ return new Promise((resolve) => setTimeout(resolve, ms));
52
+ }
53
+ function readPositiveInteger(value) {
54
+ if (!value?.trim()) {
55
+ return undefined;
56
+ }
57
+ const parsed = Number(value);
58
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
59
+ }
60
+ function readEnvBoolean(value) {
61
+ const normalized = value?.trim().toLowerCase();
62
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
63
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "responses-proxy",
3
+ "version": "0.1.0",
4
+ "description": "AI routing proxy with multi-provider fallback, RTK token saver, and web dashboard",
5
+ "bin": {
6
+ "responses-proxy": "./cli.js"
7
+ },
8
+ "files": [
9
+ "cli.js",
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "node scripts/build-cli.js",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "engines": {
19
+ "node": ">=20.0.0"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "proxy",
24
+ "router",
25
+ "openai",
26
+ "anthropic",
27
+ "claude",
28
+ "codex",
29
+ "rtk",
30
+ "token-saver",
31
+ "llm",
32
+ "fallback"
33
+ ],
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/phamtuandat/responses-proxy"
38
+ }
39
+ }