@orka-js/cli 1.5.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/LICENSE +21 -0
- package/dist/cli.js +260 -0
- package/package.json +26 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Orka Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { intro, log, spinner, outro, text, select, confirm } from '@clack/prompts';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
|
|
6
|
+
var TEMPLATES = {
|
|
7
|
+
basic: {
|
|
8
|
+
description: "Simple agent with a goal and optional tools",
|
|
9
|
+
files: {
|
|
10
|
+
"src/agent.ts": `import { StreamingToolAgent } from '@orka-js/agent';
|
|
11
|
+
import { OpenAIAdapter } from '@orka-js/openai';
|
|
12
|
+
|
|
13
|
+
const llm = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });
|
|
14
|
+
|
|
15
|
+
export const agent = new StreamingToolAgent({
|
|
16
|
+
goal: 'You are a helpful assistant.',
|
|
17
|
+
}, llm);
|
|
18
|
+
`,
|
|
19
|
+
"src/index.ts": `import { agent } from './agent.js';
|
|
20
|
+
|
|
21
|
+
const input = process.argv[2] ?? 'Hello!';
|
|
22
|
+
|
|
23
|
+
for await (const event of agent.runStream(input)) {
|
|
24
|
+
if (event.type === 'token') process.stdout.write(event.token);
|
|
25
|
+
if (event.type === 'done') console.log('\\n\\nDone!');
|
|
26
|
+
}
|
|
27
|
+
`
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
rag: {
|
|
31
|
+
description: "RAG pipeline with vector search and document loading",
|
|
32
|
+
files: {
|
|
33
|
+
"src/agent.ts": `import { StreamingToolAgent } from '@orka-js/agent';
|
|
34
|
+
import { OpenAIAdapter } from '@orka-js/openai';
|
|
35
|
+
import { InMemoryVectorStore } from '@orka-js/memory';
|
|
36
|
+
|
|
37
|
+
const llm = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });
|
|
38
|
+
const vectorStore = new InMemoryVectorStore({ llm });
|
|
39
|
+
|
|
40
|
+
export const searchTool = {
|
|
41
|
+
name: 'search_docs',
|
|
42
|
+
description: 'Search the knowledge base for relevant documents',
|
|
43
|
+
parameters: [{ name: 'query', type: 'string', description: 'Search query', required: true }],
|
|
44
|
+
execute: async ({ query }: { query: string }) => {
|
|
45
|
+
const results = await vectorStore.similaritySearch(query, { topK: 3 });
|
|
46
|
+
return results.map(r => r.content).join('\\n---\\n');
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const agent = new StreamingToolAgent({
|
|
51
|
+
goal: 'Answer questions using the knowledge base. Always search before answering.',
|
|
52
|
+
tools: [searchTool],
|
|
53
|
+
}, llm);
|
|
54
|
+
`,
|
|
55
|
+
"src/ingest.ts": `import { InMemoryVectorStore } from '@orka-js/memory';
|
|
56
|
+
import { OpenAIAdapter } from '@orka-js/openai';
|
|
57
|
+
|
|
58
|
+
const llm = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });
|
|
59
|
+
const vectorStore = new InMemoryVectorStore({ llm });
|
|
60
|
+
|
|
61
|
+
// Add your documents here
|
|
62
|
+
await vectorStore.add([
|
|
63
|
+
{ id: '1', content: 'OrkaJS is a TypeScript AI agent framework.', metadata: {} },
|
|
64
|
+
{ id: '2', content: 'OrkaJS supports streaming, tools, memory, and graph workflows.', metadata: {} },
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
console.log('Documents ingested!');
|
|
68
|
+
`
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
sales: {
|
|
72
|
+
description: "Sales agent with tools and durable job persistence",
|
|
73
|
+
files: {
|
|
74
|
+
"src/agent.ts": `import { StreamingToolAgent } from '@orka-js/agent';
|
|
75
|
+
import { DurableAgent, MemoryDurableStore } from '@orka-js/durable';
|
|
76
|
+
import { OpenAIAdapter } from '@orka-js/openai';
|
|
77
|
+
|
|
78
|
+
const llm = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });
|
|
79
|
+
const store = new MemoryDurableStore();
|
|
80
|
+
|
|
81
|
+
const tools = [
|
|
82
|
+
{
|
|
83
|
+
name: 'search_company',
|
|
84
|
+
description: 'Look up company information',
|
|
85
|
+
parameters: [{ name: 'name', type: 'string', description: 'Company name', required: true }],
|
|
86
|
+
execute: async ({ name }: { name: string }) => \`Company: \${name} \u2014 500 employees, SaaS.\`,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'send_email',
|
|
90
|
+
description: 'Send a prospecting email',
|
|
91
|
+
parameters: [
|
|
92
|
+
{ name: 'to', type: 'string', description: 'Email address', required: true },
|
|
93
|
+
{ name: 'subject', type: 'string', description: 'Email subject', required: true },
|
|
94
|
+
{ name: 'body', type: 'string', description: 'Email body', required: true },
|
|
95
|
+
],
|
|
96
|
+
execute: async ({ to, subject }: { to: string; subject: string }) => \`Email sent to \${to}: \${subject}\`,
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
const innerAgent = new StreamingToolAgent({ goal: 'You are a B2B sales agent.', tools }, llm);
|
|
101
|
+
export const durableAgent = new DurableAgent(innerAgent, store);
|
|
102
|
+
`
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
async function runInit(targetDir) {
|
|
107
|
+
intro("Orka Init \u2014 Create a new OrkaJS project");
|
|
108
|
+
const dir = targetDir ?? await text({
|
|
109
|
+
message: "Project directory:",
|
|
110
|
+
placeholder: "./my-orka-agent",
|
|
111
|
+
defaultValue: "./my-orka-agent"
|
|
112
|
+
});
|
|
113
|
+
if (!dir) {
|
|
114
|
+
log.error("No directory specified.");
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
const template = await select({
|
|
118
|
+
message: "Choose a template:",
|
|
119
|
+
options: Object.entries(TEMPLATES).map(([value, t]) => ({
|
|
120
|
+
value,
|
|
121
|
+
label: value,
|
|
122
|
+
hint: t.description
|
|
123
|
+
}))
|
|
124
|
+
});
|
|
125
|
+
const provider = await select({
|
|
126
|
+
message: "LLM provider:",
|
|
127
|
+
options: [
|
|
128
|
+
{ value: "openai", label: "OpenAI", hint: "GPT-4o, GPT-4-turbo" },
|
|
129
|
+
{ value: "anthropic", label: "Anthropic", hint: "Claude 3.5, Claude 4" },
|
|
130
|
+
{ value: "google", label: "Google", hint: "Gemini 2.0 Flash" },
|
|
131
|
+
{ value: "ollama", label: "Ollama", hint: "Local models" }
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
const install = await confirm({ message: "Install dependencies?" });
|
|
135
|
+
const s = spinner();
|
|
136
|
+
s.start("Creating project files\u2026");
|
|
137
|
+
const fullDir = join(process.cwd(), dir);
|
|
138
|
+
await fs.ensureDir(fullDir);
|
|
139
|
+
await fs.ensureDir(join(fullDir, "src"));
|
|
140
|
+
const tpl = TEMPLATES[template];
|
|
141
|
+
for (const [file, content] of Object.entries(tpl.files)) {
|
|
142
|
+
await fs.outputFile(join(fullDir, file), content);
|
|
143
|
+
}
|
|
144
|
+
const pkgDeps = {
|
|
145
|
+
"@orka-js/agent": "^1.5.0",
|
|
146
|
+
"@orka-js/core": "^1.5.0"
|
|
147
|
+
};
|
|
148
|
+
if (provider !== "ollama") pkgDeps[`@orka-js/${provider}`] = "^1.5.0";
|
|
149
|
+
if (provider === "ollama") pkgDeps["@orka-js/ollama"] = "^1.5.0";
|
|
150
|
+
if (template === "rag") pkgDeps["@orka-js/memory"] = "^1.5.0";
|
|
151
|
+
if (template === "sales") pkgDeps["@orka-js/durable"] = "^1.5.0";
|
|
152
|
+
await fs.outputJSON(join(fullDir, "package.json"), {
|
|
153
|
+
name: dir.replace("./", "").replace(/\//g, "-"),
|
|
154
|
+
version: "0.1.0",
|
|
155
|
+
type: "module",
|
|
156
|
+
scripts: { dev: "node --loader ts-node/esm src/index.ts", build: "tsc" },
|
|
157
|
+
dependencies: pkgDeps,
|
|
158
|
+
devDependencies: { typescript: "^5.4.0", "ts-node": "^10.9.2" }
|
|
159
|
+
}, { spaces: 2 });
|
|
160
|
+
const envVars = provider !== "ollama" ? `${provider.toUpperCase()}_API_KEY=your-api-key-here
|
|
161
|
+
` : "";
|
|
162
|
+
await fs.outputFile(join(fullDir, ".env.example"), envVars);
|
|
163
|
+
await fs.outputFile(join(fullDir, ".gitignore"), "node_modules\ndist\n.env\n");
|
|
164
|
+
s.stop("Project files created!");
|
|
165
|
+
if (install) {
|
|
166
|
+
const s2 = spinner();
|
|
167
|
+
s2.start("Installing dependencies\u2026");
|
|
168
|
+
const { execSync } = await import('child_process');
|
|
169
|
+
try {
|
|
170
|
+
execSync("npm install", { cwd: fullDir, stdio: "pipe" });
|
|
171
|
+
s2.stop("Dependencies installed!");
|
|
172
|
+
} catch {
|
|
173
|
+
s2.stop("Install failed \u2014 run npm install manually.");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
outro(`Done! \`cd ${dir}\` and add your API key to .env`);
|
|
177
|
+
}
|
|
178
|
+
async function runDev(options = {}) {
|
|
179
|
+
intro("Orka Dev Server");
|
|
180
|
+
const port = options.port ?? 4200;
|
|
181
|
+
const cwd = process.cwd();
|
|
182
|
+
const configPaths = [
|
|
183
|
+
join(cwd, "orka.config.ts"),
|
|
184
|
+
join(cwd, "orka.config.js"),
|
|
185
|
+
join(cwd, "src", "agent.ts"),
|
|
186
|
+
join(cwd, "src", "agents.ts")
|
|
187
|
+
];
|
|
188
|
+
let configFile = null;
|
|
189
|
+
for (const p of configPaths) {
|
|
190
|
+
if (await fs.pathExists(p)) {
|
|
191
|
+
configFile = p;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (!configFile) {
|
|
196
|
+
log.error("No agent config found. Create orka.config.ts or src/agent.ts");
|
|
197
|
+
log.info("Expected export: export default { agents: { assistant: myAgent } }");
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
const s = spinner();
|
|
201
|
+
s.start(`Loading agents from ${configFile}\u2026`);
|
|
202
|
+
try {
|
|
203
|
+
const mod = await import(configFile);
|
|
204
|
+
const agentConfig = mod.default ?? mod;
|
|
205
|
+
const agents = agentConfig.agents ?? {};
|
|
206
|
+
s.stop(`Loaded ${Object.keys(agents).length} agent(s)`);
|
|
207
|
+
const { createOrkaServer } = await import('@orka-js/server');
|
|
208
|
+
const server = await createOrkaServer({
|
|
209
|
+
agents,
|
|
210
|
+
port,
|
|
211
|
+
open: options.open ?? true
|
|
212
|
+
});
|
|
213
|
+
outro(`Orka Dev Server running at ${server.url}`);
|
|
214
|
+
log.info("Press Ctrl+C to stop.");
|
|
215
|
+
process.on("SIGINT", async () => {
|
|
216
|
+
await server.close();
|
|
217
|
+
process.exit(0);
|
|
218
|
+
});
|
|
219
|
+
} catch (error) {
|
|
220
|
+
s.stop("Failed to start server");
|
|
221
|
+
log.error(error.message);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/cli.ts
|
|
227
|
+
var [, , command, ...args] = process.argv;
|
|
228
|
+
async function main() {
|
|
229
|
+
switch (command) {
|
|
230
|
+
case "init": {
|
|
231
|
+
await runInit(args[0]);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
case "dev": {
|
|
235
|
+
const portFlag = args.findIndex((a) => a === "--port" || a === "-p");
|
|
236
|
+
const port = portFlag !== -1 ? parseInt(args[portFlag + 1]) : void 0;
|
|
237
|
+
const open = !args.includes("--no-open");
|
|
238
|
+
await runDev({ port, open });
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
default: {
|
|
242
|
+
console.log(`
|
|
243
|
+
orka \u2014 OrkaJS CLI
|
|
244
|
+
|
|
245
|
+
Commands:
|
|
246
|
+
orka init [dir] Create a new OrkaJS project
|
|
247
|
+
orka dev [--port 4200] Start the dev server
|
|
248
|
+
|
|
249
|
+
Examples:
|
|
250
|
+
npx @orka-js/cli init ./my-agent
|
|
251
|
+
npx @orka-js/cli dev --port 3000
|
|
252
|
+
`);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
main().catch((err) => {
|
|
258
|
+
console.error(err.message);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orka-js/cli",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "CLI for OrkaJS — npx orka init, orka dev",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"orka": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@clack/prompts": "^0.7.0",
|
|
14
|
+
"fs-extra": "^11.2.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/fs-extra": "^11.0.4",
|
|
18
|
+
"vitest": "^1.6.0"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"dev": "tsup --watch",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "vitest run"
|
|
25
|
+
}
|
|
26
|
+
}
|