@opperai/setup 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 ADDED
@@ -0,0 +1,27 @@
1
+ # @opperai/setup
2
+
3
+ Interactive CLI to set up Opper tooling.
4
+
5
+ ```bash
6
+ npx @opperai/setup
7
+ ```
8
+
9
+ ## What it installs
10
+
11
+ **AI Code Editors**
12
+ - **Skills** — Opper skills for your AI code editor
13
+ - **OpenCode** — Configure Opper as an OpenCode provider with curated models
14
+
15
+ **SDKs**
16
+ - **Node SDK** — AI functions, RAG, and tracing for TypeScript (`opperai`)
17
+ - **Node Agent SDK** — Build agents with tool use and reasoning (`@opperai/agents`)
18
+ - **Python SDK** — AI functions, RAG, and tracing for Python (`opperai`)
19
+ - **Python Agent SDK** — Build agents with tool use and reasoning (`opper-agents`)
20
+
21
+ **Tools**
22
+ - **Opper CLI** — Call functions, manage indexes, and track usage from the terminal
23
+
24
+ ## Requirements
25
+
26
+ - Node.js 18+
27
+ - An Opper API key from [platform.opper.ai](https://platform.opper.ai)
@@ -0,0 +1,116 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "provider": {
4
+ "opper": {
5
+ "npm": "@ai-sdk/openai-compatible",
6
+ "name": "Opper",
7
+ "options": {
8
+ "baseURL": "http://localhost:8000/v2/openai",
9
+ "apiKey": "{env:OPPER_API_KEY}"
10
+ },
11
+ "models": {
12
+ "anthropic/claude-sonnet-4.5": {
13
+ "name": "Claude Sonnet 4.5",
14
+ "cost": { "input": 3.00, "output": 15.00 },
15
+ "limit": { "context": 200000, "output": 64000 }
16
+ },
17
+ "anthropic/claude-opus-4.5": {
18
+ "name": "Claude Opus 4.5",
19
+ "cost": { "input": 5.00, "output": 25.00 },
20
+ "limit": { "context": 200000, "output": 64000 }
21
+ },
22
+ "aws/claude-sonnet-4.5-eu": {
23
+ "name": "Claude Sonnet 4.5 (EU)",
24
+ "cost": { "input": 3.00, "output": 15.00 },
25
+ "limit": { "context": 200000, "output": 64000 }
26
+ },
27
+ "aws/claude-opus-4.5-eu": {
28
+ "name": "Claude Opus 4.5 (EU)",
29
+ "cost": { "input": 5.00, "output": 25.00 },
30
+ "limit": { "context": 200000, "output": 64000 }
31
+ },
32
+ "openai/gpt-5.2": {
33
+ "name": "GPT 5.2",
34
+ "cost": { "input": 1.75, "output": 14.00 },
35
+ "limit": { "context": 400000, "output": 128000 }
36
+ },
37
+ "openai/gpt-5-mini": {
38
+ "name": "GPT 5 Mini",
39
+ "cost": { "input": 0.25, "output": 1.00 },
40
+ "limit": { "context": 400000, "output": 128000 }
41
+ },
42
+ "openai/gpt-5-nano": {
43
+ "name": "GPT 5 Nano",
44
+ "cost": { "input": 0.05, "output": 0.40 },
45
+ "limit": { "context": 400000, "output": 128000 }
46
+ },
47
+ "azure/gpt-5-mini": {
48
+ "name": "GPT 5 Mini (EU)",
49
+ "cost": { "input": 0.25, "output": 2.00 },
50
+ "limit": { "context": 400000, "output": 128000 }
51
+ },
52
+ "azure/gpt-5-nano": {
53
+ "name": "GPT 5 Nano (EU)",
54
+ "cost": { "input": 0.05, "output": 0.40 },
55
+ "limit": { "context": 400000, "output": 128000 }
56
+ },
57
+ "gcp/gemini-2.5-pro": {
58
+ "name": "Gemini 2.5 Pro",
59
+ "cost": { "input": 1.25, "output": 10.00 },
60
+ "limit": { "context": 1000000, "output": 65536 }
61
+ },
62
+ "gcp/gemini-2.5-pro-eu": {
63
+ "name": "Gemini 2.5 Pro (EU)",
64
+ "cost": { "input": 1.25, "output": 10.00 },
65
+ "limit": { "context": 1000000, "output": 65536 }
66
+ },
67
+ "gcp/gemini-2.5-flash": {
68
+ "name": "Gemini 2.5 Flash",
69
+ "cost": { "input": 0.30, "output": 2.50 },
70
+ "limit": { "context": 1000000, "output": 65536 }
71
+ },
72
+ "gcp/gemini-2.5-flash-eu": {
73
+ "name": "Gemini 2.5 Flash (EU)",
74
+ "cost": { "input": 0.30, "output": 2.50 },
75
+ "limit": { "context": 1000000, "output": 65536 }
76
+ },
77
+ "gcp/gemini-2.5-flash-lite": {
78
+ "name": "Gemini 2.5 Flash Lite",
79
+ "cost": { "input": 0.10, "output": 0.40 },
80
+ "limit": { "context": 1000000, "output": 65536 }
81
+ },
82
+ "gcp/gemini-2.5-flash-lite-eu": {
83
+ "name": "Gemini 2.5 Flash Lite (EU)",
84
+ "cost": { "input": 0.10, "output": 0.40 },
85
+ "limit": { "context": 1000000, "output": 65536 }
86
+ },
87
+ "gcp/gemini-3-flash-preview": {
88
+ "name": "Gemini 3 Flash Preview",
89
+ "cost": { "input": 0.50, "output": 3.00 },
90
+ "limit": { "context": 1000000, "output": 65536 }
91
+ },
92
+ "fireworks/kimi-k2.5": {
93
+ "name": "Kimi K2.5",
94
+ "cost": { "input": 0.60, "output": 3.00 },
95
+ "limit": { "context": 256000, "output": 65536 }
96
+ },
97
+ "fireworks/glm-4.7": {
98
+ "name": "GLM 4.7",
99
+ "cost": { "input": 0.60, "output": 2.20 },
100
+ "limit": { "context": 200000, "output": 128000 }
101
+ },
102
+ "groq/gpt-oss-120b": {
103
+ "name": "GPT OSS 120B",
104
+ "cost": { "input": 0.15, "output": 0.75 },
105
+ "limit": { "context": 131072, "output": 131072 }
106
+ },
107
+ "aws/gpt-oss-120b-eu": {
108
+ "name": "GPT OSS 120B (EU)",
109
+ "cost": { "input": 0.15, "output": 0.60 },
110
+ "limit": { "context": 128000, "output": 8192 }
111
+ }
112
+ }
113
+ }
114
+ },
115
+ "model": "opper/gcp/gemini-2.5-flash-eu"
116
+ }
@@ -0,0 +1 @@
1
+ export declare function setupApiKey(): Promise<void>;
package/dist/apikey.js ADDED
@@ -0,0 +1,46 @@
1
+ import { confirm, input } from "@inquirer/prompts";
2
+ import { exec } from "node:child_process";
3
+ function openBrowser(url) {
4
+ const cmd = process.platform === "darwin"
5
+ ? `open "${url}"`
6
+ : process.platform === "win32"
7
+ ? `start "${url}"`
8
+ : `xdg-open "${url}"`;
9
+ exec(cmd);
10
+ }
11
+ export async function setupApiKey() {
12
+ if (process.env.OPPER_API_KEY) {
13
+ console.log("OPPER_API_KEY is set.\n");
14
+ return;
15
+ }
16
+ console.log("OPPER_API_KEY is not set.\n");
17
+ const wantsKey = await confirm({
18
+ message: "Would you like to set up your Opper API key now?",
19
+ default: true,
20
+ });
21
+ if (!wantsKey) {
22
+ console.log();
23
+ return;
24
+ }
25
+ const openSite = await confirm({
26
+ message: "Open https://platform.opper.ai to get your API key?",
27
+ default: true,
28
+ });
29
+ if (openSite) {
30
+ openBrowser("https://platform.opper.ai");
31
+ console.log("\nOpening browser...\n");
32
+ }
33
+ const key = await input({
34
+ message: "Paste your API key:",
35
+ validate: (value) => (value.trim().length > 0 ? true : "API key cannot be empty"),
36
+ });
37
+ const shell = process.env.SHELL || "";
38
+ const rcFile = shell.includes("zsh")
39
+ ? "~/.zshrc"
40
+ : shell.includes("bash")
41
+ ? "~/.bashrc"
42
+ : "your shell profile";
43
+ console.log(`\nAdd this to ${rcFile}:\n`);
44
+ console.log(` export OPPER_API_KEY=${key.trim()}\n`);
45
+ console.log(`Then run: source ${rcFile}\n`);
46
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ import { checkbox, Separator } from "@inquirer/prompts";
3
+ import { setupOpenCode } from "./opencode.js";
4
+ import { setupSkills } from "./skills.js";
5
+ import { setupApiKey } from "./apikey.js";
6
+ import { installPackage, installCli } from "./install.js";
7
+ async function main() {
8
+ console.log();
9
+ await setupApiKey();
10
+ const selections = await checkbox({
11
+ message: "What would you like to set up? (space to select/deselect, enter to confirm)",
12
+ choices: [
13
+ new Separator(" "),
14
+ new Separator("── AI Code Editors ──"),
15
+ {
16
+ name: "Skills — Add Opper skills to your AI code editor",
17
+ value: "skills",
18
+ checked: true,
19
+ },
20
+ {
21
+ name: "OpenCode — Use Opper models in OpenCode",
22
+ value: "opencode",
23
+ },
24
+ new Separator(" "),
25
+ new Separator("── SDKs ──"),
26
+ {
27
+ name: "Node SDK — AI functions, RAG, and tracing for TypeScript (opperai)",
28
+ value: "node-sdk",
29
+ },
30
+ {
31
+ name: "Node Agent SDK — Build agents with tool use and reasoning (@opperai/agents)",
32
+ value: "node-agents",
33
+ },
34
+ {
35
+ name: "Python SDK — AI functions, RAG, and tracing for Python (opperai)",
36
+ value: "python-sdk",
37
+ },
38
+ {
39
+ name: "Python Agent SDK — Build agents with tool use and reasoning (opper-agents)",
40
+ value: "python-agents",
41
+ },
42
+ new Separator(" "),
43
+ new Separator("── Tools ──"),
44
+ {
45
+ name: "Opper CLI — Call functions, manage indexes, and track usage from the terminal",
46
+ value: "cli",
47
+ },
48
+ ],
49
+ });
50
+ if (selections.length === 0) {
51
+ console.log("Nothing selected. Exiting.");
52
+ return;
53
+ }
54
+ if (selections.includes("skills")) {
55
+ await setupSkills();
56
+ }
57
+ if (selections.includes("opencode")) {
58
+ await setupOpenCode();
59
+ }
60
+ if (selections.includes("node-sdk")) {
61
+ await installPackage("npm", "opperai", "Opper Node SDK");
62
+ }
63
+ if (selections.includes("node-agents")) {
64
+ await installPackage("npm", "@opperai/agents", "Opper Node Agent SDK");
65
+ }
66
+ if (selections.includes("python-sdk")) {
67
+ await installPackage("pip", "opperai", "Opper Python SDK");
68
+ }
69
+ if (selections.includes("python-agents")) {
70
+ await installPackage("pip", "opper-agents", "Opper Python Agent SDK");
71
+ }
72
+ if (selections.includes("cli")) {
73
+ await installCli();
74
+ }
75
+ console.log("\nDone!");
76
+ }
77
+ main().catch((error) => {
78
+ if (error instanceof Error && error.name === "ExitPromptError") {
79
+ console.log("\nSetup cancelled.");
80
+ process.exit(0);
81
+ }
82
+ console.error("\nSetup failed:", error instanceof Error ? error.message : error);
83
+ process.exit(1);
84
+ });
@@ -0,0 +1,2 @@
1
+ export declare function installPackage(manager: "npm" | "pip", pkg: string, label: string): Promise<void>;
2
+ export declare function installCli(): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { execSync } from "node:child_process";
2
+ export async function installPackage(manager, pkg, label) {
3
+ console.log(`\n--- ${label} ---\n`);
4
+ const cmd = manager === "npm" ? `npm install ${pkg}` : `pip install ${pkg}`;
5
+ console.log(`Running: ${cmd}\n`);
6
+ execSync(cmd, { stdio: "inherit" });
7
+ console.log(`\n${label} installed.`);
8
+ }
9
+ export async function installCli() {
10
+ console.log("\n--- Opper CLI ---\n");
11
+ if (process.platform !== "darwin") {
12
+ console.log("The Opper CLI is currently available via Homebrew on macOS.");
13
+ console.log("For other platforms, download from:");
14
+ console.log(" https://github.com/opper-ai/oppercli/releases/latest\n");
15
+ return;
16
+ }
17
+ console.log("Installing via Homebrew...\n");
18
+ execSync("brew tap opper-ai/oppercli git@github.com:opper-ai/oppercli && brew install opper", {
19
+ stdio: "inherit",
20
+ });
21
+ console.log("\nOpper CLI installed. Run `opper config add default <your-api-key>` to configure.");
22
+ }
@@ -0,0 +1 @@
1
+ export declare function setupOpenCode(): Promise<void>;
@@ -0,0 +1,48 @@
1
+ import { readFileSync, mkdirSync, writeFileSync, existsSync } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { fileURLToPath } from "node:url";
5
+ import { confirm } from "@inquirer/prompts";
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ export async function setupOpenCode() {
8
+ console.log("\n--- OpenCode Setup ---\n");
9
+ // Read embedded config template
10
+ const templatePath = join(__dirname, "..", "data", "opencode.json");
11
+ const config = readFileSync(templatePath, "utf-8");
12
+ const configDir = join(homedir(), ".config", "opencode");
13
+ const configPath = join(configDir, "opencode.json");
14
+ // Check if config already exists with opper provider
15
+ if (existsSync(configPath)) {
16
+ try {
17
+ const existing = JSON.parse(readFileSync(configPath, "utf-8"));
18
+ if (existing?.provider?.opper) {
19
+ const overwrite = await confirm({
20
+ message: "OpenCode config already has an Opper provider. Overwrite?",
21
+ default: false,
22
+ });
23
+ if (!overwrite) {
24
+ console.log("Skipping OpenCode setup.");
25
+ return;
26
+ }
27
+ }
28
+ }
29
+ catch {
30
+ // If we can't parse the existing file, proceed with overwrite
31
+ }
32
+ }
33
+ // Write config
34
+ mkdirSync(configDir, { recursive: true });
35
+ writeFileSync(configPath, config, "utf-8");
36
+ console.log(`Wrote config to ${configPath}`);
37
+ // Check for API key
38
+ if (!process.env.OPPER_API_KEY) {
39
+ console.log("\n⚠ OPPER_API_KEY is not set. Add it to your shell profile:\n" +
40
+ "\n export OPPER_API_KEY=<your-api-key>\n" +
41
+ "\nGet your API key at https://platform.opper.ai\n");
42
+ }
43
+ else {
44
+ console.log("OPPER_API_KEY is set.");
45
+ }
46
+ const parsed = JSON.parse(config);
47
+ console.log(`Default model: ${parsed.model}`);
48
+ }
@@ -0,0 +1 @@
1
+ export declare function setupSkills(): Promise<void>;
package/dist/skills.js ADDED
@@ -0,0 +1,9 @@
1
+ import { execSync } from "node:child_process";
2
+ export async function setupSkills() {
3
+ console.log("\n--- Skills Setup ---\n");
4
+ console.log("Installing Opper skills for Claude Code...\n");
5
+ execSync("npx skills add opper-ai/opper-skills", {
6
+ stdio: "inherit",
7
+ });
8
+ console.log("\nSkills installed successfully.");
9
+ }
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@opperai/setup",
3
+ "version": "0.1.0",
4
+ "description": "Set up Opper tooling for AI code editors",
5
+ "type": "module",
6
+ "bin": {
7
+ "opper-setup": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "data"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx src/index.ts",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "dependencies": {
19
+ "@inquirer/prompts": "^7"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^25.2.0",
23
+ "tsx": "^4",
24
+ "typescript": "^5"
25
+ }
26
+ }