apiario 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,57 @@
1
+ # 🐝 apiario — CLI Harness
2
+
3
+ An `npx`-installable CLI tool that wraps [pi.dev](https://pi.dev) (v0.74.0),
4
+ pre-configured to use Apiário's API (`api.apiario.dev`) as the LLM provider.
5
+ Launches directly into pi's TUI interactive mode.
6
+
7
+ ## Usage
8
+
9
+ ```bash
10
+ # Run directly (requires Node >= 20.6.0)
11
+ npx apiario
12
+
13
+ # Or with an explicit API key
14
+ APIARIO_API_KEY=sk-... npx apiario
15
+ ```
16
+
17
+ On first run, the tool will guide you through setting up your API key.
18
+
19
+ ## Quick start
20
+
21
+ 1. **Get an API key** at [platform.apiario.dev/auth](https://platform.apiario.dev/auth)
22
+ 2. **Run** `npx apiario`
23
+ 3. Paste your `sk-...` key when prompted
24
+ 4. Start chatting in the TUI
25
+
26
+ ## Environment variables
27
+
28
+ | Variable | Required | Description |
29
+ |---|---|---|
30
+ | `APIARIO_API_KEY` | No | API key. Falls back to `~/.config/apiario/settings.json` if not set |
31
+
32
+ ## Config file location
33
+
34
+ All configuration is stored under `~/.config/apiario/`:
35
+
36
+ - `settings.json` — API key
37
+ - `models.json` — Cached model list (24 h TTL)
38
+
39
+ ## Development
40
+
41
+ ```bash
42
+ # Install dependencies
43
+ cd harness && npm install
44
+
45
+ # Build
46
+ npm run build
47
+
48
+ # Watch mode
49
+ npm run dev
50
+
51
+ # Run locally
52
+ node dist/cli.js
53
+ ```
54
+
55
+ ## License
56
+
57
+ MIT
package/dist/auth.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import type { ApiarioConfig } from "./types.js";
2
+ /**
3
+ * Resolve the API key in order of priority:
4
+ * 1. `APIARIO_API_KEY` environment variable
5
+ * 2. `~/.config/apiario/settings.json`
6
+ *
7
+ * Returns the key if found, or `null` if neither source has one.
8
+ */
9
+ export declare function resolveApiKey(): string | null;
10
+ /**
11
+ * Validate an API key by hitting GET /v1/models.
12
+ * Returns `true` if the endpoint responds with a non-4xx status.
13
+ */
14
+ export declare function validateApiKey(apiKey: string): Promise<boolean>;
15
+ /**
16
+ * Run the interactive setup wizard.
17
+ *
18
+ * 1. Prints welcome box
19
+ * 2. Prompts for API key (hidden input)
20
+ * 3. Validates the key against GET /v1/models
21
+ * 4. On success: saves config, prints MOTD, returns config
22
+ * 5. On failure: retries up to `maxRetries` times
23
+ *
24
+ * @param maxRetries Maximum number of validation attempts (default 3).
25
+ * @returns The validated ApiarioConfig, or `null` if the user gave up.
26
+ */
27
+ export declare function runSetupWizard(maxRetries?: number): Promise<ApiarioConfig | null>;
28
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAc7C;AAMD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcrE;AAgGD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,UAAU,SAAI,GACb,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA6C/B"}
package/dist/auth.js ADDED
@@ -0,0 +1,180 @@
1
+ import { createInterface } from "readline";
2
+ import { loadConfig, saveConfig, SETTINGS_PATH } from "./config.js";
3
+ import { API_BASE_URL, apiClientHeaders } from "./client.js";
4
+ // ---------------------------------------------------------------------------
5
+ // Constants
6
+ // ---------------------------------------------------------------------------
7
+ const MOTD = "Apiário - de dev pra dev";
8
+ // ---------------------------------------------------------------------------
9
+ // Key resolution (env var > config file > wizard)
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Resolve the API key in order of priority:
13
+ * 1. `APIARIO_API_KEY` environment variable
14
+ * 2. `~/.config/apiario/settings.json`
15
+ *
16
+ * Returns the key if found, or `null` if neither source has one.
17
+ */
18
+ export function resolveApiKey() {
19
+ // 1. Environment variable
20
+ const envKey = process.env.APIARIO_API_KEY;
21
+ if (typeof envKey === "string" && envKey.trim().length > 0) {
22
+ return envKey.trim();
23
+ }
24
+ // 2. Config file
25
+ const config = loadConfig();
26
+ if (config && config.apiKey.trim().length > 0) {
27
+ return config.apiKey.trim();
28
+ }
29
+ return null;
30
+ }
31
+ // ---------------------------------------------------------------------------
32
+ // Key validation
33
+ // ---------------------------------------------------------------------------
34
+ /**
35
+ * Validate an API key by hitting GET /v1/models.
36
+ * Returns `true` if the endpoint responds with a non-4xx status.
37
+ */
38
+ export async function validateApiKey(apiKey) {
39
+ try {
40
+ const res = await fetch(`${API_BASE_URL}/models`, {
41
+ headers: {
42
+ ...apiClientHeaders(),
43
+ Authorization: `Bearer ${apiKey}`,
44
+ Accept: "application/json",
45
+ },
46
+ });
47
+ // Any non-4xx response means the key is accepted
48
+ return res.status < 400;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Setup wizard
56
+ // ---------------------------------------------------------------------------
57
+ /**
58
+ * Prompt the user for a single line of input, optionally hiding what they type.
59
+ * Returns the trimmed input.
60
+ */
61
+ function promptInput(question, hidden = false) {
62
+ return new Promise((resolve) => {
63
+ const rl = createInterface({
64
+ input: process.stdin,
65
+ output: process.stdout,
66
+ terminal: true,
67
+ });
68
+ if (hidden) {
69
+ // Raw mode: read characters one by one, echo '*' instead of the actual char
70
+ const stdin = process.stdin;
71
+ const stdout = process.stdout;
72
+ stdin.setRawMode?.(true);
73
+ stdin.resume();
74
+ let input = "";
75
+ stdout.write(question);
76
+ const onData = (chunk) => {
77
+ const char = chunk.toString();
78
+ if (char === "\r" || char === "\n") {
79
+ stdin.setRawMode?.(false);
80
+ stdin.pause();
81
+ stdin.removeListener("data", onData);
82
+ stdout.write("\n");
83
+ rl.close();
84
+ resolve(input);
85
+ return;
86
+ }
87
+ if (char === "\u0003") {
88
+ // Ctrl+C
89
+ stdin.setRawMode?.(false);
90
+ stdin.pause();
91
+ stdin.removeListener("data", onData);
92
+ stdout.write("\n");
93
+ rl.close();
94
+ process.exit(1);
95
+ }
96
+ // Backspace
97
+ if (char === "\u007f") {
98
+ if (input.length > 0) {
99
+ input = input.slice(0, -1);
100
+ stdout.write("\b \b");
101
+ }
102
+ return;
103
+ }
104
+ input += char;
105
+ stdout.write("*");
106
+ };
107
+ stdin.on("data", onData);
108
+ }
109
+ else {
110
+ rl.question(question, (answer) => {
111
+ rl.close();
112
+ resolve(answer.trim());
113
+ });
114
+ }
115
+ });
116
+ }
117
+ /**
118
+ * Print the welcome box from DESIGN.md.
119
+ */
120
+ function printWizardBox() {
121
+ const border = "╔══════════════════════════════════════════════╗";
122
+ const bottom = "╚══════════════════════════════════════════════╝";
123
+ const pad = (line) => `║ ${line.padEnd(44)}║`;
124
+ console.log(`\n${border}`);
125
+ console.log(pad("🐝 Apiário Dev — CLI Harness"));
126
+ console.log(pad(""));
127
+ console.log(pad("Bem-vindo! Primeiro uso detectado."));
128
+ console.log(pad("Acesse https://platform.apiario.dev/auth,"));
129
+ console.log(pad("crie uma chave de API em API Keys,"));
130
+ console.log(pad("e cole o token (sk-...) abaixo."));
131
+ console.log(pad(""));
132
+ console.log(pad("🔑 Chave de API: ********************"));
133
+ console.log(`${bottom}\n`);
134
+ }
135
+ /**
136
+ * Run the interactive setup wizard.
137
+ *
138
+ * 1. Prints welcome box
139
+ * 2. Prompts for API key (hidden input)
140
+ * 3. Validates the key against GET /v1/models
141
+ * 4. On success: saves config, prints MOTD, returns config
142
+ * 5. On failure: retries up to `maxRetries` times
143
+ *
144
+ * @param maxRetries Maximum number of validation attempts (default 3).
145
+ * @returns The validated ApiarioConfig, or `null` if the user gave up.
146
+ */
147
+ export async function runSetupWizard(maxRetries = 3) {
148
+ printWizardBox();
149
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
150
+ const apiKey = await promptInput("🔑 Chave de API: ", true);
151
+ if (!apiKey || apiKey.length === 0) {
152
+ console.log(" ❌ Nenhuma chave informada. Tente novamente.");
153
+ continue;
154
+ }
155
+ if (!apiKey.startsWith("sk-")) {
156
+ console.log(" ❌ Chave inválida. A chave deve começar com 'sk-'.");
157
+ if (attempt < maxRetries) {
158
+ console.log(" Tente novamente.\n");
159
+ }
160
+ continue;
161
+ }
162
+ console.log(" ⏳ Validando chave...");
163
+ const valid = await validateApiKey(apiKey);
164
+ if (valid) {
165
+ const config = { apiKey };
166
+ saveConfig(config);
167
+ console.log(` ✅ Chave salva em ${SETTINGS_PATH}`);
168
+ console.log(`\n 🐝 ${MOTD}\n`);
169
+ return config;
170
+ }
171
+ console.log(" ❌ Chave rejeitada pela API. Verifique se o token está correto.");
172
+ if (attempt < maxRetries) {
173
+ console.log(" Tente novamente.\n");
174
+ }
175
+ }
176
+ console.log("\n ❌ Número máximo de tentativas excedido.");
177
+ console.log(" Execute 'npx apiario' novamente quando tiver uma chave válida.\n");
178
+ return null;
179
+ }
180
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ import { AuthStorage, ModelRegistry, InteractiveMode, runPrintMode, createAgentSessionRuntime, createAgentSessionFromServices, createAgentSessionServices, SessionManager, } from "@earendil-works/pi-coding-agent";
3
+ import { resolveApiKey, runSetupWizard } from "./auth.js";
4
+ import { resolveModels, mapToProviderModelConfigs, sortModelsByPriority } from "./provider.js";
5
+ import { API_BASE_URL, apiClientHeaders } from "./client.js";
6
+ import { homedir } from "os";
7
+ import { join } from "path";
8
+ // ---------------------------------------------------------------------------
9
+ // Constants
10
+ // ---------------------------------------------------------------------------
11
+ const AGENT_DIR = join(homedir(), ".config", "apiario");
12
+ // ---------------------------------------------------------------------------
13
+ // Main
14
+ // ---------------------------------------------------------------------------
15
+ async function main() {
16
+ // ── 1. Resolve API key ──────────────────────────────────────────────
17
+ let apiKey = resolveApiKey();
18
+ if (!apiKey) {
19
+ const config = await runSetupWizard();
20
+ if (!config) {
21
+ console.error("\n ❌ Nenhuma chave de API configurada. Execute novamente quando tiver uma chave válida.");
22
+ process.exit(1);
23
+ }
24
+ apiKey = config.apiKey;
25
+ }
26
+ // ── 2. Fetch & cache models ────────────────────────────────────────
27
+ let models;
28
+ try {
29
+ const rawCards = await resolveModels(apiKey);
30
+ const mapped = mapToProviderModelConfigs(rawCards);
31
+ models = sortModelsByPriority(mapped);
32
+ console.error(` 📦 ${models.length} modelos disponíveis via Apiário Dev\n`);
33
+ }
34
+ catch (err) {
35
+ console.error(" ❌ Erro ao buscar modelos da API. Verifique sua conexão e chave de API.\n");
36
+ process.exit(2);
37
+ }
38
+ // ── 3. Set up pi.dev infrastructure with our provider ──────────────
39
+ const authStorage = AuthStorage.create();
40
+ // Store the API key in auth storage so pi can resolve it
41
+ authStorage.setRuntimeApiKey("apiario", apiKey);
42
+ const modelRegistry = ModelRegistry.inMemory(authStorage);
43
+ modelRegistry.registerProvider("apiario", {
44
+ name: "Apiário Dev",
45
+ baseUrl: API_BASE_URL,
46
+ apiKey,
47
+ api: "openai-completions",
48
+ authHeader: true,
49
+ headers: apiClientHeaders(),
50
+ models,
51
+ });
52
+ // ── 4. Create runtime ──────────────────────────────────────────────
53
+ const createRuntime = async ({ cwd, agentDir, sessionManager, sessionStartEvent, }) => {
54
+ const services = await createAgentSessionServices({
55
+ cwd,
56
+ agentDir,
57
+ authStorage,
58
+ modelRegistry,
59
+ });
60
+ // Get the first model from our registered provider
61
+ const firstModel = modelRegistry.getAll().find((m) => m.provider === "apiario");
62
+ const sessionResult = await createAgentSessionFromServices({
63
+ services,
64
+ sessionManager,
65
+ sessionStartEvent,
66
+ model: firstModel,
67
+ });
68
+ return {
69
+ ...sessionResult,
70
+ services,
71
+ diagnostics: services.diagnostics,
72
+ };
73
+ };
74
+ const cwd = process.cwd();
75
+ const sessionManager = await SessionManager.create(cwd);
76
+ const runtime = await createAgentSessionRuntime(createRuntime, {
77
+ cwd,
78
+ agentDir: AGENT_DIR,
79
+ sessionManager,
80
+ });
81
+ // ── 5. Detect TTY and launch mode ──────────────────────────────────
82
+ const isTTY = process.stdout.isTTY && !process.env.PIPESTART;
83
+ if (isTTY) {
84
+ const interactiveMode = new InteractiveMode(runtime);
85
+ await interactiveMode.init();
86
+ await interactiveMode.run();
87
+ }
88
+ else {
89
+ // Non-TTY (pipe): read from stdin and run print mode
90
+ const stdin = await readStdin();
91
+ const prompt = stdin.trim() || "Explain what this project does in one sentence.";
92
+ console.error("\n 🐝 Apiário Dev — modo não-interativo");
93
+ console.error(" Execute 'npx apiario' sem pipe para entrar no modo interativo (TUI).\n");
94
+ await runPrintMode(runtime, {
95
+ mode: "text",
96
+ initialMessage: prompt,
97
+ });
98
+ }
99
+ }
100
+ // ---------------------------------------------------------------------------
101
+ // Helpers
102
+ // ---------------------------------------------------------------------------
103
+ function readStdin() {
104
+ return new Promise((resolve) => {
105
+ if (process.stdin.isTTY) {
106
+ resolve("");
107
+ return;
108
+ }
109
+ const chunks = [];
110
+ process.stdin.on("data", (chunk) => chunks.push(chunk));
111
+ process.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
112
+ });
113
+ }
114
+ // ---------------------------------------------------------------------------
115
+ // Run
116
+ // ---------------------------------------------------------------------------
117
+ main().catch((err) => {
118
+ console.error("\n ❌ Erro inesperado:", err instanceof Error ? err.message : String(err));
119
+ process.exit(1);
120
+ });
121
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare const API_BASE_URL = "https://api.apiario.dev/v1";
2
+ /**
3
+ * Returns headers that identify the client making the request.
4
+ * Every outbound API call to api.apiario.dev should include these.
5
+ */
6
+ export declare function apiClientHeaders(): Record<string, string>;
7
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,YAAY,+BAA+B,CAAC;AAMzD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKzD"}
package/dist/client.js ADDED
@@ -0,0 +1,27 @@
1
+ import { createRequire } from "module";
2
+ import { resolve, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+ // ---------------------------------------------------------------------------
5
+ // Version (read from package.json at runtime to stay in sync)
6
+ // ---------------------------------------------------------------------------
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const require = createRequire(import.meta.url);
9
+ const { version } = require(resolve(__dirname, "..", "package.json"));
10
+ // ---------------------------------------------------------------------------
11
+ // API base URL
12
+ // ---------------------------------------------------------------------------
13
+ export const API_BASE_URL = "https://api.apiario.dev/v1";
14
+ // ---------------------------------------------------------------------------
15
+ // Client identification headers
16
+ // ---------------------------------------------------------------------------
17
+ /**
18
+ * Returns headers that identify the client making the request.
19
+ * Every outbound API call to api.apiario.dev should include these.
20
+ */
21
+ export function apiClientHeaders() {
22
+ return {
23
+ "x-client": "apiario-harness",
24
+ "x-client-version": version,
25
+ };
26
+ }
27
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,8EAA8E;AAC9E,8DAA8D;AAC9D,8EAA8E;AAE9E,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;AAEtE,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,MAAM,CAAC,MAAM,YAAY,GAAG,4BAA4B,CAAC;AAEzD,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,UAAU,EAAE,iBAAiB;QAC7B,kBAAkB,EAAE,OAAO;KAC5B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ApiarioConfig, ModelsCache } from "./types.js";
2
+ /** XDG-style config directory: ~/.config/apiario */
3
+ export declare const CONFIG_DIR: string;
4
+ /** Path to the settings JSON file. */
5
+ export declare const SETTINGS_PATH: string;
6
+ /** Path to the cached models JSON file. */
7
+ export declare const MODELS_CACHE_PATH: string;
8
+ /** Ensure the config directory exists (mode 0700). */
9
+ export declare function ensureConfigDir(): void;
10
+ /** Load ApiarioConfig from settings.json. Returns null if file doesn't exist or is unparseable. */
11
+ export declare function loadConfig(): ApiarioConfig | null;
12
+ /** Persist ApiarioConfig to settings.json (pretty-printed). */
13
+ export declare function saveConfig(config: ApiarioConfig): void;
14
+ /** Read cached models. Returns null if the file doesn't exist or is invalid. */
15
+ export declare function readModelsCache(): ModelsCache | null;
16
+ /** Write models to the cache file with the current timestamp. */
17
+ export declare function writeModelsCache(models: ModelsCache["models"], fetchedAt?: number): void;
18
+ /** Check whether a cached models payload is still valid (24 h TTL). */
19
+ export declare function isCacheValid(cache: ModelsCache): boolean;
20
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM7D,oDAAoD;AACpD,eAAO,MAAM,UAAU,QAAwC,CAAC;AAEhE,sCAAsC;AACtC,eAAO,MAAM,aAAa,QAAoC,CAAC;AAE/D,2CAA2C;AAC3C,eAAO,MAAM,iBAAiB,QAAkC,CAAC;AAMjE,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAMD,mGAAmG;AACnG,wBAAgB,UAAU,IAAI,aAAa,GAAG,IAAI,CAYjD;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAGtD;AAMD,gFAAgF;AAChF,wBAAgB,eAAe,IAAI,WAAW,GAAG,IAAI,CAQpD;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CAON;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAGxD"}
package/dist/config.js ADDED
@@ -0,0 +1,75 @@
1
+ import { homedir } from "os";
2
+ import { join } from "path";
3
+ import { mkdirSync, existsSync, readFileSync, writeFileSync } from "fs";
4
+ // ---------------------------------------------------------------------------
5
+ // Paths
6
+ // ---------------------------------------------------------------------------
7
+ /** XDG-style config directory: ~/.config/apiario */
8
+ export const CONFIG_DIR = join(homedir(), ".config", "apiario");
9
+ /** Path to the settings JSON file. */
10
+ export const SETTINGS_PATH = join(CONFIG_DIR, "settings.json");
11
+ /** Path to the cached models JSON file. */
12
+ export const MODELS_CACHE_PATH = join(CONFIG_DIR, "models.json");
13
+ // ---------------------------------------------------------------------------
14
+ // Directory helpers
15
+ // ---------------------------------------------------------------------------
16
+ /** Ensure the config directory exists (mode 0700). */
17
+ export function ensureConfigDir() {
18
+ if (!existsSync(CONFIG_DIR)) {
19
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
20
+ }
21
+ }
22
+ // ---------------------------------------------------------------------------
23
+ // Config I/O
24
+ // ---------------------------------------------------------------------------
25
+ /** Load ApiarioConfig from settings.json. Returns null if file doesn't exist or is unparseable. */
26
+ export function loadConfig() {
27
+ try {
28
+ if (!existsSync(SETTINGS_PATH))
29
+ return null;
30
+ const raw = readFileSync(SETTINGS_PATH, "utf-8");
31
+ const parsed = JSON.parse(raw);
32
+ if (typeof parsed.apiKey === "string" && parsed.apiKey.length > 0) {
33
+ return { apiKey: parsed.apiKey };
34
+ }
35
+ return null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ /** Persist ApiarioConfig to settings.json (pretty-printed). */
42
+ export function saveConfig(config) {
43
+ ensureConfigDir();
44
+ writeFileSync(SETTINGS_PATH, JSON.stringify(config, null, 2), "utf-8");
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // Models cache I/O
48
+ // ---------------------------------------------------------------------------
49
+ /** Read cached models. Returns null if the file doesn't exist or is invalid. */
50
+ export function readModelsCache() {
51
+ try {
52
+ if (!existsSync(MODELS_CACHE_PATH))
53
+ return null;
54
+ const raw = readFileSync(MODELS_CACHE_PATH, "utf-8");
55
+ return JSON.parse(raw);
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ /** Write models to the cache file with the current timestamp. */
62
+ export function writeModelsCache(models, fetchedAt) {
63
+ ensureConfigDir();
64
+ const payload = {
65
+ fetchedAt: fetchedAt ?? Date.now(),
66
+ models,
67
+ };
68
+ writeFileSync(MODELS_CACHE_PATH, JSON.stringify(payload, null, 2), "utf-8");
69
+ }
70
+ /** Check whether a cached models payload is still valid (24 h TTL). */
71
+ export function isCacheValid(cache) {
72
+ const TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
73
+ return Date.now() - cache.fetchedAt < TTL_MS;
74
+ }
75
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ModelCard } from "./types.js";
2
+ import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
3
+ /**
4
+ * Fetch available models from GET /v1/models.
5
+ * Returns the raw model cards or throws on error.
6
+ */
7
+ export declare function fetchModels(apiKey: string): Promise<ModelCard[]>;
8
+ /**
9
+ * Get the model list — tries the live API first, falls back to cache.
10
+ * If cache is expired but API is unreachable, uses expired cache with a warning.
11
+ */
12
+ export declare function resolveModels(apiKey: string): Promise<ModelCard[]>;
13
+ /**
14
+ * Map Apiário ModelCard[] into pi.dev ProviderModelConfig[].
15
+ */
16
+ export declare function mapToProviderModelConfigs(cards: ModelCard[]): ProviderModelConfig[];
17
+ /**
18
+ * Sort models by provider priority, then alphabetically by ID within
19
+ * each group.
20
+ */
21
+ export declare function sortModelsByPriority(configs: ProviderModelConfig[]): ProviderModelConfig[];
22
+ /**
23
+ * Register the "apiario" provider in pi.dev with resolved models.
24
+ *
25
+ * @param registerFn - The `pi.registerProvider` function from the SDK.
26
+ * @param apiKey - The resolved API key (literal string).
27
+ * @param models - The sorted, mapped provider model configs.
28
+ */
29
+ export declare function registerApiarioProvider(registerFn: (name: string, config: Record<string, unknown>) => void, apiKey: string, models: ProviderModelConfig[]): void;
30
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAM3E;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,EAAE,CAAC,CAwBtB;AAMD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,EAAE,CAAC,CAuBtB;AAMD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,EAAE,GACjB,mBAAmB,EAAE,CAwBvB;AAaD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,mBAAmB,EAAE,GAC7B,mBAAmB,EAAE,CAYvB;AAMD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,EACnE,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,EAAE,GAC5B,IAAI,CASN"}
@@ -0,0 +1,130 @@
1
+ import { readModelsCache, writeModelsCache, isCacheValid, } from "./config.js";
2
+ import { API_BASE_URL, apiClientHeaders } from "./client.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Model fetching
5
+ // ---------------------------------------------------------------------------
6
+ /**
7
+ * Fetch available models from GET /v1/models.
8
+ * Returns the raw model cards or throws on error.
9
+ */
10
+ export async function fetchModels(apiKey) {
11
+ const res = await fetch(`${API_BASE_URL}/models`, {
12
+ headers: {
13
+ ...apiClientHeaders(),
14
+ Authorization: `Bearer ${apiKey}`,
15
+ Accept: "application/json",
16
+ },
17
+ });
18
+ if (!res.ok) {
19
+ throw new Error(`Falha ao buscar modelos: HTTP ${res.status} ${res.statusText}`);
20
+ }
21
+ const body = await res.json();
22
+ const data = body.data ?? body;
23
+ if (!Array.isArray(data)) {
24
+ throw new Error("Resposta de /v1/models não contém um array 'data'");
25
+ }
26
+ return data;
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Caching
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Get the model list — tries the live API first, falls back to cache.
33
+ * If cache is expired but API is unreachable, uses expired cache with a warning.
34
+ */
35
+ export async function resolveModels(apiKey) {
36
+ // Try live API first
37
+ try {
38
+ const models = await fetchModels(apiKey);
39
+ writeModelsCache(models);
40
+ return models;
41
+ }
42
+ catch (fetchErr) {
43
+ // Fall back to cache (even if expired)
44
+ const cached = readModelsCache();
45
+ if (cached && cached.models.length > 0) {
46
+ if (!isCacheValid(cached)) {
47
+ console.warn(" ⚠️ API indisponível. Usando lista de modelos em cache (desde " +
48
+ new Date(cached.fetchedAt).toLocaleString("pt-BR") +
49
+ ").");
50
+ }
51
+ return cached.models;
52
+ }
53
+ // No cache available — rethrow the original error
54
+ throw fetchErr;
55
+ }
56
+ }
57
+ // ---------------------------------------------------------------------------
58
+ // Model mapping
59
+ // ---------------------------------------------------------------------------
60
+ /**
61
+ * Map Apiário ModelCard[] into pi.dev ProviderModelConfig[].
62
+ */
63
+ export function mapToProviderModelConfigs(cards) {
64
+ return cards.map((card) => {
65
+ const inputTypes = card.capabilities.includes("vision")
66
+ ? ["text", "image"]
67
+ : ["text"];
68
+ return {
69
+ id: card.id,
70
+ name: card.name,
71
+ api: "openai-completions",
72
+ reasoning: card.capabilities.includes("reasoning"),
73
+ input: inputTypes,
74
+ cost: {
75
+ input: parseFloat(card.input_price_brl_per_1m) || 0,
76
+ output: parseFloat(card.output_price_brl_per_1m) || 0,
77
+ cacheRead: 0,
78
+ cacheWrite: 0,
79
+ },
80
+ contextWindow: card.context_window,
81
+ maxTokens: Math.min(card.context_window, 128000),
82
+ };
83
+ });
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // Model sorting
87
+ // ---------------------------------------------------------------------------
88
+ /** Priority groups for model providers. Lower number = higher priority. */
89
+ const PROVIDER_PRIORITY = {
90
+ DeepSeek: 0,
91
+ OpenAI: 1,
92
+ Anthropic: 2,
93
+ };
94
+ /**
95
+ * Sort models by provider priority, then alphabetically by ID within
96
+ * each group.
97
+ */
98
+ export function sortModelsByPriority(configs) {
99
+ return [...configs].sort((a, b) => {
100
+ // Extract provider name from model ID (format: "provider/model-name")
101
+ const providerA = a.id.split("/")[0] ?? "";
102
+ const providerB = b.id.split("/")[0] ?? "";
103
+ const priA = PROVIDER_PRIORITY[providerA] ?? 99;
104
+ const priB = PROVIDER_PRIORITY[providerB] ?? 99;
105
+ if (priA !== priB)
106
+ return priA - priB;
107
+ return a.id.localeCompare(b.id);
108
+ });
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Provider registration
112
+ // ---------------------------------------------------------------------------
113
+ /**
114
+ * Register the "apiario" provider in pi.dev with resolved models.
115
+ *
116
+ * @param registerFn - The `pi.registerProvider` function from the SDK.
117
+ * @param apiKey - The resolved API key (literal string).
118
+ * @param models - The sorted, mapped provider model configs.
119
+ */
120
+ export function registerApiarioProvider(registerFn, apiKey, models) {
121
+ registerFn("apiario", {
122
+ name: "Apiário Dev",
123
+ baseUrl: API_BASE_URL,
124
+ apiKey,
125
+ api: "openai-completions",
126
+ authHeader: true,
127
+ models,
128
+ });
129
+ }
130
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Types for the Apiário Dev CLI Harness.
3
+ *
4
+ * Mirrors the /v1/models response shape and pi.dev Model shape
5
+ * as described in DESIGN.md (Model card mapping).
6
+ */
7
+ /** Stored configuration for the harness. */
8
+ export interface ApiarioConfig {
9
+ /** The user's API key (sk-...). */
10
+ apiKey: string;
11
+ }
12
+ /** A single model card as returned by GET /v1/models. */
13
+ export interface ModelCard {
14
+ id: string;
15
+ name: string;
16
+ provider: string;
17
+ capabilities: string[];
18
+ context_window: number;
19
+ input_price_brl_per_1m: string;
20
+ output_price_brl_per_1m: string;
21
+ created: number;
22
+ }
23
+ /** Top-level response from GET /v1/models. */
24
+ export interface ModelListResponse {
25
+ object: string;
26
+ data: ModelCard[];
27
+ }
28
+ /** Cached models payload with timestamp for TTL checks. */
29
+ export interface ModelsCache {
30
+ fetchedAt: number;
31
+ models: ModelCard[];
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Types for the Apiário Dev CLI Harness.
3
+ *
4
+ * Mirrors the /v1/models response shape and pi.dev Model shape
5
+ * as described in DESIGN.md (Model card mapping).
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "apiario",
3
+ "version": "0.1.0",
4
+ "description": "CLI Harness — pi.dev TUI wrapper for Apiário Dev API",
5
+ "type": "module",
6
+ "bin": {
7
+ "apiario": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "prepublishOnly": "npm run build",
12
+ "dev": "tsc --watch"
13
+ },
14
+ "dependencies": {
15
+ "@earendil-works/pi-coding-agent": "0.74.0",
16
+ "@earendil-works/pi-ai": "0.74.0",
17
+ "typebox": "1.1.38"
18
+ },
19
+ "devDependencies": {
20
+ "typescript": "^5.7.0"
21
+ },
22
+ "engines": {
23
+ "node": ">=20.6.0"
24
+ },
25
+ "files": ["dist"]
26
+ }