@openacp/cli 2026.402.4 → 2026.402.5

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/dist/index.d.ts CHANGED
@@ -31,7 +31,7 @@ type LoggingConfig = z.infer<typeof LoggingSchema>;
31
31
  declare const TunnelSchema: z.ZodDefault<z.ZodObject<{
32
32
  enabled: z.ZodDefault<z.ZodBoolean>;
33
33
  port: z.ZodDefault<z.ZodNumber>;
34
- provider: z.ZodDefault<z.ZodEnum<["cloudflare", "ngrok", "bore", "tailscale"]>>;
34
+ provider: z.ZodDefault<z.ZodEnum<["openacp", "cloudflare", "ngrok", "bore", "tailscale"]>>;
35
35
  options: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
36
36
  maxUserTunnels: z.ZodDefault<z.ZodNumber>;
37
37
  storeTtlMinutes: z.ZodDefault<z.ZodNumber>;
@@ -46,10 +46,10 @@ declare const TunnelSchema: z.ZodDefault<z.ZodObject<{
46
46
  token?: string | undefined;
47
47
  }>>;
48
48
  }, "strip", z.ZodTypeAny, {
49
+ provider: "openacp" | "cloudflare" | "ngrok" | "bore" | "tailscale";
49
50
  options: Record<string, unknown>;
50
51
  enabled: boolean;
51
52
  port: number;
52
- provider: "cloudflare" | "ngrok" | "bore" | "tailscale";
53
53
  maxUserTunnels: number;
54
54
  storeTtlMinutes: number;
55
55
  auth: {
@@ -57,10 +57,10 @@ declare const TunnelSchema: z.ZodDefault<z.ZodObject<{
57
57
  token?: string | undefined;
58
58
  };
59
59
  }, {
60
+ provider?: "openacp" | "cloudflare" | "ngrok" | "bore" | "tailscale" | undefined;
60
61
  options?: Record<string, unknown> | undefined;
61
62
  enabled?: boolean | undefined;
62
63
  port?: number | undefined;
63
- provider?: "cloudflare" | "ngrok" | "bore" | "tailscale" | undefined;
64
64
  maxUserTunnels?: number | undefined;
65
65
  storeTtlMinutes?: number | undefined;
66
66
  auth?: {
@@ -215,7 +215,7 @@ declare const ConfigSchema: z.ZodObject<{
215
215
  tunnel: z.ZodDefault<z.ZodObject<{
216
216
  enabled: z.ZodDefault<z.ZodBoolean>;
217
217
  port: z.ZodDefault<z.ZodNumber>;
218
- provider: z.ZodDefault<z.ZodEnum<["cloudflare", "ngrok", "bore", "tailscale"]>>;
218
+ provider: z.ZodDefault<z.ZodEnum<["openacp", "cloudflare", "ngrok", "bore", "tailscale"]>>;
219
219
  options: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
220
220
  maxUserTunnels: z.ZodDefault<z.ZodNumber>;
221
221
  storeTtlMinutes: z.ZodDefault<z.ZodNumber>;
@@ -230,10 +230,10 @@ declare const ConfigSchema: z.ZodObject<{
230
230
  token?: string | undefined;
231
231
  }>>;
232
232
  }, "strip", z.ZodTypeAny, {
233
+ provider: "openacp" | "cloudflare" | "ngrok" | "bore" | "tailscale";
233
234
  options: Record<string, unknown>;
234
235
  enabled: boolean;
235
236
  port: number;
236
- provider: "cloudflare" | "ngrok" | "bore" | "tailscale";
237
237
  maxUserTunnels: number;
238
238
  storeTtlMinutes: number;
239
239
  auth: {
@@ -241,10 +241,10 @@ declare const ConfigSchema: z.ZodObject<{
241
241
  token?: string | undefined;
242
242
  };
243
243
  }, {
244
+ provider?: "openacp" | "cloudflare" | "ngrok" | "bore" | "tailscale" | undefined;
244
245
  options?: Record<string, unknown> | undefined;
245
246
  enabled?: boolean | undefined;
246
247
  port?: number | undefined;
247
- provider?: "cloudflare" | "ngrok" | "bore" | "tailscale" | undefined;
248
248
  maxUserTunnels?: number | undefined;
249
249
  storeTtlMinutes?: number | undefined;
250
250
  auth?: {
@@ -383,10 +383,10 @@ declare const ConfigSchema: z.ZodObject<{
383
383
  workingDirectory?: string | undefined;
384
384
  }>;
385
385
  tunnel: {
386
+ provider: "openacp" | "cloudflare" | "ngrok" | "bore" | "tailscale";
386
387
  options: Record<string, unknown>;
387
388
  enabled: boolean;
388
389
  port: number;
389
- provider: "cloudflare" | "ngrok" | "bore" | "tailscale";
390
390
  maxUserTunnels: number;
391
391
  storeTtlMinutes: number;
392
392
  auth: {
@@ -468,10 +468,10 @@ declare const ConfigSchema: z.ZodObject<{
468
468
  workingDirectory?: string | undefined;
469
469
  }> | undefined;
470
470
  tunnel?: {
471
+ provider?: "openacp" | "cloudflare" | "ngrok" | "bore" | "tailscale" | undefined;
471
472
  options?: Record<string, unknown> | undefined;
472
473
  enabled?: boolean | undefined;
473
474
  port?: number | undefined;
474
- provider?: "cloudflare" | "ngrok" | "bore" | "tailscale" | undefined;
475
475
  maxUserTunnels?: number | undefined;
476
476
  storeTtlMinutes?: number | undefined;
477
477
  auth?: {
@@ -1711,7 +1711,7 @@ declare class TunnelService {
1711
1711
  private config;
1712
1712
  private apiPort;
1713
1713
  private startError;
1714
- constructor(config: TunnelConfig, registryPath?: string, binDir?: string);
1714
+ constructor(config: TunnelConfig, registryPath?: string, binDir?: string, storage?: PluginStorage);
1715
1715
  start(apiPort: number): Promise<string>;
1716
1716
  stop(): Promise<void>;
1717
1717
  addTunnel(port: number, opts?: {
package/dist/index.js CHANGED
@@ -431,6 +431,17 @@ var init_config_migrations = __esm({
431
431
  }
432
432
  return changed;
433
433
  }
434
+ },
435
+ {
436
+ name: "migrate-tunnel-provider-to-openacp",
437
+ apply(raw) {
438
+ const tunnel = raw.tunnel;
439
+ if (!tunnel) return false;
440
+ if (tunnel.provider !== "cloudflare") return false;
441
+ tunnel.provider = "openacp";
442
+ log2.info("Migrated tunnel provider: cloudflare \u2192 openacp (OpenACP managed tunnel)");
443
+ return true;
444
+ }
434
445
  }
435
446
  ];
436
447
  }
@@ -641,7 +652,7 @@ var init_config = __esm({
641
652
  TunnelSchema = z.object({
642
653
  enabled: z.boolean().default(false),
643
654
  port: z.number().default(3100),
644
- provider: z.enum(["cloudflare", "ngrok", "bore", "tailscale"]).default("cloudflare"),
655
+ provider: z.enum(["openacp", "cloudflare", "ngrok", "bore", "tailscale"]).default("openacp"),
645
656
  options: z.record(z.string(), z.unknown()).default({}),
646
657
  maxUserTunnels: z.number().default(5),
647
658
  storeTtlMinutes: z.number().default(60),
@@ -739,7 +750,7 @@ var init_config = __esm({
739
750
  tunnel: {
740
751
  enabled: true,
741
752
  port: 3100,
742
- provider: "cloudflare",
753
+ provider: "openacp",
743
754
  options: {},
744
755
  storeTtlMinutes: 60,
745
756
  auth: { enabled: false }
@@ -2004,7 +2015,6 @@ var init_auth = __esm({
2004
2015
 
2005
2016
  // src/plugins/api-server/server.ts
2006
2017
  import Fastify from "fastify";
2007
- import fastifyCors from "@fastify/cors";
2008
2018
  import fastifySwagger from "@fastify/swagger";
2009
2019
  import fastifySwaggerUi from "@fastify/swagger-ui";
2010
2020
  import fastifyRateLimit from "@fastify/rate-limit";
@@ -2013,16 +2023,17 @@ async function createApiServer(options) {
2013
2023
  const app = Fastify({ logger: options.logger ?? false, forceCloseConnections: true });
2014
2024
  app.setValidatorCompiler(validatorCompiler);
2015
2025
  app.setSerializerCompiler(serializerCompiler);
2016
- await app.register(fastifyCors, {
2017
- origin: (origin, cb) => {
2018
- if (!origin || origin.startsWith("http://localhost") || origin.startsWith("http://127.0.0.1")) {
2019
- cb(null, true);
2020
- } else {
2021
- cb(null, false);
2022
- }
2023
- },
2024
- methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE", "OPTIONS"],
2025
- credentials: true
2026
+ app.addHook("onRequest", async (request, reply) => {
2027
+ const origin = request.headers.origin;
2028
+ if (origin) {
2029
+ reply.header("Access-Control-Allow-Origin", origin);
2030
+ reply.header("Access-Control-Allow-Credentials", "true");
2031
+ }
2032
+ if (request.method === "OPTIONS") {
2033
+ reply.header("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS");
2034
+ reply.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
2035
+ reply.status(204).send();
2036
+ }
2026
2037
  });
2027
2038
  await app.register(fastifyRateLimit, { max: 100, timeWindow: "1 minute" });
2028
2039
  await app.register(fastifySwagger, {
@@ -2059,15 +2070,14 @@ async function createApiServer(options) {
2059
2070
  },
2060
2071
  async start() {
2061
2072
  await app.ready();
2062
- const maxRetries = 10;
2063
2073
  let port = options.port;
2064
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
2074
+ while (port <= 65535) {
2065
2075
  try {
2066
2076
  const address = await app.listen({ port, host: options.host });
2067
2077
  const url = new URL(address);
2068
2078
  return { port: Number(url.port), host: url.hostname };
2069
2079
  } catch (err) {
2070
- if (err?.code === "EADDRINUSE" && attempt < maxRetries && port < 65535) {
2080
+ if (err?.code === "EADDRINUSE" && port < 65535) {
2071
2081
  console.log(`[api-server] Port ${port} in use, trying ${port + 1}...`);
2072
2082
  port++;
2073
2083
  continue;
@@ -2075,7 +2085,7 @@ async function createApiServer(options) {
2075
2085
  throw err;
2076
2086
  }
2077
2087
  }
2078
- throw new Error(`All ports ${options.port}-${port} in use`);
2088
+ throw new Error("No available ports found");
2079
2089
  },
2080
2090
  async stop() {
2081
2091
  await app.close();
@@ -2152,28 +2162,34 @@ var init_sse_manager = __esm({
2152
2162
  },
2153
2163
  sessions: stats
2154
2164
  });
2155
- }, 3e4);
2165
+ }, 15e3);
2156
2166
  }
2157
2167
  handleRequest(req, res) {
2158
2168
  const parsedUrl = new URL(req.url || "", "http://localhost");
2159
2169
  const sessionFilter = parsedUrl.searchParams.get("sessionId");
2170
+ console.log(`[sse] new connection from origin=${req.headers.origin ?? "none"} filter=${sessionFilter ?? "none"} total=${this.sseConnections.size + 1}`);
2160
2171
  const origin = req.headers.origin;
2161
2172
  const corsHeaders = {
2162
2173
  "Content-Type": "text/event-stream",
2163
- "Cache-Control": "no-cache",
2164
- Connection: "keep-alive"
2174
+ "Cache-Control": "no-cache, no-transform",
2175
+ Connection: "keep-alive",
2176
+ // Disable buffering in Nginx/Cloudflare/other reverse proxies
2177
+ "X-Accel-Buffering": "no"
2165
2178
  };
2166
- if (origin && (origin.startsWith("http://localhost") || origin.startsWith("http://127.0.0.1"))) {
2179
+ if (origin) {
2167
2180
  corsHeaders["Access-Control-Allow-Origin"] = origin;
2168
2181
  corsHeaders["Access-Control-Allow-Credentials"] = "true";
2169
2182
  }
2183
+ res.socket?.setNoDelay(true);
2170
2184
  res.writeHead(200, corsHeaders);
2171
2185
  res.flushHeaders();
2186
+ res.write(": connected\n\n");
2172
2187
  res.sessionFilter = sessionFilter ?? void 0;
2173
2188
  this.sseConnections.add(res);
2174
2189
  const cleanup = () => {
2175
2190
  this.sseConnections.delete(res);
2176
2191
  this.sseCleanupHandlers.delete(res);
2192
+ console.log(`[sse] connection closed, remaining=${this.sseConnections.size}`);
2177
2193
  };
2178
2194
  this.sseCleanupHandlers.set(res, cleanup);
2179
2195
  req.on("close", cleanup);