kentutai-app 1.1.4 → 1.1.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/.dockerignore ADDED
@@ -0,0 +1,32 @@
1
+ # VCS
2
+ .git
3
+ **/.git
4
+
5
+ # Editor
6
+ .vscode
7
+ **/.vscode
8
+
9
+ # Dependencies and build output
10
+ node_modules
11
+ .next
12
+ out
13
+ build
14
+ dist
15
+ coverage
16
+
17
+ # Runtime data and logs
18
+ data
19
+ logs
20
+
21
+ # Local env files (inject at runtime via --env-file or -e)
22
+ .env
23
+ .env.local
24
+ .env.development.local
25
+ .env.test.local
26
+ .env.production.local
27
+
28
+ # Debug logs
29
+ npm-debug.log*
30
+ yarn-debug.log*
31
+ yarn-error.log*
32
+ .pnpm-debug.log*
package/Dockerfile ADDED
@@ -0,0 +1,52 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ ARG NODE_IMAGE=node:22-alpine
3
+ FROM ${NODE_IMAGE} AS base
4
+ WORKDIR /app
5
+
6
+ FROM base AS builder
7
+
8
+ RUN apk --no-cache upgrade && apk --no-cache add python3 make g++ linux-headers
9
+
10
+ COPY package.json ./
11
+ RUN --mount=type=cache,target=/root/.npm \
12
+ npm install
13
+
14
+ COPY . ./
15
+ ENV NEXT_TELEMETRY_DISABLED=1
16
+ RUN npm run build
17
+
18
+ FROM ${NODE_IMAGE} AS runner
19
+ WORKDIR /app
20
+
21
+ LABEL org.opencontainers.image.title="kentutai"
22
+
23
+ ENV NODE_ENV=production
24
+ ENV PORT=20123
25
+ ENV HOSTNAME=0.0.0.0
26
+ ENV NEXT_TELEMETRY_DISABLED=1
27
+ ENV DATA_DIR=/app/data
28
+
29
+ COPY --from=builder /app/public ./public
30
+ COPY --from=builder /app/.next/static ./.next/static
31
+ COPY --from=builder /app/.next/standalone ./
32
+ COPY --from=builder /app/open-sse ./open-sse
33
+ # Next file tracing can omit sibling files; MITM runs server.js as a separate process.
34
+ COPY --from=builder /app/src/mitm ./src/mitm
35
+ # Standalone node_modules may omit deps only required by the MITM child process.
36
+ COPY --from=builder /app/node_modules/node-forge ./node_modules/node-forge
37
+ # Ensure `next` is available at runtime in case tracing did not include it.
38
+ COPY --from=builder /app/node_modules/next ./node_modules/next
39
+
40
+ RUN mkdir -p /app/data && chown -R node:node /app && \
41
+ mkdir -p /app/data-home && chown node:node /app/data-home && \
42
+ ln -sf /app/data-home /root/.kentutai 2>/dev/null || true
43
+
44
+ # Fix permissions at runtime (handles mounted volumes)
45
+ RUN apk --no-cache upgrade && apk --no-cache add su-exec && \
46
+ printf '#!/bin/sh\nchown -R node:node /app/data /app/data-home 2>/dev/null\nexec su-exec node "$@"\n' > /entrypoint.sh && \
47
+ chmod +x /entrypoint.sh
48
+
49
+ EXPOSE 20123
50
+
51
+ ENTRYPOINT ["/entrypoint.sh"]
52
+ CMD ["node", "server.js"]
@@ -0,0 +1,4 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "dockerfilePath": "./Dockerfile"
4
+ }
@@ -0,0 +1,20 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get all provider connections with full data
9
+ const connections = db.exec("SELECT id, data FROM providerConnections");
10
+ if (connections[0]?.values) {
11
+ connections[0].values.forEach(row => {
12
+ const data = JSON.parse(row[1]);
13
+ console.log(`\n--- Connection: ${row[0]} ---`);
14
+ console.log(JSON.stringify(data, null, 2));
15
+ });
16
+ }
17
+
18
+ db.close();
19
+ process.exit(0);
20
+ });
package/check-db.js ADDED
@@ -0,0 +1,41 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // List all tables
9
+ const tables = db.exec("SELECT name FROM sqlite_master WHERE type='table'");
10
+ console.log('Tables:', tables[0]?.values.map(v => v[0]).join(', '));
11
+
12
+ // Get providers
13
+ try {
14
+ const providers = db.exec("SELECT id, data FROM providers");
15
+ console.log('\nProviders:', providers[0]?.columns);
16
+ if (providers[0]?.values) {
17
+ providers[0].values.forEach(row => {
18
+ const data = JSON.parse(row[1]);
19
+ console.log(`- ${row[0]}: ${data.name || 'unknown'}, enabled: ${data.enabled}`);
20
+ });
21
+ }
22
+ } catch (e) {
23
+ console.log('Providers error:', e.message);
24
+ }
25
+
26
+ // Get API keys
27
+ try {
28
+ const keys = db.exec("SELECT id, key, name FROM apiKeys");
29
+ console.log('\nAPI Keys:', keys[0]?.columns);
30
+ if (keys[0]?.values) {
31
+ keys[0].values.forEach(row => {
32
+ console.log(`- ${row[2]}: ${row[1]?.substring(0, 10)}...`);
33
+ });
34
+ }
35
+ } catch (e) {
36
+ console.log('API Keys error:', e.message);
37
+ }
38
+
39
+ db.close();
40
+ process.exit(0);
41
+ });
package/check-key.js ADDED
@@ -0,0 +1,20 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get full key data for the first key
9
+ const result = db.exec("SELECT id, key, name, data FROM apiKeys LIMIT 1");
10
+ if (result[0]?.values) {
11
+ console.log('First API Key:');
12
+ console.log('ID:', result[0].values[0][0]);
13
+ console.log('Key:', result[0].values[0][1]);
14
+ console.log('Name:', result[0].values[0][2]);
15
+ console.log('Data:', result[0].values[0][3]);
16
+ }
17
+
18
+ db.close();
19
+ process.exit(0);
20
+ });
package/check-key2.js ADDED
@@ -0,0 +1,21 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get schema
9
+ const schema = db.exec("SELECT sql FROM sqlite_master WHERE name='apiKeys'");
10
+ console.log('apiKeys schema:', schema[0]?.values[0][0]);
11
+
12
+ // Get first key
13
+ const result = db.exec("SELECT * FROM apiKeys LIMIT 1");
14
+ if (result[0]) {
15
+ console.log('\nColumns:', result[0].columns);
16
+ console.log('First row:', result[0].values[0]);
17
+ }
18
+
19
+ db.close();
20
+ process.exit(0);
21
+ });
@@ -0,0 +1,29 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get all connections with provider column
9
+ const result = db.exec("SELECT id, provider, isActive, data FROM providerConnections");
10
+ if (result[0]?.values) {
11
+ console.log('All Provider Connections (with provider column):\n');
12
+ result[0].values.forEach(row => {
13
+ const data = JSON.parse(row[3] || '{}');
14
+ const isMimo = data.baseUrl?.includes('mimo') || data.providerSpecificData?.baseUrl?.includes('mimo');
15
+ if (isMimo || row[1]?.includes('mimo')) {
16
+ console.log(`--- ${row[0]} ---`);
17
+ console.log(`Provider: ${row[1]}`);
18
+ console.log(`isActive: ${row[2]}`);
19
+ console.log(`API Key: ${data.apiKey || data.providerSpecificData?.apiKey || 'NOT FOUND'}`);
20
+ console.log(`Prefix: ${data.prefix || data.providerSpecificData?.prefix}`);
21
+ console.log(`Base URL: ${data.baseUrl || data.providerSpecificData?.baseUrl}`);
22
+ console.log('');
23
+ }
24
+ });
25
+ }
26
+
27
+ db.close();
28
+ process.exit(0);
29
+ });
package/check-mimo.js ADDED
@@ -0,0 +1,22 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get MiMo provider full data
9
+ const nodes = db.exec("SELECT id, data FROM providerNodes");
10
+ if (nodes[0]?.values) {
11
+ nodes[0].values.forEach(row => {
12
+ const data = JSON.parse(row[1]);
13
+ if (data.baseUrl?.includes('mimo')) {
14
+ console.log('MiMo Provider Full Data:');
15
+ console.log(JSON.stringify(data, null, 2));
16
+ }
17
+ });
18
+ }
19
+
20
+ db.close();
21
+ process.exit(0);
22
+ });
package/check-nodes.js ADDED
@@ -0,0 +1,26 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get all provider nodes
9
+ const result = db.exec("SELECT id, provider, name, data FROM providerNodes");
10
+ if (result[0]?.values) {
11
+ console.log('All Provider Nodes:\n');
12
+ result[0].values.forEach(row => {
13
+ const data = JSON.parse(row[3] || '{}');
14
+ console.log(`ID: ${row[0]}`);
15
+ console.log(`Provider: ${row[1]}`);
16
+ console.log(`Name: ${row[2]}`);
17
+ console.log(`Prefix: ${data.prefix}`);
18
+ console.log(`Base URL: ${data.baseUrl}`);
19
+ console.log(`Has API Key: ${!!data.apiKey}`);
20
+ console.log('---');
21
+ });
22
+ }
23
+
24
+ db.close();
25
+ process.exit(0);
26
+ });
@@ -0,0 +1,29 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get schema
9
+ const schema = db.exec("SELECT sql FROM sqlite_master WHERE name='providerNodes'");
10
+ console.log('providerNodes schema:');
11
+ console.log(schema[0]?.values[0][0]);
12
+
13
+ // Get all nodes without provider column
14
+ const result = db.exec("SELECT id, data FROM providerNodes");
15
+ if (result[0]?.values) {
16
+ console.log('\nAll Provider Nodes:\n');
17
+ result[0].values.forEach(row => {
18
+ const data = JSON.parse(row[1] || '{}');
19
+ console.log(`ID: ${row[0]}`);
20
+ console.log(`Prefix: ${data.prefix}`);
21
+ console.log(`Base URL: ${data.baseUrl}`);
22
+ console.log(`Name: ${data.name}`);
23
+ console.log('---');
24
+ });
25
+ }
26
+
27
+ db.close();
28
+ process.exit(0);
29
+ });
@@ -0,0 +1,48 @@
1
+ const initSqlJs = require('sql.js');
2
+ const fs = require('fs');
3
+
4
+ initSqlJs().then(SQL => {
5
+ const buffer = fs.readFileSync('E:/var/lib/9router/db/data.sqlite');
6
+ const db = new SQL.Database(buffer);
7
+
8
+ // Get provider connections
9
+ try {
10
+ const providers = db.exec("SELECT id, data FROM providerConnections");
11
+ console.log('Provider Connections:');
12
+ if (providers[0]?.values) {
13
+ providers[0].values.forEach(row => {
14
+ const data = JSON.parse(row[1]);
15
+ console.log(`\n- ID: ${row[0]}`);
16
+ console.log(` Name: ${data.name}`);
17
+ console.log(` Type: ${data.type}`);
18
+ console.log(` Enabled: ${data.enabled}`);
19
+ if (data.nodes) {
20
+ console.log(` Nodes: ${data.nodes.length}`);
21
+ }
22
+ });
23
+ }
24
+ } catch (e) {
25
+ console.log('Provider Connections error:', e.message);
26
+ }
27
+
28
+ // Get provider nodes
29
+ try {
30
+ const nodes = db.exec("SELECT id, data FROM providerNodes");
31
+ console.log('\n\nProvider Nodes:');
32
+ if (nodes[0]?.values) {
33
+ nodes[0].values.forEach(row => {
34
+ const data = JSON.parse(row[1]);
35
+ console.log(`\n- ID: ${row[0]}`);
36
+ console.log(` Name: ${data.name}`);
37
+ console.log(` Base URL: ${data.baseUrl}`);
38
+ console.log(` Has API Key: ${data.apiKey ? 'yes' : 'no'}`);
39
+ console.log(` Enabled: ${data.enabled}`);
40
+ });
41
+ }
42
+ } catch (e) {
43
+ console.log('Provider Nodes error:', e.message);
44
+ }
45
+
46
+ db.close();
47
+ process.exit(0);
48
+ });
package/cli/cli.js CHANGED
@@ -52,16 +52,7 @@ Options:
52
52
 
53
53
  const appDir = path.join(__dirname, "app");
54
54
  const standaloneServer = path.join(appDir, "server.js");
55
- const mainAppDir = path.resolve(__dirname, "..");
56
- const mainServerPath = path.join(mainAppDir, ".next", "standalone", "server.js");
57
-
58
55
  const useStandalone = fs.existsSync(standaloneServer);
59
- const useMainApp = !useStandalone && fs.existsSync(mainServerPath);
60
-
61
- if (!useStandalone && !useMainApp) {
62
- console.log("\n First run detected. Starting development server...\n");
63
- console.log(" For production, run: npm run build\n");
64
- }
65
56
 
66
57
  function openBrowser(url) {
67
58
  const cmd = process.platform === "darwin" ? "open"
@@ -97,31 +88,18 @@ function startServer() {
97
88
  const displayHost = host === DEFAULT_HOST ? "localhost" : host;
98
89
  const url = `http://${displayHost}:${port}/dashboard`;
99
90
 
100
- let server;
101
-
102
- if (useStandalone) {
103
- server = spawn(process.execPath, ["--max-old-space-size=4096", standaloneServer], {
104
- cwd: appDir,
105
- stdio: showLog ? "inherit" : "ignore",
106
- env: { ...process.env, PORT: String(port), HOSTNAME: host }
107
- });
108
- } else if (useMainApp) {
109
- server = spawn(process.execPath, ["--max-old-space-size=4096", mainServerPath], {
110
- cwd: path.join(mainAppDir, ".next", "standalone"),
111
- stdio: showLog ? "inherit" : "ignore",
112
- env: { ...process.env, PORT: String(port), HOSTNAME: host }
113
- });
114
- } else {
115
- const isWin = process.platform === "win32";
116
- const npmCmd = isWin ? "npm.cmd" : "npm";
117
- server = spawn(npmCmd, ["run", "dev", "--", "--port", String(port)], {
118
- cwd: mainAppDir,
119
- stdio: showLog ? "inherit" : "ignore",
120
- shell: isWin,
121
- env: { ...process.env, PORT: String(port) }
122
- });
91
+ if (!useStandalone) {
92
+ console.error("\n Error: Standalone build not found.");
93
+ console.error(" Please run 'npm run build:cli' first.\n");
94
+ process.exit(1);
123
95
  }
124
96
 
97
+ const server = spawn(process.execPath, ["--max-old-space-size=4096", standaloneServer], {
98
+ cwd: appDir,
99
+ stdio: showLog ? "inherit" : "ignore",
100
+ env: { ...process.env, PORT: String(port), HOSTNAME: host }
101
+ });
102
+
125
103
  server.on("error", (err) => {
126
104
  console.error("Failed to start server:", err.message);
127
105
  process.exit(1);
package/dev.log ADDED
@@ -0,0 +1,15 @@
1
+
2
+ > kentutai-app@1.0.0 dev
3
+ > next dev --webpack --port 20123
4
+
5
+ ⨯ Failed to start server
6
+ Error: listen EADDRINUSE: address already in use :::20123
7
+ at <unknown> (Error: listen EADDRINUSE: address already in use :::20123)
8
+ at new Promise (<anonymous>) {
9
+ code: 'EADDRINUSE',
10
+ errno: -4091,
11
+ syscall: 'listen',
12
+ address: '::',
13
+ port: 20123
14
+ }
15
+ [?25h
package/next-env.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ import "./.next/types/routes.d.ts";
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
package/opencode.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "name": "Kentut-Router",
4
+ "version": "1.0.0",
5
+ "description": "KentutAI web dashboard - FREE AI Router & Token Saver",
6
+ "skills": [
7
+ "skills/9router/SKILL.md",
8
+ "skills/9router-chat/SKILL.md",
9
+ "skills/9router-embeddings/SKILL.md",
10
+ "skills/9router-image/SKILL.md",
11
+ "skills/9router-stt/SKILL.md",
12
+ "skills/9router-tts/SKILL.md",
13
+ "skills/9router-web-fetch/SKILL.md",
14
+ "skills/9router-web-search/SKILL.md"
15
+ ],
16
+ "omo": {
17
+ "plans_dir": ".omo/plans",
18
+ "boulder_file": ".omo/boulder.json",
19
+ "evidence_dir": ".omo/evidence",
20
+ "drafts_dir": ".omo/drafts"
21
+ }
22
+ }
package/package.json CHANGED
@@ -1,19 +1,11 @@
1
1
  {
2
2
  "name": "kentutai-app",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "KentutAI web dashboard",
5
5
  "private": false,
6
6
  "bin": {
7
7
  "kentutai": "./bin.js"
8
8
  },
9
- "files": [
10
- "bin.js",
11
- "cli/",
12
- "public/",
13
- "README.md",
14
- "LICENSE",
15
- "package.json"
16
- ],
17
9
  "scripts": {
18
10
  "dev": "next dev --webpack --port 20123",
19
11
  "build": "next build",
@@ -0,0 +1,2 @@
1
+ [Tunnel] cloudflared exited unexpectedly, scheduling respawn
2
+ [Tunnel] direct URL not reachable yet, continuing via publicUrl