pulse-cli-divakar 1.0.2 → 1.0.4
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/package.json +8 -6
- package/src/cli/chat/chat-with-aiAgent.js +0 -1
- package/src/cli/chat/chat-with-aitool.js +1 -1
- package/src/cli/chat/utils/chataiutils.js +40 -19
- package/src/cli/commands/ai/wakeup.js +77 -73
- package/src/cli/commands/auth/login.js +2 -3
- package/src/cli/commands/auth/whoami.js +24 -18
- package/src/cli/commands/config/config.js +72 -0
- package/src/cli/main.js +3 -1
- package/src/config/google.config.js +21 -6
- package/src/service/chat.service.js +120 -0
- package/src/generated/prisma/browser.ts +0 -24
- package/src/generated/prisma/client.d.ts +0 -1
- package/src/generated/prisma/client.js +0 -5
- package/src/generated/prisma/client.ts +0 -48
- package/src/generated/prisma/commonInputTypes.ts +0 -92
- package/src/generated/prisma/default.d.ts +0 -1
- package/src/generated/prisma/default.js +0 -5
- package/src/generated/prisma/edge.d.ts +0 -1
- package/src/generated/prisma/edge.js +0 -234
- package/src/generated/prisma/enums.ts +0 -15
- package/src/generated/prisma/index-browser.js +0 -260
- package/src/generated/prisma/index.d.ts +0 -13151
- package/src/generated/prisma/index.js +0 -234
- package/src/generated/prisma/internal/class.ts +0 -204
- package/src/generated/prisma/internal/prismaNamespace.ts +0 -804
- package/src/generated/prisma/internal/prismaNamespaceBrowser.ts +0 -95
- package/src/generated/prisma/models/Test.ts +0 -1069
- package/src/generated/prisma/models.ts +0 -12
- package/src/generated/prisma/package.json +0 -139
- package/src/generated/prisma/query_compiler_fast_bg.js +0 -2
- package/src/generated/prisma/query_compiler_fast_bg.wasm +0 -0
- package/src/generated/prisma/query_compiler_fast_bg.wasm-base64.js +0 -2
- package/src/generated/prisma/runtime/client.d.ts +0 -3490
- package/src/generated/prisma/runtime/client.js +0 -105
- package/src/generated/prisma/runtime/index-browser.d.ts +0 -90
- package/src/generated/prisma/runtime/index-browser.js +0 -6
- package/src/generated/prisma/runtime/wasm-compiler-edge.js +0 -100
- package/src/generated/prisma/schema.prisma +0 -119
- package/src/generated/prisma/wasm-edge-light-loader.mjs +0 -5
- package/src/generated/prisma/wasm-worker-loader.mjs +0 -5
- package/src/index.js +0 -66
- package/src/lib/auth.js +0 -29
- package/src/lib/db.js +0 -9
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pulse-cli-divakar",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"main": "src/
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"main": "./src/cli/main.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"pulse": "./src/cli/main.js"
|
|
7
7
|
},
|
|
@@ -47,10 +47,12 @@
|
|
|
47
47
|
"prisma": "^7.10.1"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
"src/cli",
|
|
51
|
+
"src/service",
|
|
52
|
+
"src/lib/token.js",
|
|
53
|
+
"src/config/agent-config.js",
|
|
54
|
+
"src/config/google.config.js",
|
|
55
|
+
"src/config/tool.config.js"
|
|
54
56
|
]
|
|
55
57
|
|
|
56
58
|
}
|
|
@@ -16,7 +16,6 @@ import { markedTerminal } from "marked-terminal";
|
|
|
16
16
|
import { AIService } from "../ai/google-service.js";
|
|
17
17
|
import { ChatService } from "../../service/chat.service.js";
|
|
18
18
|
import { getStoredToken } from "../../lib/token.js";
|
|
19
|
-
import { prisma } from "../../lib/db.js";
|
|
20
19
|
import { getUserFromToken, saveMessage } from "./utils/chataiutils.js";
|
|
21
20
|
import { generateApplication } from "../../config/agent-config.js";
|
|
22
21
|
|
|
@@ -7,7 +7,7 @@ import {markedTerminal} from "marked-terminal"
|
|
|
7
7
|
import { AIService } from "../ai/google-service.js";
|
|
8
8
|
import { ChatService } from "../../service/chat.service.js";
|
|
9
9
|
import { getStoredToken } from "../../lib/token.js";
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
|
|
12
12
|
import {availableTools,getEnabledToolNames,getEnabledTools,enableTools,resetTools} from "../../config/tool.config.js"
|
|
13
13
|
import { displayMessages, getUserFromToken ,updateConversationTitle,saveMessage} from "./utils/chataiutils.js";
|
|
@@ -1,40 +1,61 @@
|
|
|
1
1
|
import yoctoSpinner from "yocto-spinner";
|
|
2
|
-
import { getStoredToken } from "../../../lib/token.js";
|
|
3
|
-
import { prisma } from "../../../lib/db.js";
|
|
4
2
|
import { AIService } from "../../ai/google-service.js";
|
|
5
3
|
import { ChatService } from "../../../service/chat.service.js";
|
|
6
4
|
import { isCancel, text } from "@clack/prompts";
|
|
7
5
|
import chalk from "chalk";
|
|
8
6
|
import boxen from "boxen";
|
|
9
7
|
import { marked } from "marked";
|
|
8
|
+
import { requireAuth } from "../../../lib/token.js";
|
|
9
|
+
import { URL } from "../../commands/auth/login.js";
|
|
10
10
|
|
|
11
11
|
const aiService=new AIService()
|
|
12
12
|
const chatService=new ChatService()
|
|
13
13
|
|
|
14
14
|
export async function getUserFromToken() {
|
|
15
|
-
const token=await
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const token = await requireAuth();
|
|
16
|
+
|
|
17
|
+
const spinner = yoctoSpinner({
|
|
18
|
+
text: "Authenticating..."
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
spinner.start();
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const serverUrl = URL.replace(/\/+$/, "");
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
const response = await fetch(`${serverUrl}/api/cli/me`, {
|
|
27
|
+
headers: {
|
|
28
|
+
Authorization: `Bearer ${token.access_token}`,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
spinner.error("Authentication failed");
|
|
34
|
+
|
|
35
|
+
if (response.status === 401) {
|
|
36
|
+
throw new Error("Session invalid or expired. Please login again.");
|
|
26
37
|
}
|
|
38
|
+
|
|
39
|
+
throw new Error(`Failed to fetch user: HTTP ${response.status}`);
|
|
27
40
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
|
|
42
|
+
const user = await response.json();
|
|
43
|
+
|
|
44
|
+
if (!user?.id) {
|
|
45
|
+
spinner.error("User not found");
|
|
46
|
+
throw new Error("User not found. Please login again.");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
spinner.success(`Welcome back, ${user.name}!`);
|
|
50
|
+
return user;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (spinner.isSpinning) {
|
|
53
|
+
spinner.error("Failed to authenticate");
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
32
56
|
}
|
|
33
|
-
spinner.success(`Welcome back, ${user.name}!`)
|
|
34
|
-
return user;
|
|
35
57
|
}
|
|
36
58
|
|
|
37
|
-
|
|
38
59
|
export async function getAIResponse(conversationId) {
|
|
39
60
|
const spinner = yoctoSpinner({
|
|
40
61
|
text: "AI is thinking...",
|
|
@@ -1,85 +1,89 @@
|
|
|
1
|
-
import chalk from "chalk"
|
|
2
|
-
import { Command } from "commander"
|
|
3
|
-
import yoctoSpinner from "yocto-spinner"
|
|
4
|
-
import { getStoredToken } from "../../../lib/token.js"
|
|
5
|
-
import { select } from "@clack/prompts"
|
|
6
|
-
import {
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import yoctoSpinner from "yocto-spinner";
|
|
4
|
+
import { getStoredToken, requireAuth } from "../../../lib/token.js";
|
|
5
|
+
import { select } from "@clack/prompts";
|
|
6
|
+
import { URL } from "../auth/login.js";
|
|
7
7
|
|
|
8
|
+
const wakeUpAction = async () => {
|
|
9
|
+
const token = await requireAuth();
|
|
10
|
+
if (!token?.access_token) {
|
|
11
|
+
console.log(chalk.red("Not Authenticated.Please login"));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
8
14
|
|
|
15
|
+
const spinner = yoctoSpinner({ text: "Fetching user information..." });
|
|
16
|
+
spinner.start();
|
|
9
17
|
|
|
10
|
-
const
|
|
11
|
-
const token=await getStoredToken()
|
|
12
|
-
if(!token?.access_token){
|
|
13
|
-
console.log(chalk.red("Not Authenticated.Please login"))
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
18
|
+
const serverUrl = URL.replace(/\/+$/, "");
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const response = await fetch(`${serverUrl}/api/cli/me`, {
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${token.access_token}`,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
sessions:{
|
|
23
|
-
some:{
|
|
24
|
-
token:token.access_token,
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
select:{
|
|
29
|
-
id:true,
|
|
30
|
-
name:true,
|
|
31
|
-
email:true,
|
|
32
|
-
image:true
|
|
33
|
-
}
|
|
34
|
-
})
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
spinner.stop();
|
|
35
28
|
|
|
36
|
-
if(
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
if (response.status === 401) {
|
|
30
|
+
console.log(chalk.red("Session invalid or expired. Please login again."));
|
|
31
|
+
} else {
|
|
32
|
+
console.log(chalk.red(`Failed to fetch user: HTTP ${response.status}`));
|
|
39
33
|
}
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
hint:"Simple chat with AI"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
value:"tool",
|
|
54
|
-
label:"Tool Calling",
|
|
55
|
-
hint:"Chat with tools.(Google Search,Code Execution)"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
value:"agent",
|
|
59
|
-
label:"Agentic Mode",
|
|
60
|
-
hint:"Advanced AI agent."
|
|
61
|
-
}
|
|
62
|
-
]
|
|
63
|
-
})
|
|
38
|
+
const user = await response.json();
|
|
39
|
+
if (!user?.id) {
|
|
40
|
+
spinner.stop();
|
|
41
|
+
console.log(chalk.red("User not found."));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
64
44
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
45
|
+
spinner.stop();
|
|
46
|
+
console.log(chalk.green(`Welcome back, ${user.name}!\n`));
|
|
47
|
+
|
|
48
|
+
const choice = await select({
|
|
49
|
+
message: "Select an Option:",
|
|
50
|
+
options: [
|
|
51
|
+
{
|
|
52
|
+
value: "chat",
|
|
53
|
+
label: "Chat",
|
|
54
|
+
hint: "Simple chat with AI",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
value: "tool",
|
|
58
|
+
label: "Tool Calling",
|
|
59
|
+
hint: "Chat with tools.(Google Search,Code Execution)",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
value: "agent",
|
|
63
|
+
label: "Agentic Mode",
|
|
64
|
+
hint: "Advanced AI agent.",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
switch (choice) {
|
|
70
|
+
case "chat":
|
|
71
|
+
const { startChat } = await import("../../chat/chat-with-ai.js");
|
|
72
|
+
await startChat("chat");
|
|
73
|
+
break;
|
|
74
|
+
case "tool":
|
|
75
|
+
const { startToolChat } = await import("../../chat/chat-with-aitool.js");
|
|
81
76
|
|
|
77
|
+
await startToolChat();
|
|
78
|
+
break;
|
|
79
|
+
case "agent":
|
|
80
|
+
const { startAgentChat } =
|
|
81
|
+
await import("../../chat/chat-with-aiAgent.js");
|
|
82
|
+
await startAgentChat();
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
82
86
|
|
|
83
|
-
export const wakeUp=new Command("wakeup")
|
|
84
|
-
.description("Wake up the AI.")
|
|
85
|
-
.action(wakeUpAction)
|
|
87
|
+
export const wakeUp = new Command("wakeup")
|
|
88
|
+
.description("Wake up the AI.")
|
|
89
|
+
.action(wakeUpAction);
|
|
@@ -13,7 +13,6 @@ import yoctoSpinner from "yocto-spinner";
|
|
|
13
13
|
import * as z from "zod/v4";
|
|
14
14
|
import dotenv from "dotenv";
|
|
15
15
|
|
|
16
|
-
import { prisma } from "../../../lib/db.js";
|
|
17
16
|
import { clearStoredToken, getStoredToken, isTokenExpired, requireAuth, storeToken } from "../../../lib/token.js";
|
|
18
17
|
import { pollForToken } from "../utils/polling.js";
|
|
19
18
|
|
|
@@ -42,8 +41,8 @@ export async function loginAction() {
|
|
|
42
41
|
|
|
43
42
|
intro(chalk.bold("🔏 Auth CLI Login."));
|
|
44
43
|
|
|
45
|
-
const existingToken =
|
|
46
|
-
const expired = isTokenExpired();
|
|
44
|
+
const existingToken =await getStoredToken();
|
|
45
|
+
const expired = await isTokenExpired();
|
|
47
46
|
|
|
48
47
|
if (existingToken && !expired) {
|
|
49
48
|
const shouldReAuth = await confirm({
|
|
@@ -1,32 +1,38 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { requireAuth } from "../../../lib/token.js";
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import { URL } from "./login.js";
|
|
6
6
|
|
|
7
|
-
export async function whoamiAction() {
|
|
7
|
+
export async function whoamiAction(options) {
|
|
8
8
|
const token=await requireAuth();
|
|
9
9
|
if(!token?.access_token){
|
|
10
10
|
console.log("No access token found.Please login");
|
|
11
11
|
process.exit(1);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
|
|
15
|
+
const serverUrl = (options.serverUrl || URL).replace(/\/+$/, "");
|
|
16
|
+
|
|
17
|
+
const response = await fetch(`${serverUrl}/api/cli/me`, {
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: `Bearer ${token.access_token}`,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
console.log(
|
|
25
|
+
chalk.red(
|
|
26
|
+
response.status === 401
|
|
27
|
+
? "Session invalid or expired. Please login again."
|
|
28
|
+
: `Failed to fetch user: HTTP ${response.status}`
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const user = await response.json();
|
|
35
|
+
|
|
30
36
|
|
|
31
37
|
console.log(
|
|
32
38
|
chalk.bold.greenBright(`\n 👤User: ${user.name}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
cancel,
|
|
4
|
+
intro,
|
|
5
|
+
isCancel,
|
|
6
|
+
outro,
|
|
7
|
+
password,
|
|
8
|
+
} from "@clack/prompts";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import fs from "node:fs/promises";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
|
|
15
|
+
const CONFIG_DIR = path.join(os.homedir(), ".pulse");
|
|
16
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
17
|
+
|
|
18
|
+
export async function configAction() {
|
|
19
|
+
intro(chalk.bold("⚙️ Pulse Configuration"));
|
|
20
|
+
|
|
21
|
+
const apiKey = await password({
|
|
22
|
+
message: "Enter your Google Gemini API key:",
|
|
23
|
+
validate(value) {
|
|
24
|
+
if (!value?.trim()) return "API key cannot be empty.";
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (isCancel(apiKey)) {
|
|
29
|
+
cancel("Configuration cancelled.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
35
|
+
|
|
36
|
+
let existingConfig = {};
|
|
37
|
+
try {
|
|
38
|
+
existingConfig = JSON.parse(
|
|
39
|
+
await fs.readFile(CONFIG_FILE, "utf8"),
|
|
40
|
+
);
|
|
41
|
+
} catch {
|
|
42
|
+
// No existing config file yet.
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await fs.writeFile(
|
|
46
|
+
CONFIG_FILE,
|
|
47
|
+
JSON.stringify(
|
|
48
|
+
{
|
|
49
|
+
...existingConfig,
|
|
50
|
+
googleApiKey: apiKey.trim(),
|
|
51
|
+
},
|
|
52
|
+
null,
|
|
53
|
+
2,
|
|
54
|
+
),
|
|
55
|
+
{ encoding: "utf8", mode: 0o600 },
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
outro(chalk.green("Google API key saved successfully."));
|
|
59
|
+
console.log(chalk.gray(`Config location: ${CONFIG_FILE}`));
|
|
60
|
+
console.log(chalk.gray("You can now run Pulse from any folder."));
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(
|
|
63
|
+
chalk.red("Could not save configuration:"),
|
|
64
|
+
error.message,
|
|
65
|
+
);
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const config = new Command("config")
|
|
71
|
+
.description("Configure your Google Gemini API key")
|
|
72
|
+
.action(configAction);
|
package/src/cli/main.js
CHANGED
|
@@ -9,6 +9,7 @@ import { login} from "./commands/auth/login.js"
|
|
|
9
9
|
import { logout } from "./commands/auth/logout.js"
|
|
10
10
|
import { whoami } from "./commands/auth/whoami.js"
|
|
11
11
|
import { wakeUp } from "./commands/ai/wakeup.js"
|
|
12
|
+
import {config} from "./commands/config/config.js"
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
dotenv.config()
|
|
@@ -26,12 +27,13 @@ async function main() {
|
|
|
26
27
|
console.log(chalk.magenta("A Cli Based AI application.\n"))
|
|
27
28
|
|
|
28
29
|
const program=new Command("pulse")
|
|
29
|
-
program.version("
|
|
30
|
+
program.version("1.0.4")
|
|
30
31
|
.description("Pulse is a Cli based application")
|
|
31
32
|
.addCommand(login)
|
|
32
33
|
.addCommand(logout)
|
|
33
34
|
.addCommand(whoami)
|
|
34
35
|
.addCommand(wakeUp)
|
|
36
|
+
.addCommand(config)
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
program.action(()=>{
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import dotenv from "dotenv"
|
|
2
|
-
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
googleApiKey:process.env.GOOGLE_GENERATIVE_AI_API_KEY,
|
|
6
|
-
model:process.env.ORBITAL_MODEL || "gemini-2.5-flash"
|
|
6
|
+
dotenv.config();
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const configPath = path.join(os.homedir(), ".pulse", "config.json");
|
|
9
|
+
|
|
10
|
+
let savedConfig = {};
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
savedConfig = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
14
|
+
} catch {
|
|
15
|
+
// Configuration has not been created yet.
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const config = {
|
|
19
|
+
googleApiKey:
|
|
20
|
+
process.env.GOOGLE_GENERATIVE_AI_API_KEY || savedConfig.googleApiKey,
|
|
21
|
+
|
|
22
|
+
model: process.env.ORBITAL_MODEL || savedConfig.model || "gemini-2.5-flash",
|
|
23
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { URL } from "../cli/commands/auth/login.js";
|
|
2
|
+
import { getStoredToken } from "../lib/token.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export class ChatService{
|
|
7
|
+
async request(endpoint, options = {}) {
|
|
8
|
+
const token = await getStoredToken();
|
|
9
|
+
|
|
10
|
+
if (!token?.access_token) {
|
|
11
|
+
throw new Error("Not authenticated. Please run 'pulse login' first.");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const response = await fetch(
|
|
15
|
+
`${URL.replace(/\/+$/, "")}/api/cli${endpoint}`,
|
|
16
|
+
{
|
|
17
|
+
...options,
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
Authorization: `Bearer ${token.access_token}`,
|
|
21
|
+
...options.headers,
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const result = await response.json().catch(() => ({}));
|
|
28
|
+
throw new Error(result.error || `API request failed: HTTP ${response.status}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (response.status === 204) return null;
|
|
32
|
+
|
|
33
|
+
return response.json();
|
|
34
|
+
}
|
|
35
|
+
async createConversation(userId, mode = "chat", title = null) {
|
|
36
|
+
return this.request("/conversations", {
|
|
37
|
+
method: "POST",
|
|
38
|
+
body: JSON.stringify({
|
|
39
|
+
mode,
|
|
40
|
+
title: title || `New ${mode} conversation`,
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getOrCreateConversation(userId, conversationId = null, mode = "chat") {
|
|
46
|
+
if (conversationId) {
|
|
47
|
+
return this.request(
|
|
48
|
+
`/conversations/${encodeURIComponent(conversationId)}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return this.createConversation(userId, mode);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// user messages add to convo like {role:user ,message:"jhfdks"}
|
|
56
|
+
async addMessage(conversationId, role, content) {
|
|
57
|
+
const contentStr =
|
|
58
|
+
typeof content === "string" ? content : JSON.stringify(content);
|
|
59
|
+
|
|
60
|
+
return this.request(
|
|
61
|
+
`/conversations/${encodeURIComponent(conversationId)}/messages`,
|
|
62
|
+
{
|
|
63
|
+
method: "POST",
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
role,
|
|
66
|
+
content: contentStr,
|
|
67
|
+
}),
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async getMessages(conversationId) {
|
|
74
|
+
const messages = await this.request(
|
|
75
|
+
`/conversations/${encodeURIComponent(conversationId)}/messages`
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
return messages.map((msg) => ({
|
|
79
|
+
...msg,
|
|
80
|
+
content: this.parseContent(msg.content),
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
async getUserConversation(userId) {
|
|
84
|
+
return this.request("/conversations");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async deleteConversation(conversationId, userId) {
|
|
88
|
+
return this.request(
|
|
89
|
+
`/conversations/${encodeURIComponent(conversationId)}`,
|
|
90
|
+
{
|
|
91
|
+
method: "DELETE",
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
async updateTitle(conversationId, title) {
|
|
96
|
+
return this.request(
|
|
97
|
+
`/conversations/${encodeURIComponent(conversationId)}`,
|
|
98
|
+
{
|
|
99
|
+
method: "PATCH",
|
|
100
|
+
body: JSON.stringify({ title }),
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
parseContent(content){
|
|
106
|
+
try {
|
|
107
|
+
return JSON.parse(content)
|
|
108
|
+
} catch (error) {
|
|
109
|
+
return content;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
formatMessageForAI(messages){
|
|
114
|
+
return messages.map((msg)=>({
|
|
115
|
+
role:msg.role,
|
|
116
|
+
content:typeof msg.content==="string" ? msg.content : JSON.stringify(msg.content)
|
|
117
|
+
}))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
|
3
|
-
/* eslint-disable */
|
|
4
|
-
// biome-ignore-all lint: generated file
|
|
5
|
-
// @ts-nocheck
|
|
6
|
-
/*
|
|
7
|
-
* This file should be your main import to use Prisma-related types and utilities in a browser.
|
|
8
|
-
* Use it to get access to models, enums, and input types.
|
|
9
|
-
*
|
|
10
|
-
* This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only.
|
|
11
|
-
* See `client.ts` for the standard, server-side entry point.
|
|
12
|
-
*
|
|
13
|
-
* 🟢 You can import this file directly.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import * as Prisma from './internal/prismaNamespaceBrowser.ts'
|
|
17
|
-
export { Prisma }
|
|
18
|
-
export * as $Enums from './enums.ts'
|
|
19
|
-
export * from './enums.ts';
|
|
20
|
-
/**
|
|
21
|
-
* Model Test
|
|
22
|
-
*
|
|
23
|
-
*/
|
|
24
|
-
export type Test = Prisma.TestModel
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./index"
|