pulse-cli-divakar 0.0.0-stage ā 1.0.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.
- package/package.json +55 -6
- package/src/cli/ai/google-service.js +127 -0
- package/src/cli/chat/chat-with-ai.js +57 -0
- package/src/cli/chat/chat-with-aiAgent.js +206 -0
- package/src/cli/chat/chat-with-aitool.js +307 -0
- package/src/cli/chat/utils/chataiutils.js +212 -0
- package/src/cli/commands/ai/wakeup.js +83 -0
- package/src/cli/commands/auth/login.js +157 -0
- package/src/cli/commands/auth/logout.js +42 -0
- package/src/cli/commands/auth/whoami.js +44 -0
- package/src/cli/commands/utils/polling.js +77 -0
- package/src/cli/main.js +46 -0
- package/src/config/agent-config.js +170 -0
- package/src/config/google.config.js +8 -0
- package/src/config/tool.config.js +99 -0
- package/src/index.js +66 -0
- package/src/lib/auth.js +29 -0
- package/src/lib/db.js +9 -0
- package/src/lib/token.js +84 -0
- package/README.md +0 -3
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { cancel, confirm, intro, isCancel, outro, select } from "@clack/prompts";
|
|
2
|
+
import { logger } from "better-auth";
|
|
3
|
+
import { createAuthClient } from "better-auth/client";
|
|
4
|
+
import { deviceAuthorizationClient } from "better-auth/client/plugins";
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { Command, program } from "commander";
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
import open from "open";
|
|
10
|
+
import os from "os";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import yoctoSpinner from "yocto-spinner";
|
|
13
|
+
import * as z from "zod/v4";
|
|
14
|
+
import dotenv from "dotenv";
|
|
15
|
+
|
|
16
|
+
import { prisma } from "../../../lib/db.js";
|
|
17
|
+
import { clearStoredToken, getStoredToken, isTokenExpired, requireAuth, storeToken } from "../../../lib/token.js";
|
|
18
|
+
import { pollForToken } from "../utils/polling.js";
|
|
19
|
+
|
|
20
|
+
dotenv.config();
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
// To store in local computer using below 4 variables
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export const URL = process.env.BACK_END || "https://pulse-4t51.onrender.com";
|
|
27
|
+
const CLIENT_ID = process.env.GITHUB_CLIENT_ID || "Ov23lijaPrTkzWootiuZ"
|
|
28
|
+
// create a .better-auth folder in home directry not actual folder create just a link like C:\Users\YourUser\.better-auth
|
|
29
|
+
export const CONFIG_DIR = path.join(os.homedir(), ".better-auth");
|
|
30
|
+
// save to token.json
|
|
31
|
+
export const TOKEN_FILE = path.join(CONFIG_DIR, "token.json");
|
|
32
|
+
|
|
33
|
+
export async function loginAction() {
|
|
34
|
+
const options = z.object({
|
|
35
|
+
serverUrl: z.string().optional(),
|
|
36
|
+
clientId: z.string().optional(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const serverUrl = options.serverUrl || URL;
|
|
40
|
+
const clientId = options.clientId || CLIENT_ID;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
intro(chalk.bold("š Auth CLI Login."));
|
|
44
|
+
|
|
45
|
+
const existingToken = getStoredToken();
|
|
46
|
+
const expired = isTokenExpired();
|
|
47
|
+
|
|
48
|
+
if (existingToken && !expired) {
|
|
49
|
+
const shouldReAuth = await confirm({
|
|
50
|
+
message: "You are already loggedIn. Do You want to login Again?",
|
|
51
|
+
initialValue: false,
|
|
52
|
+
});
|
|
53
|
+
// User choose No OR Cancel the command
|
|
54
|
+
if (isCancel(shouldReAuth) || !shouldReAuth) {
|
|
55
|
+
cancel("Login Cancelled..");
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const authClient = createAuthClient({
|
|
61
|
+
baseURL: serverUrl,
|
|
62
|
+
plugins: [deviceAuthorizationClient()],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const spinner = yoctoSpinner({ text: "Requesting device authorization..." });
|
|
66
|
+
spinner.start();
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const { data, error } = await authClient.device.code({
|
|
70
|
+
client_id: clientId,
|
|
71
|
+
scope: "openid profile email",
|
|
72
|
+
});
|
|
73
|
+
spinner.stop();
|
|
74
|
+
|
|
75
|
+
if (error || !data) {
|
|
76
|
+
logger.error(
|
|
77
|
+
`Failed to request device authorization: ${error.error_description}`,
|
|
78
|
+
);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const {
|
|
83
|
+
device_code,
|
|
84
|
+
user_code,
|
|
85
|
+
verification_uri,
|
|
86
|
+
verification_uri_complete,
|
|
87
|
+
expires_in,
|
|
88
|
+
interval,
|
|
89
|
+
} = data;
|
|
90
|
+
|
|
91
|
+
console.log(chalk.cyan("Device authorization is required."));
|
|
92
|
+
|
|
93
|
+
console.log(
|
|
94
|
+
`Please visit ${chalk.underline.blue(verification_uri || verification_uri_complete)} `,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
console.log(`Enter Code ${chalk.bold.green(user_code)}`);
|
|
98
|
+
|
|
99
|
+
const shouldOpen = await confirm({
|
|
100
|
+
message: "Open Browser automatically",
|
|
101
|
+
initialValue: true,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (!isCancel(shouldOpen) && shouldOpen) {
|
|
105
|
+
const urlToOpen = verification_uri_complete || verification_uri;
|
|
106
|
+
await open(urlToOpen);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log(
|
|
110
|
+
chalk.gray(
|
|
111
|
+
`Waiting for authorization (expires in ${Math.floor(
|
|
112
|
+
expires_in / 60,
|
|
113
|
+
)} minutes)....`,
|
|
114
|
+
),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const token = await pollForToken(
|
|
118
|
+
authClient,
|
|
119
|
+
device_code,
|
|
120
|
+
clientId,
|
|
121
|
+
interval,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
if(token){
|
|
125
|
+
const saved=await storeToken(token)
|
|
126
|
+
if (!saved) {
|
|
127
|
+
console.log(
|
|
128
|
+
chalk.yellow("\nā ļø Warning: Could not save authentication token.")
|
|
129
|
+
);
|
|
130
|
+
console.log(
|
|
131
|
+
chalk.yellow("You may need to login again on next use.")
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
outro(chalk.green("Login successfull!"))
|
|
136
|
+
|
|
137
|
+
console.log(chalk.gray(`\n Token Saved to: ${TOKEN_FILE}`))
|
|
138
|
+
console.log(chalk.gray("You can now use Pulse Commands without logging-in again.\n "))
|
|
139
|
+
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
} catch (error) {
|
|
143
|
+
spinner.stop();
|
|
144
|
+
console.error(chalk.red("\nLogin failed:"), error.message);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
export const login = new Command("login")
|
|
151
|
+
.description("Login to Better-Auth")
|
|
152
|
+
.option("--server-url <url>", "The Better Auth server URL", URL)
|
|
153
|
+
.option("--client-id <id>", "The OAuth client ID", CLIENT_ID)
|
|
154
|
+
.action(loginAction)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { confirm, intro, isCancel, outro } from "@clack/prompts";
|
|
2
|
+
import { clearStoredToken, getStoredToken } from "../../../lib/token.js";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import dotenv from "dotenv";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
dotenv.config();
|
|
10
|
+
|
|
11
|
+
export async function logoutAction() {
|
|
12
|
+
intro(chalk.bold("šLogout"));
|
|
13
|
+
|
|
14
|
+
const token=await getStoredToken();
|
|
15
|
+
if(!token){
|
|
16
|
+
console.log(chalk.yellow("You're not logged in.Please LogIn First"))
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
const shouldLogout=await confirm({
|
|
20
|
+
message:"Are you sure , do you want to logout?",
|
|
21
|
+
initialValue:false
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
if(isCancel(shouldLogout) || !shouldLogout){
|
|
25
|
+
cancel("Logout Cancelled")
|
|
26
|
+
process.exit(0)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const cleared=await clearStoredToken();
|
|
30
|
+
if(cleared){
|
|
31
|
+
outro(chalk.green("ā
Successfully logged out!"))
|
|
32
|
+
}
|
|
33
|
+
else{
|
|
34
|
+
console.log(chalk.yellow("ā Could not clear token file."))
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export const logout = new Command("logout")
|
|
41
|
+
.description("Logout and Clear stored credentials")
|
|
42
|
+
.action(logoutAction)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { prisma } from "../../../lib/db.js";
|
|
3
|
+
import { requireAuth } from "../../../lib/token.js";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { URL } from "./login.js";
|
|
6
|
+
|
|
7
|
+
export async function whoamiAction() {
|
|
8
|
+
const token=await requireAuth();
|
|
9
|
+
if(!token?.access_token){
|
|
10
|
+
console.log("No access token found.Please login");
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const user=await prisma.user.findFirst({
|
|
15
|
+
where:{
|
|
16
|
+
sessions:{
|
|
17
|
+
some:{
|
|
18
|
+
token:token.access_token,
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
select:{
|
|
23
|
+
id:true,
|
|
24
|
+
name:true,
|
|
25
|
+
email:true,
|
|
26
|
+
image:true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
console.log(
|
|
32
|
+
chalk.bold.greenBright(`\n š¤User: ${user.name}
|
|
33
|
+
š© Email: ${user.email}
|
|
34
|
+
šŖŖ ID: ${user.id}
|
|
35
|
+
`)
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export const whoami = new Command("whoami")
|
|
42
|
+
.description("Show current authenticated user")
|
|
43
|
+
.option("--server-url <url>", "The Better Auth server URL", URL)
|
|
44
|
+
.action(whoamiAction)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { logger } from "better-auth";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import yoctoSpinner from "yocto-spinner";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export async function pollForToken(
|
|
7
|
+
authClient,
|
|
8
|
+
deviceCode,
|
|
9
|
+
clientId,
|
|
10
|
+
initialIntervalue,
|
|
11
|
+
) {
|
|
12
|
+
let pollingInterval = initialIntervalue;
|
|
13
|
+
const spinner = yoctoSpinner({ text: "", color: "cyan" });
|
|
14
|
+
|
|
15
|
+
let dots = 0;
|
|
16
|
+
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const poll = async () => {
|
|
19
|
+
dots = (dots + 1) % 4;
|
|
20
|
+
spinner.text = chalk.gray(
|
|
21
|
+
`Polling for authorization${".".repeat(dots)}${" ".repeat(3 - dots)}`,
|
|
22
|
+
);
|
|
23
|
+
if (!spinner.isSpinning) spinner.start();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const { data, error } = await authClient.device.token({
|
|
27
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
28
|
+
device_code: deviceCode,
|
|
29
|
+
client_id: clientId,
|
|
30
|
+
fetchOptions: {
|
|
31
|
+
headers: {
|
|
32
|
+
"user-agent": `My CLI`,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (data?.access_token) {
|
|
38
|
+
console.log(
|
|
39
|
+
chalk.bold.yellow(`Your acess token: ${data.access_token}`),
|
|
40
|
+
);
|
|
41
|
+
spinner.stop();
|
|
42
|
+
resolve(data);
|
|
43
|
+
return;
|
|
44
|
+
} else if (error) {
|
|
45
|
+
switch (error.error) {
|
|
46
|
+
case "authorization_pending":
|
|
47
|
+
// Continue polling
|
|
48
|
+
break;
|
|
49
|
+
case "slow_down":
|
|
50
|
+
pollingInterval += 5;
|
|
51
|
+
break;
|
|
52
|
+
case "access_denied":
|
|
53
|
+
console.error("Access was denied by the user");
|
|
54
|
+
return;
|
|
55
|
+
case "expired_token":
|
|
56
|
+
console.error(
|
|
57
|
+
"The device code has expired. Please try again.",
|
|
58
|
+
);
|
|
59
|
+
return;
|
|
60
|
+
default:
|
|
61
|
+
spinner.stop();
|
|
62
|
+
logger.error(`Error: ${error.error_description}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
spinner.stop();
|
|
68
|
+
logger.error(`Network error: ${error.message}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setTimeout(poll, pollingInterval * 1000);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
setTimeout(poll , pollingInterval * 1000);
|
|
76
|
+
});
|
|
77
|
+
}
|
package/src/cli/main.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import dotenv from "dotenv"
|
|
4
|
+
import chalk from "chalk" //to add colours
|
|
5
|
+
import figlet from "figlet" //to add banners
|
|
6
|
+
|
|
7
|
+
import {Command} from "commander" //to create a command
|
|
8
|
+
import { login} from "./commands/auth/login.js"
|
|
9
|
+
import { logout } from "./commands/auth/logout.js"
|
|
10
|
+
import { whoami } from "./commands/auth/whoami.js"
|
|
11
|
+
import { wakeUp } from "./commands/ai/wakeup.js"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
dotenv.config()
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
|
|
18
|
+
console.log(
|
|
19
|
+
chalk.greenBright(
|
|
20
|
+
figlet.textSync("Pulse CLI",{
|
|
21
|
+
font:"Standard",
|
|
22
|
+
horizontalLayout:"default"
|
|
23
|
+
})
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
console.log(chalk.magenta("A Cli Based AI application.\n"))
|
|
27
|
+
|
|
28
|
+
const program=new Command("pulse")
|
|
29
|
+
program.version("0.0.1")
|
|
30
|
+
.description("Pulse is a Cli based application")
|
|
31
|
+
.addCommand(login)
|
|
32
|
+
.addCommand(logout)
|
|
33
|
+
.addCommand(whoami)
|
|
34
|
+
.addCommand(wakeUp)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
program.action(()=>{
|
|
38
|
+
program.help();
|
|
39
|
+
})
|
|
40
|
+
await program.parseAsync(process.argv);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
main().catch((error)=>{
|
|
44
|
+
console.log(chalk.red("Error running Pulse Cli:"),error);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
})
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { generateText, Output } from "ai";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
const ApplicationSchema = z.object({
|
|
8
|
+
folderName: z.string().describe("Kebab-case folder name for the application"),
|
|
9
|
+
description: z.string().describe("Brief description of what was created"),
|
|
10
|
+
files: z
|
|
11
|
+
.array(
|
|
12
|
+
z.object({
|
|
13
|
+
path: z.string().describe("Relative file path (e.g., src/App.jsx)"),
|
|
14
|
+
content: z.string().describe("Complete file content"),
|
|
15
|
+
}),
|
|
16
|
+
)
|
|
17
|
+
.describe("All files needed for the application"),
|
|
18
|
+
setupCommands: z
|
|
19
|
+
.array(z.string())
|
|
20
|
+
.describe(
|
|
21
|
+
"Bash commands to setup and run (e.g., npm install, npm run dev)",
|
|
22
|
+
),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function printSystem(message) {
|
|
26
|
+
console.log(message);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function displayFileTree(files, folderName) {
|
|
30
|
+
printSystem(chalk.cyan("\nš Project Structure:"));
|
|
31
|
+
printSystem(chalk.white(`${folderName}/`));
|
|
32
|
+
|
|
33
|
+
const filesByDir = {};
|
|
34
|
+
files.forEach((file) => {
|
|
35
|
+
const parts = file.path.split("/");
|
|
36
|
+
const dir = parts.length > 1 ? parts.slice(0, -1).join("/") : "";
|
|
37
|
+
|
|
38
|
+
if (!filesByDir[dir]) {
|
|
39
|
+
filesByDir[dir] = [];
|
|
40
|
+
}
|
|
41
|
+
filesByDir[dir].push(parts[parts.length - 1]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
Object.keys(filesByDir)
|
|
45
|
+
.sort()
|
|
46
|
+
.forEach((dir) => {
|
|
47
|
+
if (dir) {
|
|
48
|
+
printSystem(chalk.white(`āāā ${dir}/`));
|
|
49
|
+
filesByDir[dir].forEach((file) => {
|
|
50
|
+
printSystem(chalk.white(`ā āāā ${file}`));
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
filesByDir[dir].forEach((file) => {
|
|
54
|
+
printSystem(chalk.white(`āāā ${file}`));
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async function createApplicationFiles(baseDir, folderName, files) {
|
|
62
|
+
const appDir = path.join(baseDir, folderName);
|
|
63
|
+
|
|
64
|
+
await fs.mkdir(appDir, { recursive: true });
|
|
65
|
+
printSystem(chalk.cyan(`\nš Created directory: ${folderName}/`));
|
|
66
|
+
|
|
67
|
+
for (const file of files) {
|
|
68
|
+
const filePath = path.join(appDir, file.path);
|
|
69
|
+
const fileDir = path.dirname(filePath);
|
|
70
|
+
|
|
71
|
+
await fs.mkdir(fileDir, { recursive: true });
|
|
72
|
+
await fs.writeFile(filePath, file.content, 'utf8');
|
|
73
|
+
printSystem(chalk.green(` ā ${file.path}`));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return appDir;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
export async function generateApplication(
|
|
81
|
+
description,
|
|
82
|
+
aiService,
|
|
83
|
+
cwd = process.cwd(),
|
|
84
|
+
) {
|
|
85
|
+
try {
|
|
86
|
+
printSystem(
|
|
87
|
+
chalk.cyan("\nš¤ Agent Mode: Generating your application...\n"),
|
|
88
|
+
);
|
|
89
|
+
printSystem(chalk.gray(`Request: ${description}\n`));
|
|
90
|
+
|
|
91
|
+
printSystem(chalk.magenta("š¤ Generating structured output...\n"));
|
|
92
|
+
|
|
93
|
+
const result = await generateText({
|
|
94
|
+
model: aiService.model,
|
|
95
|
+
output: Output.object({
|
|
96
|
+
schema: ApplicationSchema,
|
|
97
|
+
}),
|
|
98
|
+
prompt: `Create a complete, production-ready application for: ${description}
|
|
99
|
+
|
|
100
|
+
CRITICAL REQUIREMENTS:
|
|
101
|
+
1. Generate ALL files needed for the application to run
|
|
102
|
+
2. Include package.json with ALL dependencies and correct versions (if needed)
|
|
103
|
+
3. Include README.md with setup instructions
|
|
104
|
+
4. Include configuration files (.gitignore, etc.) if needed
|
|
105
|
+
5. Write clean, well-commented, production-ready code
|
|
106
|
+
6. Include error handling and input validation
|
|
107
|
+
7. Use modern JavaScript/TypeScript best practices
|
|
108
|
+
8. Make sure all imports and paths are correct
|
|
109
|
+
9. NO PLACEHOLDERS - everything must be complete and working
|
|
110
|
+
10. For simple HTML/CSS/JS projects, you can skip package.json if not needed
|
|
111
|
+
|
|
112
|
+
Provide:
|
|
113
|
+
- A meaningful kebab-case folder name
|
|
114
|
+
- All necessary files with complete content
|
|
115
|
+
- Setup commands (for example: cd folder, npm install, npm run dev OR just open index.html)
|
|
116
|
+
- Make it visually appealing and functional`,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const application = result.output;
|
|
120
|
+
|
|
121
|
+
printSystem(chalk.green(`\nā
Generated: ${application.folderName}\n`));
|
|
122
|
+
printSystem(chalk.gray(`Description: ${application.description}\n`));
|
|
123
|
+
|
|
124
|
+
if (!application.files || application.files.length === 0) {
|
|
125
|
+
throw new Error("No files were generated");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
printSystem(chalk.green(`Files: ${application.files.length}\n`));
|
|
129
|
+
|
|
130
|
+
displayFileTree(application.files, application.folderName);
|
|
131
|
+
|
|
132
|
+
printSystem(chalk.cyan(`\nš Creating files...\n`));
|
|
133
|
+
|
|
134
|
+
const appDir = await createApplicationFiles(
|
|
135
|
+
cwd,
|
|
136
|
+
application.folderName,
|
|
137
|
+
application.files,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
printSystem(chalk.green.bold(`\n⨠Application created successfully!\n`));
|
|
141
|
+
printSystem(chalk.cyan(`š Location: ${chalk.bold(appDir)}\n`));
|
|
142
|
+
|
|
143
|
+
if (application.setupCommands && application.setupCommands.length > 0) {
|
|
144
|
+
printSystem(chalk.cyan("š Next Steps:\n"));
|
|
145
|
+
printSystem(chalk.white("```bash"));
|
|
146
|
+
application.setupCommands.forEach((cmd) => {
|
|
147
|
+
printSystem(chalk.white(cmd));
|
|
148
|
+
});
|
|
149
|
+
printSystem(chalk.white("```\n"));
|
|
150
|
+
} else {
|
|
151
|
+
printSystem(chalk.yellow("ā¹ļø No setup commands provided\n"));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
folderName: application.folderName,
|
|
156
|
+
appDir,
|
|
157
|
+
files: application.files.map((f) => f.path),
|
|
158
|
+
commands: application.setupCommands || [],
|
|
159
|
+
success: true,
|
|
160
|
+
};
|
|
161
|
+
} catch (err) {
|
|
162
|
+
printSystem(
|
|
163
|
+
chalk.red(`\nā Error generating application: ${err.message}\n`),
|
|
164
|
+
);
|
|
165
|
+
if (err.stack) {
|
|
166
|
+
printSystem(chalk.dim(err.stack + "\n"));
|
|
167
|
+
}
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {google} from "@ai-sdk/google"
|
|
2
|
+
import chalk from "chalk"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const availableTools=[
|
|
6
|
+
{
|
|
7
|
+
id:"google_search",
|
|
8
|
+
name:"Google Search",
|
|
9
|
+
description:"Acess the latest information using Google Search.Usefull for current events,news ,and real-time information.",
|
|
10
|
+
getTool:()=>google.tools.googleSearch({}),
|
|
11
|
+
enabled:false,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'code_execution',
|
|
15
|
+
name: 'Code Execution',
|
|
16
|
+
description: 'Generate and execute Python code to perform calculations, solve problems, or provide accurate information.',
|
|
17
|
+
getTool: () => google.tools.codeExecution({}),
|
|
18
|
+
enabled: false,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'url_context',
|
|
22
|
+
name: 'URL Context',
|
|
23
|
+
description: 'Provide specific URLs that you want the model to analyze directly from the prompt. Supports up to 20 URLs per request.',
|
|
24
|
+
getTool: () => google.tools.urlContext({}),
|
|
25
|
+
enabled: false,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
export function getEnabledTools(){
|
|
33
|
+
const tools={}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
for(const toolConfig of availableTools){
|
|
37
|
+
if(toolConfig.enabled){
|
|
38
|
+
tools[toolConfig.id]=toolConfig.getTool()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (Object.keys(tools).length > 0) {
|
|
43
|
+
console.log(chalk.gray(`[DEBUG] Enabled tools: ${Object.keys(tools).join(', ')}`));
|
|
44
|
+
} else {
|
|
45
|
+
console.log(chalk.yellow('[DEBUG] No tools enabled'));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return Object.keys(tools).length > 0 ? tools : undefined;
|
|
49
|
+
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error(chalk.red('[ERROR] Failed to initialize tools:'), error.message);
|
|
52
|
+
console.error(chalk.yellow('Make sure you have @ai-sdk/google version 2.0+ installed'));
|
|
53
|
+
console.error(chalk.yellow('Run: npm install @ai-sdk/google@latest'));
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export function togggleTool(toolid){
|
|
60
|
+
const tool=availableTools.find(t=>t.id===toolid)
|
|
61
|
+
|
|
62
|
+
if(tool){
|
|
63
|
+
tool.enabled = !tool.enabled;
|
|
64
|
+
console.log(chalk.gray(`[DEBUG] Tool ${toolId} toggled to ${tool.enabled}`));
|
|
65
|
+
return tool.enabled;
|
|
66
|
+
}
|
|
67
|
+
console.log(chalk.red(`[DEBUG] Tool ${toolId} not found`));
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
export function enableTools(toolIds) {
|
|
73
|
+
console.log(chalk.gray('[DEBUG] enableTools called with:'), toolIds);
|
|
74
|
+
|
|
75
|
+
availableTools.forEach(tool => {
|
|
76
|
+
const wasEnabled = tool.enabled;
|
|
77
|
+
tool.enabled = toolIds.includes(tool.id);
|
|
78
|
+
|
|
79
|
+
if (tool.enabled !== wasEnabled) {
|
|
80
|
+
console.log(chalk.gray(`[DEBUG] ${tool.id}: ${wasEnabled} ā ${tool.enabled}`));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const enabledCount = availableTools.filter(t => t.enabled).length;
|
|
85
|
+
console.log(chalk.gray(`[DEBUG] Total tools enabled: ${enabledCount}/${availableTools.length}`));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function getEnabledToolNames() {
|
|
89
|
+
const names = availableTools.filter(t => t.enabled).map(t => t.name);
|
|
90
|
+
console.log(chalk.gray('[DEBUG] getEnabledToolNames returning:'), names);
|
|
91
|
+
return names;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function resetTools() {
|
|
95
|
+
availableTools.forEach(tool => {
|
|
96
|
+
tool.enabled = false;
|
|
97
|
+
});
|
|
98
|
+
console.log(chalk.gray('[DEBUG] All tools have been reset (disabled)'));
|
|
99
|
+
}
|