@agentforge-ai/cli 0.4.0 → 0.4.1
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/default/.env.example +11 -0
- package/dist/default/dashboard/app/components/DashboardLayout.tsx +245 -0
- package/dist/default/dashboard/app/components/ui/badge.tsx +26 -0
- package/dist/default/dashboard/app/components/ui/button.tsx +41 -0
- package/dist/default/dashboard/app/components/ui/card.tsx +44 -0
- package/dist/default/dashboard/app/components/ui/dialog.tsx +66 -0
- package/dist/default/dashboard/app/components/ui/input.tsx +21 -0
- package/dist/default/dashboard/app/components/ui/label.tsx +18 -0
- package/dist/default/dashboard/app/components/ui/select.tsx +75 -0
- package/dist/default/dashboard/app/components/ui/sheet.tsx +73 -0
- package/dist/default/dashboard/app/components/ui/switch.tsx +34 -0
- package/dist/default/dashboard/app/components/ui/table.tsx +60 -0
- package/dist/default/dashboard/app/components/ui/tabs.tsx +50 -0
- package/dist/default/dashboard/app/components/ui/tooltip.tsx +23 -0
- package/dist/default/dashboard/app/lib/utils.ts +6 -0
- package/dist/default/dashboard/app/main.tsx +35 -0
- package/dist/default/dashboard/app/routeTree.gen.ts +352 -0
- package/dist/default/dashboard/app/routes/__root.tsx +10 -0
- package/dist/default/dashboard/app/routes/agents.tsx +255 -0
- package/dist/default/dashboard/app/routes/chat.tsx +427 -0
- package/dist/default/dashboard/app/routes/connections.tsx +413 -0
- package/dist/default/dashboard/app/routes/cron.tsx +322 -0
- package/dist/default/dashboard/app/routes/files.tsx +203 -0
- package/dist/default/dashboard/app/routes/index.tsx +141 -0
- package/dist/default/dashboard/app/routes/projects.tsx +254 -0
- package/dist/default/dashboard/app/routes/sessions.tsx +272 -0
- package/dist/default/dashboard/app/routes/settings.tsx +583 -0
- package/dist/default/dashboard/app/routes/skills.tsx +252 -0
- package/dist/default/dashboard/app/routes/usage.tsx +181 -0
- package/dist/default/dashboard/app/styles/globals.css +93 -0
- package/dist/default/dashboard/index.html +13 -0
- package/dist/default/dashboard/package.json +36 -0
- package/dist/default/dashboard/postcss.config.js +6 -0
- package/dist/default/dashboard/tailwind.config.js +50 -0
- package/dist/default/dashboard/tsconfig.json +24 -0
- package/dist/default/dashboard/vite.config.ts +16 -0
- package/dist/default/package.json +5 -2
- package/dist/default/src/agent.ts +42 -2
- package/dist/index.js +135 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/.env.example +11 -0
- package/templates/default/dashboard/app/components/DashboardLayout.tsx +245 -0
- package/templates/default/dashboard/app/components/ui/badge.tsx +26 -0
- package/templates/default/dashboard/app/components/ui/button.tsx +41 -0
- package/templates/default/dashboard/app/components/ui/card.tsx +44 -0
- package/templates/default/dashboard/app/components/ui/dialog.tsx +66 -0
- package/templates/default/dashboard/app/components/ui/input.tsx +21 -0
- package/templates/default/dashboard/app/components/ui/label.tsx +18 -0
- package/templates/default/dashboard/app/components/ui/select.tsx +75 -0
- package/templates/default/dashboard/app/components/ui/sheet.tsx +73 -0
- package/templates/default/dashboard/app/components/ui/switch.tsx +34 -0
- package/templates/default/dashboard/app/components/ui/table.tsx +60 -0
- package/templates/default/dashboard/app/components/ui/tabs.tsx +50 -0
- package/templates/default/dashboard/app/components/ui/tooltip.tsx +23 -0
- package/templates/default/dashboard/app/lib/utils.ts +6 -0
- package/templates/default/dashboard/app/main.tsx +35 -0
- package/templates/default/dashboard/app/routeTree.gen.ts +352 -0
- package/templates/default/dashboard/app/routes/__root.tsx +10 -0
- package/templates/default/dashboard/app/routes/agents.tsx +255 -0
- package/templates/default/dashboard/app/routes/chat.tsx +427 -0
- package/templates/default/dashboard/app/routes/connections.tsx +413 -0
- package/templates/default/dashboard/app/routes/cron.tsx +322 -0
- package/templates/default/dashboard/app/routes/files.tsx +203 -0
- package/templates/default/dashboard/app/routes/index.tsx +141 -0
- package/templates/default/dashboard/app/routes/projects.tsx +254 -0
- package/templates/default/dashboard/app/routes/sessions.tsx +272 -0
- package/templates/default/dashboard/app/routes/settings.tsx +583 -0
- package/templates/default/dashboard/app/routes/skills.tsx +252 -0
- package/templates/default/dashboard/app/routes/usage.tsx +181 -0
- package/templates/default/dashboard/app/styles/globals.css +93 -0
- package/templates/default/dashboard/index.html +13 -0
- package/templates/default/dashboard/package.json +36 -0
- package/templates/default/dashboard/postcss.config.js +6 -0
- package/templates/default/dashboard/tailwind.config.js +50 -0
- package/templates/default/dashboard/tsconfig.json +24 -0
- package/templates/default/dashboard/vite.config.ts +16 -0
- package/templates/default/package.json +5 -2
- package/templates/default/src/agent.ts +42 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [react(), tsconfigPaths()],
|
|
7
|
+
build: {
|
|
8
|
+
outDir: "dist",
|
|
9
|
+
sourcemap: true,
|
|
10
|
+
},
|
|
11
|
+
server: {
|
|
12
|
+
port: 3000,
|
|
13
|
+
host: "0.0.0.0",
|
|
14
|
+
allowedHosts: true,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -8,10 +8,13 @@
|
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"convex:dev": "npx convex dev",
|
|
10
10
|
"convex:deploy": "npx convex deploy",
|
|
11
|
-
"dashboard": "agentforge dashboard"
|
|
11
|
+
"dashboard": "agentforge dashboard",
|
|
12
|
+
"dashboard:install": "cd dashboard && pnpm install",
|
|
13
|
+
"dashboard:dev": "cd dashboard && pnpm dev",
|
|
14
|
+
"dashboard:build": "cd dashboard && pnpm build"
|
|
12
15
|
},
|
|
13
16
|
"dependencies": {
|
|
14
|
-
"@agentforge-ai/core": "^0.
|
|
17
|
+
"@agentforge-ai/core": "^0.4.0",
|
|
15
18
|
"convex": "^1.17.0",
|
|
16
19
|
"zod": "^3.23.0"
|
|
17
20
|
},
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { Agent } from '@agentforge-ai/core';
|
|
2
|
+
import { AgentForgeWorkspace } from '@agentforge-ai/core/workspace';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* AgentForge — Your First Agent
|
|
5
6
|
*
|
|
6
7
|
* This starter agent demonstrates how to configure an AI agent with
|
|
7
|
-
* AgentForge's multi-provider support
|
|
8
|
-
*
|
|
8
|
+
* AgentForge's multi-provider support and Mastra Workspace integration.
|
|
9
|
+
*
|
|
10
|
+
* Workspace gives your agent:
|
|
11
|
+
* - Filesystem: Read, write, list, and delete files
|
|
12
|
+
* - Sandbox: Execute shell commands
|
|
13
|
+
* - Skills: Discover and activate reusable instructions
|
|
14
|
+
* - Search: BM25 keyword search over indexed content
|
|
9
15
|
*
|
|
10
16
|
* Set your provider and API key in the .env file:
|
|
11
17
|
* OPENAI_API_KEY=sk-...
|
|
@@ -13,6 +19,20 @@ import { Agent } from '@agentforge-ai/core';
|
|
|
13
19
|
* ANTHROPIC_API_KEY=sk-ant-...
|
|
14
20
|
*/
|
|
15
21
|
|
|
22
|
+
// ─── Workspace Setup ──────────────────────────────────────────────────
|
|
23
|
+
// The workspace provides persistent file storage, command execution,
|
|
24
|
+
// skill discovery, and content search for your agents.
|
|
25
|
+
const workspace = AgentForgeWorkspace.local({
|
|
26
|
+
basePath: './workspace',
|
|
27
|
+
skills: ['/skills'],
|
|
28
|
+
search: true,
|
|
29
|
+
autoIndexPaths: ['/skills'],
|
|
30
|
+
sandbox: true,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Initialize workspace (triggers auto-indexing)
|
|
34
|
+
await workspace.init();
|
|
35
|
+
|
|
16
36
|
// ─── Main Agent ────────────────────────────────────────────────────────
|
|
17
37
|
const myAgent = new Agent({
|
|
18
38
|
id: 'my-first-agent',
|
|
@@ -21,6 +41,9 @@ const myAgent = new Agent({
|
|
|
21
41
|
You can help users with a variety of tasks.
|
|
22
42
|
Be concise, accurate, and friendly.
|
|
23
43
|
|
|
44
|
+
You have access to a workspace with file management, command execution,
|
|
45
|
+
and skill discovery capabilities. Use them when appropriate.
|
|
46
|
+
|
|
24
47
|
When you don't know something, say so honestly.
|
|
25
48
|
When asked about your capabilities, mention that you're powered by AgentForge.`,
|
|
26
49
|
|
|
@@ -33,8 +56,21 @@ When asked about your capabilities, mention that you're powered by AgentForge.`,
|
|
|
33
56
|
model: 'openai:gpt-4o-mini',
|
|
34
57
|
});
|
|
35
58
|
|
|
59
|
+
export { workspace };
|
|
36
60
|
export default myAgent;
|
|
37
61
|
|
|
62
|
+
// ─── Example: Cloud Workspace (Cloudflare R2) ─────────────────────────
|
|
63
|
+
// For production deployment on Cloudflare, use a cloud workspace:
|
|
64
|
+
//
|
|
65
|
+
// const cloudWorkspace = AgentForgeWorkspace.cloud({
|
|
66
|
+
// bucket: 'my-agent-files',
|
|
67
|
+
// region: 'auto',
|
|
68
|
+
// endpoint: process.env.R2_ENDPOINT,
|
|
69
|
+
// accessKeyId: process.env.R2_ACCESS_KEY_ID,
|
|
70
|
+
// secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
|
|
71
|
+
// skills: ['/skills'],
|
|
72
|
+
// });
|
|
73
|
+
|
|
38
74
|
// ─── Example: Agent with Custom Tools ──────────────────────────────────
|
|
39
75
|
// import { z } from 'zod';
|
|
40
76
|
//
|
|
@@ -60,3 +96,7 @@ export default myAgent;
|
|
|
60
96
|
// ─── Example: Using the Agent ──────────────────────────────────────────
|
|
61
97
|
// const response = await myAgent.generate('Hello, what can you do?');
|
|
62
98
|
// console.log(response.text);
|
|
99
|
+
//
|
|
100
|
+
// ─── Example: Searching Workspace Content ──────────────────────────────
|
|
101
|
+
// const results = await workspace.search('code review');
|
|
102
|
+
// console.log(results);
|
package/dist/index.js
CHANGED
|
@@ -19,15 +19,25 @@ async function createProject(projectName, options) {
|
|
|
19
19
|
console.log(`
|
|
20
20
|
\u{1F528} Creating AgentForge project: ${projectName}
|
|
21
21
|
`);
|
|
22
|
-
const
|
|
23
|
-
__dirname,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
options.template
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
const searchDirs = [
|
|
23
|
+
path.resolve(__dirname, options.template),
|
|
24
|
+
// dist/default (built)
|
|
25
|
+
path.resolve(__dirname, "..", "templates", options.template),
|
|
26
|
+
// packages/cli/templates/default (dev)
|
|
27
|
+
path.resolve(__dirname, "..", "..", "templates", options.template)
|
|
28
|
+
// fallback
|
|
29
|
+
];
|
|
30
|
+
let templateDir = "";
|
|
31
|
+
for (const dir of searchDirs) {
|
|
32
|
+
if (await fs.pathExists(path.join(dir, "package.json"))) {
|
|
33
|
+
templateDir = dir;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (!templateDir) {
|
|
30
38
|
console.error(`Error: Template "${options.template}" not found.`);
|
|
39
|
+
console.error(`Searched in:`);
|
|
40
|
+
searchDirs.forEach((d) => console.error(` - ${d}`));
|
|
31
41
|
process.exit(1);
|
|
32
42
|
}
|
|
33
43
|
await fs.copy(templateDir, targetDir);
|
|
@@ -37,6 +47,12 @@ async function createProject(projectName, options) {
|
|
|
37
47
|
pkg2.name = projectName;
|
|
38
48
|
await fs.writeJson(pkgPath, pkg2, { spaces: 2 });
|
|
39
49
|
}
|
|
50
|
+
const dashPkgPath = path.join(targetDir, "dashboard", "package.json");
|
|
51
|
+
if (await fs.pathExists(dashPkgPath)) {
|
|
52
|
+
const dashPkg = await fs.readJson(dashPkgPath);
|
|
53
|
+
dashPkg.name = `${projectName}-dashboard`;
|
|
54
|
+
await fs.writeJson(dashPkgPath, dashPkg, { spaces: 2 });
|
|
55
|
+
}
|
|
40
56
|
console.log(` \u2705 Project scaffolded at ./${projectName}`);
|
|
41
57
|
console.log(`
|
|
42
58
|
\u{1F4E6} Installing dependencies...
|
|
@@ -54,12 +70,58 @@ async function createProject(projectName, options) {
|
|
|
54
70
|
\u26A0\uFE0F Could not install dependencies. Run "cd ${projectName} && pnpm install" manually.`
|
|
55
71
|
);
|
|
56
72
|
}
|
|
73
|
+
const dashDir = path.join(targetDir, "dashboard");
|
|
74
|
+
if (await fs.pathExists(dashDir)) {
|
|
75
|
+
console.log(`
|
|
76
|
+
\u{1F4E6} Installing dashboard dependencies...
|
|
77
|
+
`);
|
|
78
|
+
try {
|
|
79
|
+
execSync("pnpm install", {
|
|
80
|
+
cwd: dashDir,
|
|
81
|
+
stdio: "inherit"
|
|
82
|
+
});
|
|
83
|
+
console.log(`
|
|
84
|
+
\u2705 Dashboard dependencies installed`);
|
|
85
|
+
} catch {
|
|
86
|
+
console.warn(
|
|
87
|
+
`
|
|
88
|
+
\u26A0\uFE0F Could not install dashboard dependencies. Run "cd ${projectName}/dashboard && pnpm install" manually.`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
console.log(`
|
|
93
|
+
\u26A1 Initializing Convex...
|
|
94
|
+
`);
|
|
95
|
+
try {
|
|
96
|
+
execSync("npx convex dev --once", {
|
|
97
|
+
cwd: targetDir,
|
|
98
|
+
stdio: "inherit"
|
|
99
|
+
});
|
|
100
|
+
console.log(`
|
|
101
|
+
\u2705 Convex initialized`);
|
|
102
|
+
} catch {
|
|
103
|
+
console.warn(
|
|
104
|
+
`
|
|
105
|
+
\u26A0\uFE0F Convex initialization skipped. Run "npx convex dev" to set up your backend.`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
57
108
|
console.log(`
|
|
58
109
|
\u{1F389} AgentForge project "${projectName}" created successfully!
|
|
59
110
|
|
|
60
111
|
Next steps:
|
|
61
112
|
cd ${projectName}
|
|
62
|
-
|
|
113
|
+
|
|
114
|
+
# Start the Convex backend
|
|
115
|
+
npx convex dev
|
|
116
|
+
|
|
117
|
+
# In another terminal, launch the dashboard
|
|
118
|
+
agentforge dashboard
|
|
119
|
+
|
|
120
|
+
# Or chat with your agent from the CLI
|
|
121
|
+
agentforge chat
|
|
122
|
+
|
|
123
|
+
# Check system status
|
|
124
|
+
agentforge status
|
|
63
125
|
|
|
64
126
|
Documentation: https://github.com/Agentic-Engineering-Agency/agentforge
|
|
65
127
|
`);
|
|
@@ -1545,6 +1607,7 @@ function registerStatusCommand(program2) {
|
|
|
1545
1607
|
checks["Project Root"] = fs8.existsSync(path8.join(cwd, "package.json")) ? "\u2714 Found" : "\u2716 Not found";
|
|
1546
1608
|
checks["Convex Dir"] = fs8.existsSync(path8.join(cwd, "convex")) ? "\u2714 Found" : "\u2716 Not found";
|
|
1547
1609
|
checks["Skills Dir"] = fs8.existsSync(path8.join(cwd, "skills")) ? "\u2714 Found" : "\u2716 Not configured";
|
|
1610
|
+
checks["Dashboard Dir"] = fs8.existsSync(path8.join(cwd, "dashboard")) ? "\u2714 Found" : "\u2716 Not found";
|
|
1548
1611
|
checks["Env Config"] = fs8.existsSync(path8.join(cwd, ".env.local")) || fs8.existsSync(path8.join(cwd, ".env")) ? "\u2714 Found" : "\u2716 Not found";
|
|
1549
1612
|
try {
|
|
1550
1613
|
const client = createClient();
|
|
@@ -1577,24 +1640,75 @@ function registerStatusCommand(program2) {
|
|
|
1577
1640
|
checks["LLM Provider"] = provider !== "Not configured" ? `\u2714 ${provider}` : "\u2716 Not configured";
|
|
1578
1641
|
details(checks);
|
|
1579
1642
|
});
|
|
1580
|
-
program2.command("dashboard").description("Launch the web dashboard").option("-p, --port <port>", "Port for the dashboard", "3000").action(async (opts) => {
|
|
1643
|
+
program2.command("dashboard").description("Launch the web dashboard").option("-p, --port <port>", "Port for the dashboard", "3000").option("--install", "Install dashboard dependencies before starting").action(async (opts) => {
|
|
1581
1644
|
const cwd = process.cwd();
|
|
1582
|
-
const
|
|
1583
|
-
|
|
1645
|
+
const searchPaths = [
|
|
1646
|
+
path8.join(cwd, "dashboard"),
|
|
1647
|
+
// 1. Bundled in project (agentforge create)
|
|
1648
|
+
path8.join(cwd, "packages", "web"),
|
|
1649
|
+
// 2. Monorepo structure
|
|
1650
|
+
path8.join(cwd, "node_modules", "@agentforge-ai", "web")
|
|
1651
|
+
// 3. Installed as dependency
|
|
1652
|
+
];
|
|
1584
1653
|
let dashDir = "";
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1654
|
+
for (const p of searchPaths) {
|
|
1655
|
+
if (fs8.existsSync(path8.join(p, "package.json"))) {
|
|
1656
|
+
dashDir = p;
|
|
1657
|
+
break;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
if (!dashDir) {
|
|
1661
|
+
error("Dashboard not found!");
|
|
1662
|
+
console.log();
|
|
1663
|
+
info("The dashboard should be in your project's ./dashboard/ directory.");
|
|
1664
|
+
info("If you created this project with an older version of AgentForge,");
|
|
1665
|
+
info("you can add it manually:");
|
|
1666
|
+
console.log();
|
|
1667
|
+
console.log(` ${colors.cyan}# Option 1: Recreate the project${colors.reset}`);
|
|
1668
|
+
console.log(` agentforge create my-project`);
|
|
1669
|
+
console.log();
|
|
1670
|
+
console.log(` ${colors.cyan}# Option 2: Clone the dashboard from the repo${colors.reset}`);
|
|
1671
|
+
console.log(` git clone https://github.com/Agentic-Engineering-Agency/agentforge /tmp/af`);
|
|
1672
|
+
console.log(` cp -r /tmp/af/packages/web ./dashboard`);
|
|
1673
|
+
console.log(` cd dashboard && pnpm install`);
|
|
1674
|
+
console.log();
|
|
1593
1675
|
return;
|
|
1594
1676
|
}
|
|
1677
|
+
const nodeModulesExists = fs8.existsSync(path8.join(dashDir, "node_modules"));
|
|
1678
|
+
if (!nodeModulesExists || opts.install) {
|
|
1679
|
+
header("AgentForge Dashboard \u2014 Installing Dependencies");
|
|
1680
|
+
info(`Installing in ${path8.relative(cwd, dashDir) || "."}...`);
|
|
1681
|
+
console.log();
|
|
1682
|
+
const installChild = spawn2("pnpm", ["install"], {
|
|
1683
|
+
cwd: dashDir,
|
|
1684
|
+
stdio: "inherit",
|
|
1685
|
+
shell: true
|
|
1686
|
+
});
|
|
1687
|
+
await new Promise((resolve2, reject) => {
|
|
1688
|
+
installChild.on("close", (code) => {
|
|
1689
|
+
if (code === 0) resolve2();
|
|
1690
|
+
else reject(new Error(`pnpm install exited with code ${code}`));
|
|
1691
|
+
});
|
|
1692
|
+
installChild.on("error", reject);
|
|
1693
|
+
});
|
|
1694
|
+
console.log();
|
|
1695
|
+
success("Dependencies installed.");
|
|
1696
|
+
console.log();
|
|
1697
|
+
}
|
|
1698
|
+
const envPath = path8.join(cwd, ".env.local");
|
|
1699
|
+
if (fs8.existsSync(envPath)) {
|
|
1700
|
+
const envContent = fs8.readFileSync(envPath, "utf-8");
|
|
1701
|
+
const convexUrlMatch = envContent.match(/CONVEX_URL=(.+)/);
|
|
1702
|
+
if (convexUrlMatch) {
|
|
1703
|
+
const dashEnvPath = path8.join(dashDir, ".env.local");
|
|
1704
|
+
const dashEnvContent = `VITE_CONVEX_URL=${convexUrlMatch[1].trim()}
|
|
1705
|
+
`;
|
|
1706
|
+
fs8.writeFileSync(dashEnvPath, dashEnvContent);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1595
1709
|
header("AgentForge Dashboard");
|
|
1596
1710
|
info(`Starting dashboard on port ${opts.port}...`);
|
|
1597
|
-
info(`Open http://localhost:${opts.port} in your browser.`);
|
|
1711
|
+
info(`Open ${colors.cyan}http://localhost:${opts.port}${colors.reset} in your browser.`);
|
|
1598
1712
|
console.log();
|
|
1599
1713
|
const child = spawn2("pnpm", ["dev", "--port", opts.port], {
|
|
1600
1714
|
cwd: dashDir,
|
|
@@ -1653,7 +1767,6 @@ function registerStatusCommand(program2) {
|
|
|
1653
1767
|
});
|
|
1654
1768
|
console.log();
|
|
1655
1769
|
const rl = readline9.createInterface({ input: process.stdin, output: process.stdout });
|
|
1656
|
-
const { createInterface } = await import("readline");
|
|
1657
1770
|
const answer = await new Promise((r) => rl.question("Resume pending tasks? (y/N): ", (a) => {
|
|
1658
1771
|
rl.close();
|
|
1659
1772
|
r(a.trim());
|