@operor/cli 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.
- package/README.md +76 -0
- package/dist/config-Bn2pbORi.js +34 -0
- package/dist/config-Bn2pbORi.js.map +1 -0
- package/dist/converse-C_PB7-JH.js +142 -0
- package/dist/converse-C_PB7-JH.js.map +1 -0
- package/dist/doctor-98gPl743.js +122 -0
- package/dist/doctor-98gPl743.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2268 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-override-BIQl0V6H.js +445 -0
- package/dist/llm-override-BIQl0V6H.js.map +1 -0
- package/dist/reset-DT8SBgFS.js +87 -0
- package/dist/reset-DT8SBgFS.js.map +1 -0
- package/dist/simulate-BKv62GJc.js +144 -0
- package/dist/simulate-BKv62GJc.js.map +1 -0
- package/dist/status-D6LIZvQa.js +82 -0
- package/dist/status-D6LIZvQa.js.map +1 -0
- package/dist/test-DYjkxbtK.js +177 -0
- package/dist/test-DYjkxbtK.js.map +1 -0
- package/dist/test-suite-D8H_5uKs.js +209 -0
- package/dist/test-suite-D8H_5uKs.js.map +1 -0
- package/dist/utils-BuV4q7f6.js +11 -0
- package/dist/utils-BuV4q7f6.js.map +1 -0
- package/dist/vibe-Bl_js3Jo.js +395 -0
- package/dist/vibe-Bl_js3Jo.js.map +1 -0
- package/package.json +43 -0
- package/src/commands/analytics.ts +408 -0
- package/src/commands/chat.ts +310 -0
- package/src/commands/config.ts +34 -0
- package/src/commands/converse.ts +182 -0
- package/src/commands/doctor.ts +154 -0
- package/src/commands/history.ts +60 -0
- package/src/commands/init.ts +163 -0
- package/src/commands/kb.ts +429 -0
- package/src/commands/llm-override.ts +480 -0
- package/src/commands/reset.ts +72 -0
- package/src/commands/simulate.ts +187 -0
- package/src/commands/status.ts +112 -0
- package/src/commands/test-suite.ts +247 -0
- package/src/commands/test.ts +177 -0
- package/src/commands/vibe.ts +478 -0
- package/src/config.ts +127 -0
- package/src/index.ts +190 -0
- package/src/log-timestamps.ts +26 -0
- package/src/setup.ts +712 -0
- package/src/start.ts +573 -0
- package/src/utils.ts +6 -0
- package/templates/agents/_defaults/SOUL.md +20 -0
- package/templates/agents/_defaults/USER.md +16 -0
- package/templates/agents/customer-support/IDENTITY.md +6 -0
- package/templates/agents/customer-support/INSTRUCTIONS.md +79 -0
- package/templates/agents/customer-support/SOUL.md +26 -0
- package/templates/agents/faq-bot/IDENTITY.md +6 -0
- package/templates/agents/faq-bot/INSTRUCTIONS.md +53 -0
- package/templates/agents/faq-bot/SOUL.md +19 -0
- package/templates/agents/sales/IDENTITY.md +6 -0
- package/templates/agents/sales/INSTRUCTIONS.md +67 -0
- package/templates/agents/sales/SOUL.md +20 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.ts +13 -0
- package/vitest.config.ts +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @operor/cli
|
|
2
|
+
|
|
3
|
+
CLI tool for Operor — setup wizard, diagnostics, testing, and knowledge base management.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -g @operor/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
### Setup & Runtime
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
operor setup # Interactive setup wizard
|
|
17
|
+
operor start # Start with existing .env config
|
|
18
|
+
operor status # Show configuration status
|
|
19
|
+
operor doctor # Validate config and test connections
|
|
20
|
+
operor test # Run demo test scenarios
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Configuration
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
operor config show # Show current config
|
|
27
|
+
operor config set KEY VALUE # Set a config value
|
|
28
|
+
operor config unset KEY # Remove a config value
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Knowledge Base
|
|
32
|
+
|
|
33
|
+
Requires `KB_ENABLED=true` in `.env` (set via `operor setup` or `operor config set`).
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Ingest content
|
|
37
|
+
operor kb add-url <url> # Ingest a web page
|
|
38
|
+
operor kb add-file <path> # Ingest a document (PDF, TXT, MD, etc.)
|
|
39
|
+
operor kb add-faq <question> <answer> # Add a manual FAQ entry
|
|
40
|
+
|
|
41
|
+
# Browse & search
|
|
42
|
+
operor kb list # List all documents
|
|
43
|
+
operor kb search <query> # Search with relevance scores
|
|
44
|
+
operor kb search <query> -n 10 # Search with custom result limit
|
|
45
|
+
|
|
46
|
+
# Manage
|
|
47
|
+
operor kb delete <id> # Delete a document by ID
|
|
48
|
+
operor kb stats # Show KB statistics (docs, chunks, DB size)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Examples
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Add your docs
|
|
55
|
+
operor kb add-url https://docs.example.com/faq
|
|
56
|
+
operor kb add-file ./product-manual.pdf
|
|
57
|
+
operor kb add-faq "What are your hours?" "We're open Mon-Fri 9am-5pm EST."
|
|
58
|
+
|
|
59
|
+
# Test retrieval
|
|
60
|
+
operor kb search "return policy"
|
|
61
|
+
|
|
62
|
+
# Check stats
|
|
63
|
+
operor kb stats
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### KB Configuration
|
|
67
|
+
|
|
68
|
+
Set during `operor setup` or manually via `operor config set`:
|
|
69
|
+
|
|
70
|
+
| Variable | Description | Default |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `KB_ENABLED` | Enable knowledge base | `false` |
|
|
73
|
+
| `KB_DB_PATH` | SQLite database path | `./knowledge.db` |
|
|
74
|
+
| `KB_EMBEDDING_PROVIDER` | `openai`, `google`, `mistral`, `cohere`, or `ollama` | `openai` |
|
|
75
|
+
| `KB_EMBEDDING_MODEL` | Embedding model name | Provider default |
|
|
76
|
+
| `KB_EMBEDDING_API_KEY` | API key for embeddings | — |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { n as readConfig, r as writeConfig, t as configExists } from "./index.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/config.ts
|
|
4
|
+
function showConfig() {
|
|
5
|
+
if (!configExists()) {
|
|
6
|
+
console.error("No configuration found. Run \"operor setup\" first.");
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const config = readConfig();
|
|
10
|
+
for (const [key, value] of Object.entries(config)) {
|
|
11
|
+
const display = key.includes("KEY") || key.includes("TOKEN") || key.includes("SECRET") ? maskValue(value || "") : value;
|
|
12
|
+
console.log(` ${key}=${display}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function setConfigValue(key, value) {
|
|
16
|
+
const config = readConfig();
|
|
17
|
+
config[key] = value;
|
|
18
|
+
writeConfig(config);
|
|
19
|
+
console.log(` Set ${key}=${key.includes("KEY") ? maskValue(value) : value}`);
|
|
20
|
+
}
|
|
21
|
+
function unsetConfigValue(key) {
|
|
22
|
+
const config = readConfig();
|
|
23
|
+
delete config[key];
|
|
24
|
+
writeConfig(config);
|
|
25
|
+
console.log(` Removed ${key}`);
|
|
26
|
+
}
|
|
27
|
+
function maskValue(val) {
|
|
28
|
+
if (val.length <= 8) return "••••••••";
|
|
29
|
+
return val.slice(0, 4) + "••••" + val.slice(-4);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { setConfigValue, showConfig, unsetConfigValue };
|
|
34
|
+
//# sourceMappingURL=config-Bn2pbORi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-Bn2pbORi.js","names":[],"sources":["../src/commands/config.ts"],"sourcesContent":["import { readConfig, writeConfig, configExists } from '../config.js';\n\nexport function showConfig(): void {\n if (!configExists()) {\n console.error('No configuration found. Run \"operor setup\" first.');\n process.exit(1);\n }\n const config = readConfig();\n for (const [key, value] of Object.entries(config)) {\n const display = key.includes('KEY') || key.includes('TOKEN') || key.includes('SECRET')\n ? maskValue(value || '')\n : value;\n console.log(` ${key}=${display}`);\n }\n}\n\nexport function setConfigValue(key: string, value: string): void {\n const config = readConfig();\n config[key] = value;\n writeConfig(config);\n console.log(` Set ${key}=${key.includes('KEY') ? maskValue(value) : value}`);\n}\n\nexport function unsetConfigValue(key: string): void {\n const config = readConfig();\n delete config[key];\n writeConfig(config);\n console.log(` Removed ${key}`);\n}\n\nfunction maskValue(val: string): string {\n if (val.length <= 8) return '••••••••';\n return val.slice(0, 4) + '••••' + val.slice(-4);\n}\n"],"mappings":";;;AAEA,SAAgB,aAAmB;AACjC,KAAI,CAAC,cAAc,EAAE;AACnB,UAAQ,MAAM,sDAAoD;AAClE,UAAQ,KAAK,EAAE;;CAEjB,MAAM,SAAS,YAAY;AAC3B,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;EACjD,MAAM,UAAU,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,QAAQ,IAAI,IAAI,SAAS,SAAS,GAClF,UAAU,SAAS,GAAG,GACtB;AACJ,UAAQ,IAAI,KAAK,IAAI,GAAG,UAAU;;;AAItC,SAAgB,eAAe,KAAa,OAAqB;CAC/D,MAAM,SAAS,YAAY;AAC3B,QAAO,OAAO;AACd,aAAY,OAAO;AACnB,SAAQ,IAAI,SAAS,IAAI,GAAG,IAAI,SAAS,MAAM,GAAG,UAAU,MAAM,GAAG,QAAQ;;AAG/E,SAAgB,iBAAiB,KAAmB;CAClD,MAAM,SAAS,YAAY;AAC3B,QAAO,OAAO;AACd,aAAY,OAAO;AACnB,SAAQ,IAAI,aAAa,MAAM;;AAGjC,SAAS,UAAU,KAAqB;AACtC,KAAI,IAAI,UAAU,EAAG,QAAO;AAC5B,QAAO,IAAI,MAAM,GAAG,EAAE,GAAG,SAAS,IAAI,MAAM,GAAG"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { n as readConfig } from "./index.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/converse.ts
|
|
4
|
+
async function runConverse(options) {
|
|
5
|
+
const config = readConfig();
|
|
6
|
+
const { Operor } = await import("@operor/core");
|
|
7
|
+
const { MockProvider } = await import("@operor/provider-mock");
|
|
8
|
+
const { MockShopifySkill, CustomerSimulator, ConversationEvaluator, ConversationRunner, ECOMMERCE_SCENARIOS, SkillTestHarness } = await import("@operor/testing");
|
|
9
|
+
let llm;
|
|
10
|
+
if (config.LLM_PROVIDER && config.LLM_API_KEY) {
|
|
11
|
+
const { AIProvider } = await import("@operor/llm");
|
|
12
|
+
llm = new AIProvider({
|
|
13
|
+
provider: config.LLM_PROVIDER,
|
|
14
|
+
apiKey: config.LLM_API_KEY,
|
|
15
|
+
model: config.LLM_MODEL
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
let scenarios = [...ECOMMERCE_SCENARIOS];
|
|
19
|
+
if (options.file) {
|
|
20
|
+
const fs = await import("fs");
|
|
21
|
+
try {
|
|
22
|
+
const raw = fs.readFileSync(options.file, "utf-8");
|
|
23
|
+
scenarios = JSON.parse(raw);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(`Failed to load scenarios from ${options.file}:`, err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (options.scenario) {
|
|
30
|
+
const match = scenarios.filter((s) => s.name.toLowerCase().includes(options.scenario.toLowerCase()) || s.id.toLowerCase().includes(options.scenario.toLowerCase()));
|
|
31
|
+
if (match.length === 0) {
|
|
32
|
+
console.error(`No scenario matching "${options.scenario}". Available:`);
|
|
33
|
+
scenarios.forEach((s) => console.error(` - ${s.id}: ${s.name}`));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
scenarios = match;
|
|
37
|
+
}
|
|
38
|
+
if (options.turns) scenarios = scenarios.map((s) => ({
|
|
39
|
+
...s,
|
|
40
|
+
maxTurns: options.turns
|
|
41
|
+
}));
|
|
42
|
+
if (options.persona) scenarios = scenarios.map((s) => ({
|
|
43
|
+
...s,
|
|
44
|
+
persona: options.persona
|
|
45
|
+
}));
|
|
46
|
+
const os = new Operor({
|
|
47
|
+
debug: false,
|
|
48
|
+
batchWindowMs: 0
|
|
49
|
+
});
|
|
50
|
+
const provider = new MockProvider();
|
|
51
|
+
const shopify = new MockShopifySkill();
|
|
52
|
+
let skill = shopify;
|
|
53
|
+
if (options.real || options.dryRun) {
|
|
54
|
+
skill = new SkillTestHarness(shopify, {
|
|
55
|
+
allowWrites: options.allowWrites ?? false,
|
|
56
|
+
dryRun: options.dryRun ?? false
|
|
57
|
+
});
|
|
58
|
+
await skill.authenticate();
|
|
59
|
+
}
|
|
60
|
+
await os.addProvider(provider);
|
|
61
|
+
await os.addSkill(skill);
|
|
62
|
+
const allTools = [
|
|
63
|
+
shopify.tools.get_order,
|
|
64
|
+
shopify.tools.create_discount,
|
|
65
|
+
shopify.tools.search_products
|
|
66
|
+
];
|
|
67
|
+
const agent = os.createAgent({
|
|
68
|
+
name: "Test Agent",
|
|
69
|
+
purpose: "Handle customer support conversations",
|
|
70
|
+
personality: "empathetic and solution-focused",
|
|
71
|
+
triggers: ["order_tracking", "general"],
|
|
72
|
+
tools: allTools,
|
|
73
|
+
rules: [{
|
|
74
|
+
name: "Auto-compensation",
|
|
75
|
+
condition: async (_ctx, toolResults) => {
|
|
76
|
+
const order = toolResults.find((t) => t.name === "get_order");
|
|
77
|
+
return order?.success && order.result?.isDelayed && order.result?.delayDays >= 2;
|
|
78
|
+
},
|
|
79
|
+
action: async () => {
|
|
80
|
+
return {
|
|
81
|
+
type: "discount_created",
|
|
82
|
+
code: (await shopify.tools.create_discount.execute({
|
|
83
|
+
percent: 10,
|
|
84
|
+
validDays: 30
|
|
85
|
+
})).code,
|
|
86
|
+
percent: 10,
|
|
87
|
+
validDays: 30
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}]
|
|
91
|
+
});
|
|
92
|
+
let kbRuntime;
|
|
93
|
+
if (config.KB_ENABLED === "true") try {
|
|
94
|
+
const { SQLiteKnowledgeStore, EmbeddingService, RetrievalPipeline } = await import("@operor/knowledge");
|
|
95
|
+
const embedder = new EmbeddingService({
|
|
96
|
+
provider: config.KB_EMBEDDING_PROVIDER || config.LLM_PROVIDER,
|
|
97
|
+
apiKey: config.KB_EMBEDDING_API_KEY || config.LLM_API_KEY || "",
|
|
98
|
+
model: config.KB_EMBEDDING_MODEL
|
|
99
|
+
});
|
|
100
|
+
const kbStore = new SQLiteKnowledgeStore(config.KB_DB_PATH || "./knowledge.db", embedder.dimensions);
|
|
101
|
+
await kbStore.initialize();
|
|
102
|
+
const retrieval = new RetrievalPipeline(kbStore, embedder);
|
|
103
|
+
kbRuntime = { retrieve: (q) => retrieval.retrieve(q) };
|
|
104
|
+
console.log("[Operor] 📚 Knowledge Base enabled for conversations");
|
|
105
|
+
} catch (kbError) {
|
|
106
|
+
console.warn("[Operor] ⚠️ Failed to initialize Knowledge Base:", kbError.message);
|
|
107
|
+
}
|
|
108
|
+
if (llm) {
|
|
109
|
+
const { applyLLMOverride } = await import("./llm-override-BIQl0V6H.js").then((n) => n.n);
|
|
110
|
+
applyLLMOverride(agent, llm, allTools, { kbRuntime });
|
|
111
|
+
}
|
|
112
|
+
await os.start();
|
|
113
|
+
const runner = new ConversationRunner({
|
|
114
|
+
agentOS: os,
|
|
115
|
+
customerSimulator: new CustomerSimulator({ llmProvider: llm }),
|
|
116
|
+
conversationEvaluator: new ConversationEvaluator({ llmProvider: llm }),
|
|
117
|
+
verbose: options.verbose ?? false
|
|
118
|
+
});
|
|
119
|
+
if (!options.json) console.log(`\n Running ${scenarios.length} conversation scenario(s)...\n`);
|
|
120
|
+
const results = await runner.runScenarios(scenarios);
|
|
121
|
+
await os.stop();
|
|
122
|
+
if (options.json) console.log(JSON.stringify(results, null, 2));
|
|
123
|
+
else {
|
|
124
|
+
let passed = 0;
|
|
125
|
+
let failed = 0;
|
|
126
|
+
for (const r of results) {
|
|
127
|
+
const icon = r.passed ? "✓" : "✗";
|
|
128
|
+
const status = r.passed ? "PASS" : "FAIL";
|
|
129
|
+
console.log(` ${icon} ${r.scenario.name} — ${status} (${r.turns.length} turns, ${r.duration}ms)`);
|
|
130
|
+
if (!r.passed && r.evaluation.feedback) console.log(` ${r.evaluation.feedback}`);
|
|
131
|
+
if (r.passed) passed++;
|
|
132
|
+
else failed++;
|
|
133
|
+
}
|
|
134
|
+
console.log(`\n Results: ${passed} passed, ${failed} failed out of ${results.length}`);
|
|
135
|
+
console.log(` Status: ${failed === 0 ? "✓ ALL PASSED" : "✗ SOME FAILED"}\n`);
|
|
136
|
+
}
|
|
137
|
+
process.exit(results.every((r) => r.passed) ? 0 : 1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
141
|
+
export { runConverse };
|
|
142
|
+
//# sourceMappingURL=converse-C_PB7-JH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converse-C_PB7-JH.js","names":[],"sources":["../src/commands/converse.ts"],"sourcesContent":["import { readConfig } from '../config.js';\nimport { formatTimestamp } from '../utils.js';\n\nexport async function runConverse(options: {\n scenario?: string;\n file?: string;\n turns?: number;\n persona?: string;\n verbose?: boolean;\n json?: boolean;\n real?: boolean;\n allowWrites?: boolean;\n dryRun?: boolean;\n}): Promise<void> {\n const config = readConfig();\n const { Operor } = await import('@operor/core');\n const { MockProvider } = await import('@operor/provider-mock');\n const {\n MockShopifySkill,\n CustomerSimulator,\n ConversationEvaluator,\n ConversationRunner,\n ECOMMERCE_SCENARIOS,\n SkillTestHarness,\n } = await import('@operor/testing');\n\n // Set up LLM if configured\n let llm: any;\n if (config.LLM_PROVIDER && config.LLM_API_KEY) {\n const { AIProvider } = await import('@operor/llm');\n llm = new AIProvider({\n provider: config.LLM_PROVIDER as any,\n apiKey: config.LLM_API_KEY,\n model: config.LLM_MODEL,\n });\n }\n\n // Determine which scenarios to run\n let scenarios = [...ECOMMERCE_SCENARIOS];\n\n if (options.file) {\n const fs = await import('fs');\n try {\n const raw = fs.readFileSync(options.file, 'utf-8');\n scenarios = JSON.parse(raw);\n } catch (err) {\n console.error(`Failed to load scenarios from ${options.file}:`, err);\n process.exit(1);\n }\n }\n\n if (options.scenario) {\n const match = scenarios.filter(\n (s) => s.name.toLowerCase().includes(options.scenario!.toLowerCase()) ||\n s.id.toLowerCase().includes(options.scenario!.toLowerCase())\n );\n if (match.length === 0) {\n console.error(`No scenario matching \"${options.scenario}\". Available:`);\n scenarios.forEach((s) => console.error(` - ${s.id}: ${s.name}`));\n process.exit(1);\n }\n scenarios = match;\n }\n\n // Apply overrides\n if (options.turns) {\n scenarios = scenarios.map((s) => ({ ...s, maxTurns: options.turns! }));\n }\n if (options.persona) {\n scenarios = scenarios.map((s) => ({ ...s, persona: options.persona! }));\n }\n\n // Set up Operor with mocks\n const os = new Operor({ debug: false, batchWindowMs: 0 });\n const provider = new MockProvider();\n const shopify = new MockShopifySkill();\n\n // Wrap skill with safety harness if --real or --dry-run\n let skill: any = shopify;\n if (options.real || options.dryRun) {\n skill = new SkillTestHarness(shopify, {\n allowWrites: options.allowWrites ?? false,\n dryRun: options.dryRun ?? false,\n });\n await skill.authenticate();\n }\n\n await os.addProvider(provider);\n await os.addSkill(skill);\n\n const allTools = [shopify.tools.get_order, shopify.tools.create_discount, shopify.tools.search_products];\n\n const agent = os.createAgent({\n name: 'Test Agent',\n purpose: 'Handle customer support conversations',\n personality: 'empathetic and solution-focused',\n triggers: ['order_tracking', 'general'],\n tools: allTools,\n rules: [{\n name: 'Auto-compensation',\n condition: async (_ctx: any, toolResults: any[]) => {\n const order = toolResults.find((t) => t.name === 'get_order');\n return order?.success && order.result?.isDelayed && order.result?.delayDays >= 2;\n },\n action: async () => {\n const discount = await shopify.tools.create_discount.execute({ percent: 10, validDays: 30 });\n return { type: 'discount_created', code: discount.code, percent: 10, validDays: 30 };\n },\n }],\n });\n\n // Set up Knowledge Base if enabled\n let kbRuntime: any;\n if (config.KB_ENABLED === 'true') {\n try {\n const { SQLiteKnowledgeStore, EmbeddingService, RetrievalPipeline } = await import('@operor/knowledge');\n const embedder = new EmbeddingService({\n provider: (config.KB_EMBEDDING_PROVIDER || config.LLM_PROVIDER) as any,\n apiKey: config.KB_EMBEDDING_API_KEY || config.LLM_API_KEY || '',\n model: config.KB_EMBEDDING_MODEL,\n });\n const kbStore = new SQLiteKnowledgeStore(config.KB_DB_PATH || './knowledge.db', embedder.dimensions);\n await kbStore.initialize();\n const retrieval = new RetrievalPipeline(kbStore, embedder);\n kbRuntime = { retrieve: (q: string) => retrieval.retrieve(q) };\n console.log('[Operor] 📚 Knowledge Base enabled for conversations');\n } catch (kbError: any) {\n console.warn('[Operor] ⚠️ Failed to initialize Knowledge Base:', kbError.message);\n }\n }\n\n // Override agent.process with LLM-based implementation if LLM is configured\n if (llm) {\n const { applyLLMOverride } = await import('./llm-override.js');\n applyLLMOverride(agent, llm, allTools, { kbRuntime });\n }\n\n await os.start();\n\n // Create runner components with LLM if configured\n const customerSimulator = new CustomerSimulator({ llmProvider: llm });\n const conversationEvaluator = new ConversationEvaluator({ llmProvider: llm });\n const runner = new ConversationRunner({\n agentOS: os,\n customerSimulator,\n conversationEvaluator,\n verbose: options.verbose ?? false,\n });\n\n if (!options.json) {\n console.log(`\\n Running ${scenarios.length} conversation scenario(s)...\\n`);\n }\n\n const results = await runner.runScenarios(scenarios);\n await os.stop();\n\n // Output results\n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n } else {\n let passed = 0;\n let failed = 0;\n\n for (const r of results) {\n const icon = r.passed ? '✓' : '✗';\n const status = r.passed ? 'PASS' : 'FAIL';\n console.log(` ${icon} ${r.scenario.name} — ${status} (${r.turns.length} turns, ${r.duration}ms)`);\n\n if (!r.passed && r.evaluation.feedback) {\n console.log(` ${r.evaluation.feedback}`);\n }\n\n if (r.passed) passed++;\n else failed++;\n }\n\n console.log(`\\n Results: ${passed} passed, ${failed} failed out of ${results.length}`);\n console.log(` Status: ${failed === 0 ? '✓ ALL PASSED' : '✗ SOME FAILED'}\\n`);\n }\n\n process.exit(results.every((r) => r.passed) ? 0 : 1);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { n as readConfig, t as configExists } from "./index.js";
|
|
2
|
+
import * as clack from "@clack/prompts";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/doctor.ts
|
|
5
|
+
async function runDoctor() {
|
|
6
|
+
clack.intro("Operor Doctor");
|
|
7
|
+
if (!configExists()) {
|
|
8
|
+
clack.log.error(".env file not found. Run \"operor setup\" first.");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
const config = readConfig();
|
|
12
|
+
let allPassed = true;
|
|
13
|
+
clack.log.success(".env file found");
|
|
14
|
+
if (config.LLM_PROVIDER && config.LLM_API_KEY) {
|
|
15
|
+
const spinner = clack.spinner();
|
|
16
|
+
spinner.start(`Testing ${config.LLM_PROVIDER} LLM connection...`);
|
|
17
|
+
try {
|
|
18
|
+
const { AIProvider } = await import("@operor/llm");
|
|
19
|
+
await new AIProvider({
|
|
20
|
+
provider: config.LLM_PROVIDER,
|
|
21
|
+
apiKey: config.LLM_API_KEY,
|
|
22
|
+
model: config.LLM_MODEL
|
|
23
|
+
}).complete([{
|
|
24
|
+
role: "user",
|
|
25
|
+
content: "ping"
|
|
26
|
+
}], { maxTokens: 5 });
|
|
27
|
+
spinner.stop(`${config.LLM_PROVIDER} LLM: OK`);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
spinner.stop(`${config.LLM_PROVIDER} LLM: FAILED — ${error.message}`);
|
|
30
|
+
allPassed = false;
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
clack.log.warning("LLM not configured");
|
|
34
|
+
allPassed = false;
|
|
35
|
+
}
|
|
36
|
+
if (config.SKILLS_ENABLED !== "false") {
|
|
37
|
+
const skillSpinner = clack.spinner();
|
|
38
|
+
skillSpinner.start("Checking MCP Skills...");
|
|
39
|
+
try {
|
|
40
|
+
const { loadSkillsConfig, SkillManager } = await import("@operor/skills");
|
|
41
|
+
const enabledSkills = loadSkillsConfig().skills.filter((s) => s.enabled !== false);
|
|
42
|
+
if (enabledSkills.length === 0) skillSpinner.stop("MCP Skills: No skills configured in mcp.json");
|
|
43
|
+
else {
|
|
44
|
+
const errors = [];
|
|
45
|
+
for (const skill of enabledSkills) {
|
|
46
|
+
const error = SkillManager.validateConfig(skill);
|
|
47
|
+
if (error) errors.push(`${skill.name}: ${error}`);
|
|
48
|
+
}
|
|
49
|
+
if (errors.length > 0) {
|
|
50
|
+
skillSpinner.stop(`MCP Skills: ${errors.length} config error(s)`);
|
|
51
|
+
for (const err of errors) clack.log.warning(` ${err}`);
|
|
52
|
+
allPassed = false;
|
|
53
|
+
} else skillSpinner.stop(`MCP Skills: ${enabledSkills.length} skill(s) configured`);
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
skillSpinner.stop("MCP Skills: Not available (mcp.json not found or @operor/skills not installed)");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (config.CHANNEL === "telegram" && config.TELEGRAM_BOT_TOKEN) clack.log.success("Telegram bot token configured");
|
|
60
|
+
else if (config.CHANNEL === "wati") if (config.WATI_API_TOKEN && config.WATI_TENANT_ID) clack.log.success("WATI credentials configured");
|
|
61
|
+
else {
|
|
62
|
+
clack.log.error("WATI: missing WATI_API_TOKEN or WATI_TENANT_ID");
|
|
63
|
+
allPassed = false;
|
|
64
|
+
}
|
|
65
|
+
if (config.KB_ENABLED === "true") {
|
|
66
|
+
const kbSpinner = clack.spinner();
|
|
67
|
+
kbSpinner.start("Checking Knowledge Base...");
|
|
68
|
+
try {
|
|
69
|
+
const { writeFileSync, unlinkSync, existsSync } = await import("node:fs");
|
|
70
|
+
const { dirname } = await import("node:path");
|
|
71
|
+
const { mkdirSync } = await import("node:fs");
|
|
72
|
+
const dbPath = config.KB_DB_PATH || "./knowledge.db";
|
|
73
|
+
const dir = dirname(dbPath);
|
|
74
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
75
|
+
const testFile = dbPath + ".write-test";
|
|
76
|
+
writeFileSync(testFile, "");
|
|
77
|
+
unlinkSync(testFile);
|
|
78
|
+
if (config.KB_EMBEDDING_PROVIDER !== "ollama" && !config.KB_EMBEDDING_API_KEY) {
|
|
79
|
+
kbSpinner.stop("Knowledge Base: WARNING — no embedding API key set");
|
|
80
|
+
allPassed = false;
|
|
81
|
+
} else try {
|
|
82
|
+
await import("@operor/knowledge");
|
|
83
|
+
kbSpinner.stop("Knowledge Base: OK");
|
|
84
|
+
} catch {
|
|
85
|
+
kbSpinner.stop("Knowledge Base: OK (config valid, @operor/knowledge not installed yet)");
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
kbSpinner.stop(`Knowledge Base: FAILED — ${error.message}`);
|
|
89
|
+
allPassed = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (config.ANALYTICS_ENABLED !== "false") {
|
|
93
|
+
const analyticsSpinner = clack.spinner();
|
|
94
|
+
analyticsSpinner.start("Checking Analytics...");
|
|
95
|
+
try {
|
|
96
|
+
const { writeFileSync, unlinkSync, existsSync } = await import("node:fs");
|
|
97
|
+
const { dirname } = await import("node:path");
|
|
98
|
+
const { mkdirSync } = await import("node:fs");
|
|
99
|
+
const dbPath = config.ANALYTICS_DB_PATH || "./analytics.db";
|
|
100
|
+
const dir = dirname(dbPath);
|
|
101
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
102
|
+
const testFile = dbPath + ".write-test";
|
|
103
|
+
writeFileSync(testFile, "");
|
|
104
|
+
unlinkSync(testFile);
|
|
105
|
+
analyticsSpinner.stop("Analytics: OK (DB path writable)");
|
|
106
|
+
} catch (error) {
|
|
107
|
+
analyticsSpinner.stop(`Analytics: FAILED — ${error.message}`);
|
|
108
|
+
allPassed = false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const nodeVersion = process.versions.node;
|
|
112
|
+
if (parseInt(nodeVersion.split(".")[0]) >= 18) clack.log.success(`Node.js ${nodeVersion}`);
|
|
113
|
+
else {
|
|
114
|
+
clack.log.error(`Node.js ${nodeVersion} — requires >= 18`);
|
|
115
|
+
allPassed = false;
|
|
116
|
+
}
|
|
117
|
+
clack.outro(allPassed ? "All checks passed!" : "Some checks failed. Fix the issues above.");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
export { runDoctor };
|
|
122
|
+
//# sourceMappingURL=doctor-98gPl743.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-98gPl743.js","names":[],"sources":["../src/commands/doctor.ts"],"sourcesContent":["import * as clack from '@clack/prompts';\nimport { readConfig, configExists } from '../config.js';\n\nexport async function runDoctor(): Promise<void> {\n clack.intro('Operor Doctor');\n\n if (!configExists()) {\n clack.log.error('.env file not found. Run \"operor setup\" first.');\n process.exit(1);\n }\n\n const config = readConfig();\n let allPassed = true;\n\n // 1. Check .env exists\n clack.log.success('.env file found');\n\n // 2. Validate LLM\n if (config.LLM_PROVIDER && config.LLM_API_KEY) {\n const spinner = clack.spinner();\n spinner.start(`Testing ${config.LLM_PROVIDER} LLM connection...`);\n try {\n const { AIProvider } = await import('@operor/llm');\n const llm = new AIProvider({\n provider: config.LLM_PROVIDER as any,\n apiKey: config.LLM_API_KEY,\n model: config.LLM_MODEL,\n });\n await llm.complete([{ role: 'user', content: 'ping' }], { maxTokens: 5 });\n spinner.stop(`${config.LLM_PROVIDER} LLM: OK`);\n } catch (error: any) {\n spinner.stop(`${config.LLM_PROVIDER} LLM: FAILED — ${error.message}`);\n allPassed = false;\n }\n } else {\n clack.log.warning('LLM not configured');\n allPassed = false;\n }\n\n // 3. Validate MCP Skills\n if (config.SKILLS_ENABLED !== 'false') {\n const skillSpinner = clack.spinner();\n skillSpinner.start('Checking MCP Skills...');\n try {\n const { loadSkillsConfig, SkillManager } = await import('@operor/skills');\n const skillsConfig = loadSkillsConfig();\n const enabledSkills = skillsConfig.skills.filter((s: any) => s.enabled !== false);\n\n if (enabledSkills.length === 0) {\n skillSpinner.stop('MCP Skills: No skills configured in mcp.json');\n } else {\n // Validate config only (don't start servers)\n const errors: string[] = [];\n for (const skill of enabledSkills) {\n const error = SkillManager.validateConfig(skill);\n if (error) errors.push(`${skill.name}: ${error}`);\n }\n if (errors.length > 0) {\n skillSpinner.stop(`MCP Skills: ${errors.length} config error(s)`);\n for (const err of errors) clack.log.warning(` ${err}`);\n allPassed = false;\n } else {\n skillSpinner.stop(`MCP Skills: ${enabledSkills.length} skill(s) configured`);\n }\n }\n } catch (error: any) {\n skillSpinner.stop('MCP Skills: Not available (mcp.json not found or @operor/skills not installed)');\n }\n }\n\n // 4. Validate channel credentials\n if (config.CHANNEL === 'telegram' && config.TELEGRAM_BOT_TOKEN) {\n clack.log.success('Telegram bot token configured');\n } else if (config.CHANNEL === 'wati') {\n if (config.WATI_API_TOKEN && config.WATI_TENANT_ID) {\n clack.log.success('WATI credentials configured');\n } else {\n clack.log.error('WATI: missing WATI_API_TOKEN or WATI_TENANT_ID');\n allPassed = false;\n }\n }\n\n // 5. Knowledge Base checks\n if (config.KB_ENABLED === 'true') {\n const kbSpinner = clack.spinner();\n kbSpinner.start('Checking Knowledge Base...');\n try {\n // Check DB path is writable\n const { writeFileSync, unlinkSync, existsSync } = await import('node:fs');\n const { dirname } = await import('node:path');\n const { mkdirSync } = await import('node:fs');\n const dbPath = config.KB_DB_PATH || './knowledge.db';\n const dir = dirname(dbPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const testFile = dbPath + '.write-test';\n writeFileSync(testFile, '');\n unlinkSync(testFile);\n\n // Check embedding API key (unless ollama)\n if (config.KB_EMBEDDING_PROVIDER !== 'ollama' && !config.KB_EMBEDDING_API_KEY) {\n kbSpinner.stop('Knowledge Base: WARNING — no embedding API key set');\n allPassed = false;\n } else {\n // Try loading sqlite-vec\n try {\n await import('@operor/knowledge');\n kbSpinner.stop('Knowledge Base: OK');\n } catch {\n kbSpinner.stop('Knowledge Base: OK (config valid, @operor/knowledge not installed yet)');\n }\n }\n } catch (error: any) {\n kbSpinner.stop(`Knowledge Base: FAILED — ${error.message}`);\n allPassed = false;\n }\n }\n\n // 6. Analytics checks\n if (config.ANALYTICS_ENABLED !== 'false') {\n const analyticsSpinner = clack.spinner();\n analyticsSpinner.start('Checking Analytics...');\n try {\n const { writeFileSync, unlinkSync, existsSync } = await import('node:fs');\n const { dirname } = await import('node:path');\n const { mkdirSync } = await import('node:fs');\n const dbPath = config.ANALYTICS_DB_PATH || './analytics.db';\n const dir = dirname(dbPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const testFile = dbPath + '.write-test';\n writeFileSync(testFile, '');\n unlinkSync(testFile);\n analyticsSpinner.stop('Analytics: OK (DB path writable)');\n } catch (error: any) {\n analyticsSpinner.stop(`Analytics: FAILED — ${error.message}`);\n allPassed = false;\n }\n }\n\n // 7. Check Node.js version\n const nodeVersion = process.versions.node;\n const major = parseInt(nodeVersion.split('.')[0]);\n if (major >= 18) {\n clack.log.success(`Node.js ${nodeVersion}`);\n } else {\n clack.log.error(`Node.js ${nodeVersion} — requires >= 18`);\n allPassed = false;\n }\n\n clack.outro(allPassed ? 'All checks passed!' : 'Some checks failed. Fix the issues above.');\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|