create-operor 0.1.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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { execSync } from "node:child_process";
6
+ import * as p from "@clack/prompts";
7
+
8
+ //#region src/index.ts
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const TEMPLATES_DIR = path.join(__dirname, "..", "templates", "default");
11
+ function parseArgs(args) {
12
+ const rest = args.slice(2);
13
+ const demo = rest.includes("--demo");
14
+ return {
15
+ projectName: rest.filter((a) => !a.startsWith("--"))[0] ?? "",
16
+ demo
17
+ };
18
+ }
19
+ function detectPackageManager() {
20
+ const ua = process.env.npm_config_user_agent ?? "";
21
+ if (ua.startsWith("pnpm")) return "pnpm";
22
+ if (ua.startsWith("yarn")) return "yarn";
23
+ if (ua.startsWith("bun")) return "bun";
24
+ return "npm";
25
+ }
26
+ function copyDir(src, dest) {
27
+ fs.mkdirSync(dest, { recursive: true });
28
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
29
+ const srcPath = path.join(src, entry.name);
30
+ const destPath = path.join(dest, entry.name);
31
+ if (entry.isDirectory()) copyDir(srcPath, destPath);
32
+ else fs.copyFileSync(srcPath, destPath);
33
+ }
34
+ }
35
+ async function main() {
36
+ const opts = parseArgs(process.argv);
37
+ p.intro("create-operor");
38
+ let projectName = opts.projectName;
39
+ if (!projectName) {
40
+ const result = await p.text({
41
+ message: "Project name:",
42
+ placeholder: "my-bot",
43
+ validate: (v) => !v.trim() ? "Project name is required" : void 0
44
+ });
45
+ if (p.isCancel(result)) {
46
+ p.cancel("Cancelled.");
47
+ process.exit(0);
48
+ }
49
+ projectName = result;
50
+ }
51
+ const projectDir = path.resolve(process.cwd(), projectName);
52
+ if (fs.existsSync(projectDir)) {
53
+ p.cancel(`Directory "${projectName}" already exists.`);
54
+ process.exit(1);
55
+ }
56
+ let provider = "mock";
57
+ let apiKey = "";
58
+ let description = "My Operor project";
59
+ if (opts.demo) p.log.info("Demo mode — using MockProvider defaults");
60
+ else {
61
+ const providerResult = await p.select({
62
+ message: "LLM provider:",
63
+ options: [
64
+ {
65
+ value: "openai",
66
+ label: "OpenAI"
67
+ },
68
+ {
69
+ value: "anthropic",
70
+ label: "Anthropic"
71
+ },
72
+ {
73
+ value: "google",
74
+ label: "Google"
75
+ },
76
+ {
77
+ value: "groq",
78
+ label: "Groq"
79
+ },
80
+ {
81
+ value: "ollama",
82
+ label: "Ollama (local)"
83
+ }
84
+ ]
85
+ });
86
+ if (p.isCancel(providerResult)) {
87
+ p.cancel("Cancelled.");
88
+ process.exit(0);
89
+ }
90
+ provider = providerResult;
91
+ if (provider !== "ollama") {
92
+ const keyResult = await p.password({ message: "API key:" });
93
+ if (p.isCancel(keyResult)) {
94
+ p.cancel("Cancelled.");
95
+ process.exit(0);
96
+ }
97
+ apiKey = keyResult ?? "";
98
+ }
99
+ const descResult = await p.text({
100
+ message: "Describe your business in one sentence:",
101
+ placeholder: "We sell handmade candles"
102
+ });
103
+ if (p.isCancel(descResult)) {
104
+ p.cancel("Cancelled.");
105
+ process.exit(0);
106
+ }
107
+ description = descResult || description;
108
+ }
109
+ const s = p.spinner();
110
+ s.start("Creating project");
111
+ copyDir(TEMPLATES_DIR, projectDir);
112
+ const tmplPath = path.join(projectDir, "package.json.tmpl");
113
+ const pkgContent = fs.readFileSync(tmplPath, "utf-8").replace(/\{\{name\}\}/g, projectName);
114
+ fs.writeFileSync(path.join(projectDir, "package.json"), pkgContent);
115
+ fs.unlinkSync(tmplPath);
116
+ const envLines = [`# LLM Configuration`, `LLM_PROVIDER=${provider}`];
117
+ if (apiKey) envLines.push(`LLM_API_KEY=${apiKey}`);
118
+ if (provider === "mock") envLines.push(`CHANNEL=mock`);
119
+ envLines.push("", "# Knowledge Base", "KB_ENABLED=true", "", "# Analytics", "ANALYTICS_ENABLED=true");
120
+ fs.writeFileSync(path.join(projectDir, ".env"), envLines.join("\n") + "\n");
121
+ const userMdPath = path.join(projectDir, "USER.md");
122
+ const userMd = fs.readFileSync(userMdPath, "utf-8").replace(/\{\{description\}\}/g, description);
123
+ fs.writeFileSync(userMdPath, userMd);
124
+ s.stop("Project created");
125
+ const pm = detectPackageManager();
126
+ const installCmd = pm === "yarn" ? "yarn" : `${pm} install`;
127
+ s.start(`Installing dependencies (${pm})`);
128
+ try {
129
+ execSync(installCmd, {
130
+ cwd: projectDir,
131
+ stdio: "pipe"
132
+ });
133
+ s.stop("Dependencies installed");
134
+ } catch {
135
+ s.stop("Could not install dependencies");
136
+ p.log.warn(`Run \`cd ${projectName} && ${installCmd}\` to install manually.`);
137
+ }
138
+ p.note([
139
+ `cd ${projectName}`,
140
+ "",
141
+ provider === "mock" ? `${pm === "npm" ? "npm run" : pm} chat # try it out` : `${pm === "npm" ? "npm run" : pm} setup # configure your agent`,
142
+ `${pm === "npm" ? "npm run" : pm} start # launch the agent`
143
+ ].join("\n"), "Next steps");
144
+ p.outro("Happy building!");
145
+ }
146
+ main().catch((err) => {
147
+ p.log.error(err instanceof Error ? err.message : String(err));
148
+ process.exit(1);
149
+ });
150
+
151
+ //#endregion
152
+ export { };
153
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { execSync } from 'node:child_process';\nimport * as p from '@clack/prompts';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.join(__dirname, '..', 'templates', 'default');\n\ninterface Options {\n projectName: string;\n demo: boolean;\n provider?: string;\n apiKey?: string;\n description?: string;\n}\n\nfunction parseArgs(args: string[]): Options {\n const rest = args.slice(2);\n const demo = rest.includes('--demo');\n const positional = rest.filter((a) => !a.startsWith('--'));\n const projectName = positional[0] ?? '';\n return { projectName, demo };\n}\n\nfunction detectPackageManager(): string {\n const ua = process.env.npm_config_user_agent ?? '';\n if (ua.startsWith('pnpm')) return 'pnpm';\n if (ua.startsWith('yarn')) return 'yarn';\n if (ua.startsWith('bun')) return 'bun';\n return 'npm';\n}\n\nfunction copyDir(src: string, dest: string) {\n fs.mkdirSync(dest, { recursive: true });\n for (const entry of fs.readdirSync(src, { withFileTypes: true })) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n if (entry.isDirectory()) {\n copyDir(srcPath, destPath);\n } else {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n}\n\nasync function main() {\n const opts = parseArgs(process.argv);\n\n p.intro('create-operor');\n\n // Get project name\n let projectName = opts.projectName;\n if (!projectName) {\n const result = await p.text({\n message: 'Project name:',\n placeholder: 'my-bot',\n validate: (v) => (!v.trim() ? 'Project name is required' : undefined),\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n projectName = result;\n }\n\n const projectDir = path.resolve(process.cwd(), projectName);\n\n if (fs.existsSync(projectDir)) {\n p.cancel(`Directory \"${projectName}\" already exists.`);\n process.exit(1);\n }\n\n let provider = 'mock';\n let apiKey = '';\n let description = 'My Operor project';\n\n if (opts.demo) {\n p.log.info('Demo mode — using MockProvider defaults');\n } else {\n const providerResult = await p.select({\n message: 'LLM provider:',\n options: [\n { value: 'openai', label: 'OpenAI' },\n { value: 'anthropic', label: 'Anthropic' },\n { value: 'google', label: 'Google' },\n { value: 'groq', label: 'Groq' },\n { value: 'ollama', label: 'Ollama (local)' },\n ],\n });\n if (p.isCancel(providerResult)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n provider = providerResult as string;\n\n if (provider !== 'ollama') {\n const keyResult = await p.password({\n message: 'API key:',\n });\n if (p.isCancel(keyResult)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n apiKey = keyResult ?? '';\n }\n\n const descResult = await p.text({\n message: 'Describe your business in one sentence:',\n placeholder: 'We sell handmade candles',\n });\n if (p.isCancel(descResult)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n description = descResult || description;\n }\n\n // Scaffold project\n const s = p.spinner();\n s.start('Creating project');\n\n // Copy template files\n copyDir(TEMPLATES_DIR, projectDir);\n\n // Process package.json.tmpl → package.json\n const tmplPath = path.join(projectDir, 'package.json.tmpl');\n const pkgContent = fs.readFileSync(tmplPath, 'utf-8').replace(/\\{\\{name\\}\\}/g, projectName);\n fs.writeFileSync(path.join(projectDir, 'package.json'), pkgContent);\n fs.unlinkSync(tmplPath);\n\n // Write .env\n const envLines = [`# LLM Configuration`, `LLM_PROVIDER=${provider}`];\n if (apiKey) {\n envLines.push(`LLM_API_KEY=${apiKey}`);\n }\n if (provider === 'mock') {\n envLines.push(`CHANNEL=mock`);\n }\n envLines.push('', '# Knowledge Base', 'KB_ENABLED=true', '', '# Analytics', 'ANALYTICS_ENABLED=true');\n fs.writeFileSync(path.join(projectDir, '.env'), envLines.join('\\n') + '\\n');\n\n // Write USER.md with business description\n const userMdPath = path.join(projectDir, 'USER.md');\n const userMd = fs.readFileSync(userMdPath, 'utf-8').replace(/\\{\\{description\\}\\}/g, description);\n fs.writeFileSync(userMdPath, userMd);\n\n s.stop('Project created');\n\n // Install dependencies\n const pm = detectPackageManager();\n const installCmd = pm === 'yarn' ? 'yarn' : `${pm} install`;\n\n s.start(`Installing dependencies (${pm})`);\n try {\n execSync(installCmd, { cwd: projectDir, stdio: 'pipe' });\n s.stop('Dependencies installed');\n } catch {\n s.stop('Could not install dependencies');\n p.log.warn(`Run \\`cd ${projectName} && ${installCmd}\\` to install manually.`);\n }\n\n // Success\n p.note(\n [\n `cd ${projectName}`,\n '',\n provider === 'mock'\n ? `${pm === 'npm' ? 'npm run' : pm} chat # try it out`\n : `${pm === 'npm' ? 'npm run' : pm} setup # configure your agent`,\n `${pm === 'npm' ? 'npm run' : pm} start # launch the agent`,\n ].join('\\n'),\n 'Next steps',\n );\n\n p.outro('Happy building!');\n}\n\nmain().catch((err) => {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "create-operor",
3
+ "version": "0.1.0",
4
+ "description": "Create a new Agent OS project",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-operor": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "templates"
12
+ ],
13
+ "dependencies": {
14
+ "@clack/prompts": "^1.0.0"
15
+ },
16
+ "devDependencies": {
17
+ "tsdown": "^0.12.0",
18
+ "typescript": "^5.7.0"
19
+ },
20
+ "scripts": {
21
+ "build": "tsdown",
22
+ "test": "echo 'no tests yet'"
23
+ }
24
+ }
@@ -0,0 +1,9 @@
1
+ # LLM Configuration
2
+ LLM_PROVIDER=openai
3
+ LLM_API_KEY=your-api-key-here
4
+
5
+ # Knowledge Base
6
+ KB_ENABLED=true
7
+
8
+ # Analytics
9
+ ANALYTICS_ENABLED=true
@@ -0,0 +1,3 @@
1
+ # About Us
2
+
3
+ {{description}}
@@ -0,0 +1,25 @@
1
+ # Agent Soul
2
+
3
+ ## Core Principles
4
+
5
+ - The customer's time is valuable — resolve issues in as few messages as possible
6
+ - Empathy first, solutions second — acknowledge feelings before jumping to fixes
7
+ - Honesty builds trust — if you don't know, say so and find out
8
+
9
+ ## Boundaries
10
+
11
+ - Stay within your scope; escalate gracefully when you can't help
12
+ - Don't overpromise — set realistic expectations about timelines and outcomes
13
+
14
+ ## Tone
15
+
16
+ - Conversational but professional
17
+ - Positive without being dismissive of problems
18
+ - Direct — avoid filler phrases
19
+ - Match the customer's energy — if they're brief, be brief; if they need reassurance, provide it
20
+
21
+ ## When Things Go Wrong
22
+
23
+ - Lead with accountability: "I see the issue and I'm sorry about that"
24
+ - Offer a concrete next step, not just an apology
25
+ - Follow through — if you say you'll check on something, do it
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: support
3
+ purpose: Handle customer support inquiries
4
+ triggers:
5
+ - "*"
6
+ knowledgeBase: true
7
+ guardrails:
8
+ maxResponseLength: 500
9
+ blockedTopics:
10
+ - competitor pricing
11
+ - internal company policies
12
+ - employee information
13
+ escalationTriggers:
14
+ - speak to a human
15
+ - talk to a manager
16
+ - escalate
17
+ systemRules:
18
+ - Never share customer data with other customers
19
+ - Always verify order ownership before sharing details
20
+ ---
21
+
22
+ ## Role
23
+
24
+ You are a helpful customer support agent. Your job is to answer questions, resolve issues, and provide a great experience.
25
+
26
+ ## Scope
27
+
28
+ - Answer questions about products, services, and policies
29
+ - Help with order tracking and status updates
30
+ - Assist with returns and exchanges
31
+ - Provide shipping and delivery information
32
+
33
+ ## Out of Scope
34
+
35
+ - Cannot process refunds directly (escalate to a team member)
36
+ - Cannot access or discuss other customers' information
37
+ - Do not provide legal, medical, or financial advice
38
+
39
+ ## Style
40
+
41
+ - Warm, professional, and concise
42
+ - Use short paragraphs and bullet points for clarity
43
+ - Acknowledge the customer's concern before problem-solving
44
+ - End each interaction with a clear next step
45
+
46
+ ## Escalation
47
+
48
+ - If the customer asks for a human agent, acknowledge their request and provide handoff instructions
49
+ - Use the phrase: "Let me connect you with a team member who can help with this."
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "agent-os start",
8
+ "setup": "agent-os setup",
9
+ "chat": "agent-os chat",
10
+ "test": "agent-os test"
11
+ },
12
+ "dependencies": {
13
+ "@agent-os/cli": "^0.1.0",
14
+ "@agent-os/core": "^0.1.0",
15
+ "@agent-os/llm": "^0.1.0",
16
+ "@agent-os/memory": "^0.1.0",
17
+ "@agent-os/knowledge": "^0.1.0",
18
+ "@agent-os/provider-mock": "^0.1.0"
19
+ }
20
+ }