jishushell 0.0.1 → 0.4.2-beta2

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 (139) hide show
  1. package/INSTALL-NOTICE +41 -0
  2. package/LICENSE +202 -0
  3. package/README.md +36 -0
  4. package/THIRD-PARTY-NOTICES +387 -0
  5. package/dist/auth.d.ts +6 -0
  6. package/dist/auth.js +88 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +290 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.d.ts +24 -0
  12. package/dist/config.js +226 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/constants.d.ts +3 -0
  15. package/dist/constants.js +15 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/control.d.ts +44 -0
  18. package/dist/control.js +1359 -0
  19. package/dist/control.js.map +1 -0
  20. package/dist/crypto-shim.d.ts +1 -0
  21. package/dist/crypto-shim.js +2 -0
  22. package/dist/crypto-shim.js.map +1 -0
  23. package/dist/doctor.d.ts +46 -0
  24. package/dist/doctor.js +937 -0
  25. package/dist/doctor.js.map +1 -0
  26. package/dist/install.d.ts +27 -0
  27. package/dist/install.js +570 -0
  28. package/dist/install.js.map +1 -0
  29. package/dist/routes/auth.d.ts +4 -0
  30. package/dist/routes/auth.js +151 -0
  31. package/dist/routes/auth.js.map +1 -0
  32. package/dist/routes/instances.d.ts +2 -0
  33. package/dist/routes/instances.js +1303 -0
  34. package/dist/routes/instances.js.map +1 -0
  35. package/dist/routes/setup.d.ts +2 -0
  36. package/dist/routes/setup.js +139 -0
  37. package/dist/routes/setup.js.map +1 -0
  38. package/dist/routes/system.d.ts +2 -0
  39. package/dist/routes/system.js +102 -0
  40. package/dist/routes/system.js.map +1 -0
  41. package/dist/server.d.ts +6 -0
  42. package/dist/server.js +392 -0
  43. package/dist/server.js.map +1 -0
  44. package/dist/services/instance-manager.d.ts +67 -0
  45. package/dist/services/instance-manager.js +1319 -0
  46. package/dist/services/instance-manager.js.map +1 -0
  47. package/dist/services/llm-proxy/adapters.d.ts +3 -0
  48. package/dist/services/llm-proxy/adapters.js +309 -0
  49. package/dist/services/llm-proxy/adapters.js.map +1 -0
  50. package/dist/services/llm-proxy/circuit-breaker.d.ts +9 -0
  51. package/dist/services/llm-proxy/circuit-breaker.js +73 -0
  52. package/dist/services/llm-proxy/circuit-breaker.js.map +1 -0
  53. package/dist/services/llm-proxy/encryption.d.ts +6 -0
  54. package/dist/services/llm-proxy/encryption.js +61 -0
  55. package/dist/services/llm-proxy/encryption.js.map +1 -0
  56. package/dist/services/llm-proxy/index.d.ts +24 -0
  57. package/dist/services/llm-proxy/index.js +708 -0
  58. package/dist/services/llm-proxy/index.js.map +1 -0
  59. package/dist/services/llm-proxy/rate-limiter.d.ts +1 -0
  60. package/dist/services/llm-proxy/rate-limiter.js +39 -0
  61. package/dist/services/llm-proxy/rate-limiter.js.map +1 -0
  62. package/dist/services/llm-proxy/sse.d.ts +10 -0
  63. package/dist/services/llm-proxy/sse.js +378 -0
  64. package/dist/services/llm-proxy/sse.js.map +1 -0
  65. package/dist/services/llm-proxy/ssrf.d.ts +16 -0
  66. package/dist/services/llm-proxy/ssrf.js +185 -0
  67. package/dist/services/llm-proxy/ssrf.js.map +1 -0
  68. package/dist/services/llm-proxy/types.d.ts +52 -0
  69. package/dist/services/llm-proxy/types.js +2 -0
  70. package/dist/services/llm-proxy/types.js.map +1 -0
  71. package/dist/services/llm-proxy/usage.d.ts +12 -0
  72. package/dist/services/llm-proxy/usage.js +108 -0
  73. package/dist/services/llm-proxy/usage.js.map +1 -0
  74. package/dist/services/nomad-manager.d.ts +22 -0
  75. package/dist/services/nomad-manager.js +828 -0
  76. package/dist/services/nomad-manager.js.map +1 -0
  77. package/dist/services/plugin-installer.d.ts +22 -0
  78. package/dist/services/plugin-installer.js +102 -0
  79. package/dist/services/plugin-installer.js.map +1 -0
  80. package/dist/services/process-manager.d.ts +25 -0
  81. package/dist/services/process-manager.js +531 -0
  82. package/dist/services/process-manager.js.map +1 -0
  83. package/dist/services/setup-manager.d.ts +93 -0
  84. package/dist/services/setup-manager.js +1922 -0
  85. package/dist/services/setup-manager.js.map +1 -0
  86. package/dist/services/system-monitor.d.ts +1 -0
  87. package/dist/services/system-monitor.js +79 -0
  88. package/dist/services/system-monitor.js.map +1 -0
  89. package/dist/services/telemetry/activation.d.ts +12 -0
  90. package/dist/services/telemetry/activation.js +78 -0
  91. package/dist/services/telemetry/activation.js.map +1 -0
  92. package/dist/services/telemetry/client.d.ts +21 -0
  93. package/dist/services/telemetry/client.js +36 -0
  94. package/dist/services/telemetry/client.js.map +1 -0
  95. package/dist/services/telemetry/device-fingerprint.d.ts +18 -0
  96. package/dist/services/telemetry/device-fingerprint.js +123 -0
  97. package/dist/services/telemetry/device-fingerprint.js.map +1 -0
  98. package/dist/services/telemetry/heartbeat.d.ts +13 -0
  99. package/dist/services/telemetry/heartbeat.js +87 -0
  100. package/dist/services/telemetry/heartbeat.js.map +1 -0
  101. package/dist/services/telemetry/index.d.ts +3 -0
  102. package/dist/services/telemetry/index.js +4 -0
  103. package/dist/services/telemetry/index.js.map +1 -0
  104. package/dist/types.d.ts +51 -0
  105. package/dist/types.js +2 -0
  106. package/dist/types.js.map +1 -0
  107. package/dist/utils/safe-json.d.ts +2 -0
  108. package/dist/utils/safe-json.js +80 -0
  109. package/dist/utils/safe-json.js.map +1 -0
  110. package/dist/utils/ttl-cache.d.ts +29 -0
  111. package/dist/utils/ttl-cache.js +77 -0
  112. package/dist/utils/ttl-cache.js.map +1 -0
  113. package/install/jishu-install.sh +2920 -0
  114. package/install/jishu-uninstall.sh +811 -0
  115. package/install/post-install.sh +124 -0
  116. package/install/post-uninstall.sh +46 -0
  117. package/package.json +57 -8
  118. package/public/assets/Dashboard-Dxsq690N.js +1 -0
  119. package/public/assets/InitPassword-CslWYy8G.js +1 -0
  120. package/public/assets/InstanceDetail-DmEkMj-t.js +14 -0
  121. package/public/assets/Login-d45wtgVA.js +1 -0
  122. package/public/assets/NewInstance-Czp5-AJe.js +1 -0
  123. package/public/assets/Settings-BKMGck05.js +1 -0
  124. package/public/assets/Setup-D3rfLWjZ.js +1 -0
  125. package/public/assets/index-77Ug7feY.css +1 -0
  126. package/public/assets/index-DkDnIohs.js +16 -0
  127. package/public/assets/logo-black-theme-DywLAtFy.png +0 -0
  128. package/public/assets/logo-white-theme-DXffFAWw.png +0 -0
  129. package/public/assets/providers-lBSOjUWy.js +1 -0
  130. package/public/assets/usePolling-CqQ8hrNc.js +1 -0
  131. package/public/assets/vendor-i18n-Bvxxh8Di.js +9 -0
  132. package/public/assets/vendor-react-DONn7uBV.js +59 -0
  133. package/public/index.html +15 -0
  134. package/scripts/build-image.sh +55 -0
  135. package/scripts/run.sh +310 -0
  136. package/scripts/setup-pi.sh +80 -0
  137. package/scripts/start-feishu1.js +46 -0
  138. package/index.js +0 -0
  139. package/jishushell-0.0.1.tgz +0 -0
@@ -0,0 +1,185 @@
1
+ import { request as httpRequest } from "http";
2
+ import { request as httpsRequest } from "https";
3
+ import { lookup } from "dns/promises";
4
+ import { Readable } from "stream";
5
+ // SSRF protection — private IP ranges
6
+ const PRIVATE_HOST_PATTERNS = [
7
+ /^127\./,
8
+ /^10\./,
9
+ /^172\.(1[6-9]|2\d|3[01])\./,
10
+ /^192\.168\./,
11
+ /^169\.254\./,
12
+ /^0\./,
13
+ /^localhost$/i,
14
+ /^\[?::1\]?$/,
15
+ /^\[?fc/i,
16
+ /^\[?fd/i,
17
+ /^\[?fe80:/i,
18
+ ];
19
+ export const LOCAL_PROVIDER_IDS = new Set(["ollama", "vllm", "sglang"]);
20
+ const LOCALHOST_HOSTS = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
21
+ function isPrivateHost(hostname) {
22
+ const cleaned = hostname.replace(/^\[|\]$/g, "");
23
+ return PRIVATE_HOST_PATTERNS.some((p) => p.test(cleaned));
24
+ }
25
+ function isPrivateIP(ip) {
26
+ // Strip brackets (e.g. [::1] → ::1)
27
+ const cleaned = ip.replace(/^\[|\]$/g, "");
28
+ const lower = cleaned.toLowerCase();
29
+ // Handle IPv4-mapped IPv6: ::ffff:127.0.0.1, ::ffff:0:127.0.0.1
30
+ if (lower.startsWith("::ffff:0:"))
31
+ return isPrivateIP(lower.slice(9));
32
+ if (lower.startsWith("::ffff:"))
33
+ return isPrivateIP(lower.slice(7));
34
+ // Handle full-form IPv4-mapped IPv6 (e.g. 0000:0000:0000:0000:0000:ffff:7f00:0001)
35
+ if (lower.includes(":ffff:")) {
36
+ const mapped = lower.split(":ffff:")[1];
37
+ if (mapped) {
38
+ // Dotted form (::ffff:192.168.1.1)
39
+ if (mapped.includes("."))
40
+ return isPrivateIP(mapped);
41
+ // Hex form (::ffff:7f00:0001) — convert to IPv4
42
+ const parts = mapped.split(":");
43
+ if (parts.length === 2) {
44
+ const hi = parseInt(parts[0], 16);
45
+ const lo = parseInt(parts[1], 16);
46
+ if (!isNaN(hi) && !isNaN(lo)) {
47
+ return isPrivateIP(`${(hi >> 8) & 0xff}.${hi & 0xff}.${(lo >> 8) & 0xff}.${lo & 0xff}`);
48
+ }
49
+ }
50
+ }
51
+ }
52
+ // IPv4 private and reserved ranges
53
+ if (cleaned.startsWith("0."))
54
+ return true; // 0.0.0.0/8 — RFC 1122 "This host on this network"
55
+ if (cleaned.startsWith("10."))
56
+ return true; // 10.0.0.0/8
57
+ if (cleaned.startsWith("127."))
58
+ return true; // 127.0.0.0/8 — loopback
59
+ if (cleaned.startsWith("172.")) {
60
+ const second = parseInt(cleaned.split(".")[1], 10);
61
+ if (second >= 16 && second <= 31)
62
+ return true; // 172.16.0.0/12
63
+ }
64
+ if (cleaned.startsWith("192.168."))
65
+ return true; // 192.168.0.0/16
66
+ if (cleaned.startsWith("169.254."))
67
+ return true; // 169.254.0.0/16 — link-local
68
+ // CGNAT range — often reaches cloud metadata services
69
+ if (cleaned.startsWith("100.")) {
70
+ const second = parseInt(cleaned.split(".")[1], 10);
71
+ if (second >= 64 && second <= 127)
72
+ return true; // 100.64.0.0/10
73
+ }
74
+ // IPv6 loopback, unspecified, and private
75
+ if (lower === "::1" || lower === "::" || lower === "0:0:0:0:0:0:0:0" || lower === "0:0:0:0:0:0:0:1")
76
+ return true;
77
+ if (lower.startsWith("fe80:") || lower.startsWith("fc") || lower.startsWith("fd"))
78
+ return true;
79
+ return false;
80
+ }
81
+ /**
82
+ * Validate upstream URL for SSRF and return the resolved IP address.
83
+ * Returns null for local providers (no DNS pinning needed).
84
+ */
85
+ export async function validateUpstreamUrl(urlStr, providerId) {
86
+ try {
87
+ const url = new URL(urlStr);
88
+ const isLocalHost = LOCALHOST_HOSTS.has(url.hostname);
89
+ if (LOCAL_PROVIDER_IDS.has(providerId)) {
90
+ // Local AI providers (ollama/vllm/sglang): allow localhost and private
91
+ // networks, but block cloud metadata endpoints (169.254.x.x link-local).
92
+ if (isLocalHost)
93
+ return null;
94
+ if (url.hostname.startsWith("169.254.")) {
95
+ throw new Error(`Local provider URL must not target link-local/metadata address ${url.hostname}`);
96
+ }
97
+ // Allow private LAN addresses (192.168.x, 10.x, 172.16-31.x) — admin explicitly configured
98
+ return null;
99
+ }
100
+ // Even for remote providers, if destination is localhost, skip DNS pinning
101
+ // but still allow it (reverse-proxy setups). Do NOT skip SSRF for
102
+ // non-localhost destinations just because providerId looks local.
103
+ if (isLocalHost)
104
+ return null;
105
+ if (isPrivateHost(url.hostname)) {
106
+ throw new Error(`upstream URL resolves to a private address`);
107
+ }
108
+ try {
109
+ const { address, family } = await lookup(url.hostname);
110
+ if (isPrivateIP(address)) {
111
+ throw new Error(`Provider URL resolves to private IP ${address}`);
112
+ }
113
+ return { address, family: family };
114
+ }
115
+ catch (e) {
116
+ if (e.message?.includes("private IP") || e.message?.includes("must use localhost"))
117
+ throw e;
118
+ throw new Error(`Cannot resolve provider hostname: ${url.hostname}`);
119
+ }
120
+ }
121
+ catch (err) {
122
+ if (err.message.includes("private address") || err.message.includes("private IP"))
123
+ throw err;
124
+ throw new Error(`invalid upstream URL: ${urlStr}`);
125
+ }
126
+ }
127
+ /**
128
+ * Fetch using http(s).request with DNS pinned to a pre-resolved IP.
129
+ */
130
+ export function pinnedFetch(url, options, resolved) {
131
+ return new Promise((resolve, reject) => {
132
+ const parsed = new URL(url);
133
+ const isHttps = parsed.protocol === "https:";
134
+ const requestFn = isHttps ? httpsRequest : httpRequest;
135
+ if (options.signal?.aborted) {
136
+ reject(new DOMException("The operation was aborted.", "AbortError"));
137
+ return;
138
+ }
139
+ const pinnedLookup = (...args) => {
140
+ const cb = args[args.length - 1];
141
+ const opts = typeof args[1] === "object" && args[1] !== null ? args[1] : {};
142
+ if (opts.all) {
143
+ cb(null, [{ address: resolved.address, family: resolved.family }]);
144
+ return;
145
+ }
146
+ cb(null, resolved.address, resolved.family);
147
+ };
148
+ const bodyBuffer = Buffer.from(options.body);
149
+ const req = requestFn({
150
+ hostname: parsed.hostname,
151
+ port: parseInt(parsed.port) || (isHttps ? 443 : 80),
152
+ path: parsed.pathname + parsed.search,
153
+ method: options.method,
154
+ headers: { ...options.headers, "content-length": String(bodyBuffer.length) },
155
+ lookup: pinnedLookup,
156
+ }, (res) => {
157
+ const webStream = Readable.toWeb(res);
158
+ const h = new Headers();
159
+ for (const [k, v] of Object.entries(res.headers)) {
160
+ if (v === undefined)
161
+ continue;
162
+ if (Array.isArray(v)) {
163
+ for (const val of v)
164
+ h.append(k, val);
165
+ }
166
+ else
167
+ h.set(k, v);
168
+ }
169
+ resolve(new Response(webStream, { status: res.statusCode || 200, headers: h }));
170
+ });
171
+ req.on("error", (err) => {
172
+ if (options.signal?.aborted) {
173
+ reject(new DOMException("The operation was aborted.", "AbortError"));
174
+ }
175
+ else {
176
+ reject(err);
177
+ }
178
+ });
179
+ if (options.signal) {
180
+ options.signal.addEventListener("abort", () => req.destroy(), { once: true });
181
+ }
182
+ req.end(bodyBuffer);
183
+ });
184
+ }
185
+ //# sourceMappingURL=ssrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../../../src/services/llm-proxy/ssrf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,sCAAsC;AACtC,MAAM,qBAAqB,GAAG;IAC5B,QAAQ;IACR,OAAO;IACP,4BAA4B;IAC5B,aAAa;IACb,aAAa;IACb,MAAM;IACN,cAAc;IACd,aAAa;IACb,SAAS;IACT,SAAS;IACT,YAAY;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AACxE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5E,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,WAAW,CAAC,EAAU;IAC7B,oCAAoC;IACpC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEpC,gEAAgE;IAChE,IAAI,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpE,mFAAmF;IACnF,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,MAAM,EAAE,CAAC;YACX,mCAAmC;YACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;YACrD,gDAAgD;YAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClC,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7B,OAAO,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;gBAC1F,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAO,mDAAmD;IACpG,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,CAAO,aAAa;IAC/D,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC,CAAM,yBAAyB;IAC3E,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC,CAAE,gBAAgB;IAClE,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC,CAAE,iBAAiB;IACnE,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC,CAAE,8BAA8B;IAChF,sDAAsD;IACtD,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,IAAI,GAAG;YAAE,OAAO,IAAI,CAAC,CAAE,gBAAgB;IACnE,CAAC;IAED,0CAA0C;IAC1C,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,iBAAiB,IAAI,KAAK,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACjH,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/F,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAc,EAAE,UAAkB;IAC1E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtD,IAAI,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,uEAAuE;YACvE,yEAAyE;YACzE,IAAI,WAAW;gBAAE,OAAO,IAAI,CAAC;YAC7B,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,kEAAkE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpG,CAAC;YACD,2FAA2F;YAC3F,OAAO,IAAI,CAAC;QACd,CAAC;QACD,2EAA2E;QAC3E,kEAAkE;QAClE,kEAAkE;QAClE,IAAI,WAAW;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACvD,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,EAAE,CAAC,CAAC;YACpE,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAe,EAAE,CAAC;QAC9C,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC;gBAAE,MAAM,CAAC,CAAC;YAC5F,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,MAAM,GAAG,CAAC;QAC7F,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,GAAW,EACX,OAAgG,EAChG,QAAyB;IAEzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;QAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;QAEvD,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,YAAY,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE;YACtC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;gBACb,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBACnE,OAAO;YACT,CAAC;YACD,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE7C,MAAM,GAAG,GAAG,SAAS,CACnB;YACE,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,IAAI,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM;YACrC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;YAC5E,MAAM,EAAE,YAAmB;SAC5B,EACD,CAAC,GAAG,EAAE,EAAE;YACN,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAA0B,CAAmB,CAAC;YAC/E,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;YACxB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjD,IAAI,CAAC,KAAK,SAAS;oBAAE,SAAS;gBAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;oBAAC,KAAK,MAAM,GAAG,IAAI,CAAC;wBAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAAC,CAAC;;oBAC3D,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnB,CAAC;YACD,OAAO,CAAC,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,CAAC,CACF,CAAC;QAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACtB,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,YAAY,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC,CAAC;YACvE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,52 @@
1
+ export interface UpstreamConfig {
2
+ providerId: string;
3
+ baseUrl: string;
4
+ api: string;
5
+ authHeader: boolean;
6
+ headers: Record<string, string>;
7
+ models: Array<{
8
+ id: string;
9
+ name: string;
10
+ contextWindow: number;
11
+ [key: string]: unknown;
12
+ }>;
13
+ selectedModelId: string;
14
+ apiKey: string;
15
+ hasApiKey: boolean;
16
+ clearApiKey: boolean;
17
+ }
18
+ export interface UpstreamRequest {
19
+ url: string;
20
+ headers: Record<string, string>;
21
+ body: string;
22
+ }
23
+ export interface CachedUpstreamConfig {
24
+ upstream: UpstreamConfig;
25
+ apiKey: string;
26
+ timestamp: number;
27
+ }
28
+ export interface RateBucket {
29
+ count: number;
30
+ windowStart: number;
31
+ }
32
+ export interface CircuitState {
33
+ failures: number;
34
+ lastFailure: number;
35
+ state: "closed" | "open" | "half-open";
36
+ halfOpenInFlight: boolean;
37
+ }
38
+ export interface UsageRecord {
39
+ instanceId: string;
40
+ timestamp: number;
41
+ model: string;
42
+ promptTokens: number;
43
+ completionTokens: number;
44
+ totalTokens: number;
45
+ latencyMs: number;
46
+ status: "success" | "error";
47
+ errorCode?: number;
48
+ }
49
+ export interface ResolvedAddress {
50
+ address: string;
51
+ family: 4 | 6;
52
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/llm-proxy/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { UsageRecord } from "./types.js";
2
+ export declare function trackUsage(record: UsageRecord): void;
3
+ export declare function flushUsage(): void;
4
+ export declare function getProxyUsage(instanceId?: string): Promise<{
5
+ requests: number;
6
+ tokens: {
7
+ prompt: number;
8
+ completion: number;
9
+ total: number;
10
+ };
11
+ errors: number;
12
+ }>;
@@ -0,0 +1,108 @@
1
+ import { existsSync, createReadStream } from "fs";
2
+ import { appendFile, stat, rename, mkdir } from "fs/promises";
3
+ import { createInterface } from "readline";
4
+ import { dirname, join } from "path";
5
+ import { JISHUSHELL_HOME } from "../../config.js";
6
+ const USAGE_MAX_BUFFER_SIZE = 100;
7
+ const USAGE_MAX_FILE_SIZE = 50 * 1024 * 1024; // 50 MB
8
+ const USAGE_FLUSH_INTERVAL_MS = 60_000;
9
+ const usageBuffer = [];
10
+ let usageFlushTimer = null;
11
+ let _flushing = false;
12
+ async function flushUsageBuffer() {
13
+ usageFlushTimer = null;
14
+ if (usageBuffer.length === 0 || _flushing)
15
+ return;
16
+ _flushing = true;
17
+ // Snapshot-then-clear: only remove from buffer AFTER successful write.
18
+ // If write fails, data stays in buffer for retry on next flush.
19
+ const snapshot = usageBuffer.slice(0);
20
+ const lines = snapshot.join("\n") + "\n";
21
+ try {
22
+ const usagePath = join(JISHUSHELL_HOME, "proxy-usage.jsonl");
23
+ await mkdir(dirname(usagePath), { recursive: true });
24
+ try {
25
+ const st = await stat(usagePath).catch(() => null);
26
+ if (st && st.size > USAGE_MAX_FILE_SIZE) {
27
+ await rename(usagePath, usagePath + ".1");
28
+ }
29
+ }
30
+ catch { /* ignore rotation errors */ }
31
+ await appendFile(usagePath, lines);
32
+ // Write succeeded — remove the flushed records from buffer
33
+ usageBuffer.splice(0, snapshot.length);
34
+ }
35
+ catch (err) {
36
+ console.error("[llm-proxy] usage flush error (data retained for retry):", err.message);
37
+ }
38
+ finally {
39
+ _flushing = false;
40
+ // Re-schedule if new records accumulated during flush
41
+ if (usageBuffer.length > 0 && !usageFlushTimer) {
42
+ usageFlushTimer = setTimeout(flushUsageBuffer, USAGE_FLUSH_INTERVAL_MS);
43
+ usageFlushTimer.unref();
44
+ }
45
+ }
46
+ }
47
+ const USAGE_MAX_BUFFER_HARD_LIMIT = USAGE_MAX_BUFFER_SIZE * 2; // 200 records max in memory (RPi-friendly)
48
+ export function trackUsage(record) {
49
+ // Drop oldest records if buffer grows too large (flush blocked by _flushing)
50
+ if (usageBuffer.length >= USAGE_MAX_BUFFER_HARD_LIMIT) {
51
+ usageBuffer.splice(0, usageBuffer.length - USAGE_MAX_BUFFER_SIZE);
52
+ }
53
+ usageBuffer.push(JSON.stringify(record));
54
+ if (usageBuffer.length >= USAGE_MAX_BUFFER_SIZE) {
55
+ flushUsageBuffer();
56
+ }
57
+ else if (!usageFlushTimer) {
58
+ usageFlushTimer = setTimeout(flushUsageBuffer, USAGE_FLUSH_INTERVAL_MS);
59
+ usageFlushTimer.unref();
60
+ }
61
+ }
62
+ export function flushUsage() {
63
+ flushUsageBuffer();
64
+ }
65
+ // Flush buffered usage records synchronously on graceful shutdown
66
+ import { appendFileSync } from "fs";
67
+ function flushUsageSync() {
68
+ if (usageBuffer.length === 0)
69
+ return;
70
+ try {
71
+ const lines = usageBuffer.splice(0).join("\n") + "\n";
72
+ appendFileSync(join(JISHUSHELL_HOME, "proxy-usage.jsonl"), lines);
73
+ }
74
+ catch { /* best-effort */ }
75
+ }
76
+ process.on("SIGTERM", flushUsageSync);
77
+ process.on("SIGINT", flushUsageSync);
78
+ export async function getProxyUsage(instanceId) {
79
+ const usagePath = join(JISHUSHELL_HOME, "proxy-usage.jsonl");
80
+ const result = { requests: 0, tokens: { prompt: 0, completion: 0, total: 0 }, errors: 0 };
81
+ // Read both current and rotated file to avoid losing historical data
82
+ for (const filePath of [usagePath + ".1", usagePath]) {
83
+ if (!existsSync(filePath))
84
+ continue;
85
+ try {
86
+ const rl = createInterface({ input: createReadStream(filePath, "utf-8"), crlfDelay: Infinity });
87
+ for await (const line of rl) {
88
+ if (!line.trim())
89
+ continue;
90
+ try {
91
+ const r = JSON.parse(line);
92
+ if (instanceId && r.instanceId !== instanceId)
93
+ continue;
94
+ result.requests++;
95
+ result.tokens.prompt += r.promptTokens || 0;
96
+ result.tokens.completion += r.completionTokens || 0;
97
+ result.tokens.total += r.totalTokens || 0;
98
+ if (r.status === "error")
99
+ result.errors++;
100
+ }
101
+ catch { /* skip malformed lines */ }
102
+ }
103
+ }
104
+ catch { /* file read error */ }
105
+ }
106
+ return result;
107
+ }
108
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/services/llm-proxy/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Nomad-based service manager for OpenClaw instances.
3
+ * Communicates with Nomad via its HTTP API.
4
+ */
5
+ export declare const DOCKER_IMAGE_RE: RegExp;
6
+ export declare const MAX_DOCKER_IMAGE_NAME_LEN = 256;
7
+ export declare function setPanelPort(port: number): void;
8
+ export declare const VALID_LOG_TYPES: Set<string>;
9
+ export declare const NOMAD_TEMPLATE_UNSAFE_RE: RegExp;
10
+ export declare function purgeInstanceVariables(instanceId: string): Promise<void>;
11
+ export declare const VALID_USER_RE: RegExp;
12
+ export declare function shouldAutoStart(instanceId: string): Promise<boolean>;
13
+ export declare function getStatus(instanceId: string): Promise<Record<string, any>>;
14
+ export declare function startInstance(instanceId: string): Promise<Record<string, any>>;
15
+ export declare function stopInstance(instanceId: string, purge?: boolean): Promise<Record<string, any>>;
16
+ export declare function restartInstance(instanceId: string): Promise<Record<string, any>>;
17
+ export declare function getLogs(instanceId: string, lines?: number, logType?: string): Promise<string[]>;
18
+ export declare function exec(instanceId: string, command: string[], timeoutMs?: number): Promise<{
19
+ stdout: string;
20
+ stderr: string;
21
+ exitCode: number;
22
+ }>;