@alfe.ai/config 0.0.1

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,34 @@
1
+ # packages/config (`@alfe.ai/config`)
2
+
3
+ **Config** — read/write `~/.alfe/config.toml` for Alfe CLI and gateway.
4
+
5
+ ## What It Does
6
+
7
+ Shared config management for the Alfe user-side tools (CLI, gateway daemon, plugins). Reads and writes the user's local config file at `~/.alfe/config.toml`.
8
+
9
+ - **`readConfig()`** — read and parse `~/.alfe/config.toml`
10
+ - **`writeConfig(config)`** — write config to `~/.alfe/config.toml`
11
+ - **`configExists()`** — check if config file exists
12
+ - **`getApiEndpoint()`** — resolve API URL from config or token prefix
13
+ - **`getEndpointFromToken(token)`** — derive API endpoint from token prefix (`alfe_dev_`, `alfe_test_`, `alfe_live_`)
14
+
15
+ ## Config Format
16
+
17
+ ```toml
18
+ # ~/.alfe/config.toml
19
+ api_key = "alfe_live_xxxx..."
20
+ gateway = "https://api.alfe.ai" # optional override
21
+ ```
22
+
23
+ The API endpoint is derived automatically from the token prefix unless `gateway` is explicitly set.
24
+
25
+ ## Development
26
+
27
+ ```bash
28
+ pnpm install
29
+ pnpm --filter @alfe.ai/config build
30
+ ```
31
+
32
+ ## Dependencies
33
+
34
+ - **smol-toml** — TOML parsing and serialization
@@ -0,0 +1,47 @@
1
+ //#region src/index.d.ts
2
+ /**
3
+ * @alfe.ai/config — read/write ~/.alfe/config.toml
4
+ *
5
+ * Shared across CLI, gateway, and other services so all can
6
+ * resolve the user's API key without circular dependencies.
7
+ */
8
+ interface AlfeConfig {
9
+ api_key: string;
10
+ gateway?: string;
11
+ gateway_url?: string;
12
+ }
13
+ /**
14
+ * Derive the API endpoint URL from a token's prefix.
15
+ * Throws if the token doesn't match any known prefix.
16
+ */
17
+ declare function getEndpointFromToken(token: string): string;
18
+ /**
19
+ * Derive the ai-proxy URL from a token's prefix.
20
+ * Used by the local ai-proxy to know where to forward requests.
21
+ */
22
+ declare function getAiProxyUrlFromToken(token: string): string;
23
+ /**
24
+ * Check if ~/.alfe/config.toml exists.
25
+ */
26
+ declare function configExists(): boolean;
27
+ /**
28
+ * Read the Alfe config from ~/.alfe/config.toml.
29
+ * Throws if the file doesn't exist or is malformed.
30
+ */
31
+ declare function readConfig(): Promise<AlfeConfig>;
32
+ /**
33
+ * Write the Alfe config to ~/.alfe/config.toml.
34
+ * Creates the ~/.alfe directory if it doesn't exist.
35
+ */
36
+ declare function writeConfig(config: AlfeConfig): Promise<void>;
37
+ /**
38
+ * Add or update a [runtimes.<name>] section in ~/.alfe/config.toml.
39
+ * Preserves existing config values and only merges the runtime section.
40
+ */
41
+ declare function writeRuntimeConfig(name: string, runtimeConfig: {
42
+ workspace: string;
43
+ }): Promise<void>;
44
+ //# sourceMappingURL=index.d.ts.map
45
+ //#endregion
46
+ export { AlfeConfig, configExists, getAiProxyUrlFromToken, getEndpointFromToken, readConfig, writeConfig, writeRuntimeConfig };
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;AAaA;AA2BA;AAaA;AAYA;AAQA;AAAgC,UA5Df,UAAA,CA4De;SAAY,EAAA,MAAA;SAAR,CAAA,EAAA,MAAA;EAAO,WAAA,CAAA,EAAA,MAAA;AA2B3C;;;;;AAmBsB,iBA/EN,oBAAA,CAkFN,KAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;;iBArEM,sBAAA;;;;iBAYA,YAAA,CAAA;;;;;iBAQM,UAAA,CAAA,GAAc,QAAQ;;;;;iBA2BtB,WAAA,SAAoB,aAAa;;;;;iBAmBjC,kBAAA;;IAGnB"}
package/dist/index.js ADDED
@@ -0,0 +1,87 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ import { parse, stringify } from "smol-toml";
6
+ //#region src/index.ts
7
+ /**
8
+ * @alfe.ai/config — read/write ~/.alfe/config.toml
9
+ *
10
+ * Shared across CLI, gateway, and other services so all can
11
+ * resolve the user's API key without circular dependencies.
12
+ */
13
+ const ALFE_DIR = join(homedir(), ".alfe");
14
+ const CONFIG_PATH = join(ALFE_DIR, "config.toml");
15
+ const TOKEN_PREFIX_MAP = {
16
+ "alfe_dev_": "https://api.dev.alfe.ai",
17
+ "alfe_test_": "https://api.test.alfe.ai",
18
+ "alfe_live_": "https://api.alfe.ai"
19
+ };
20
+ const AI_PROXY_PREFIX_MAP = {
21
+ "alfe_dev_": "https://ai.dev.alfe.ai",
22
+ "alfe_test_": "https://ai.test.alfe.ai",
23
+ "alfe_live_": "https://ai.alfe.ai"
24
+ };
25
+ /**
26
+ * Derive the API endpoint URL from a token's prefix.
27
+ * Throws if the token doesn't match any known prefix.
28
+ */
29
+ function getEndpointFromToken(token) {
30
+ for (const [prefix, url] of Object.entries(TOKEN_PREFIX_MAP)) if (token.startsWith(prefix)) return url;
31
+ throw new Error(`Unknown token prefix — expected alfe_dev_, alfe_test_, or alfe_live_`);
32
+ }
33
+ /**
34
+ * Derive the ai-proxy URL from a token's prefix.
35
+ * Used by the local ai-proxy to know where to forward requests.
36
+ */
37
+ function getAiProxyUrlFromToken(token) {
38
+ for (const [prefix, url] of Object.entries(AI_PROXY_PREFIX_MAP)) if (token.startsWith(prefix)) return url;
39
+ throw new Error(`Unknown token prefix — expected alfe_dev_, alfe_test_, or alfe_live_`);
40
+ }
41
+ /**
42
+ * Check if ~/.alfe/config.toml exists.
43
+ */
44
+ function configExists() {
45
+ return existsSync(CONFIG_PATH);
46
+ }
47
+ /**
48
+ * Read the Alfe config from ~/.alfe/config.toml.
49
+ * Throws if the file doesn't exist or is malformed.
50
+ */
51
+ async function readConfig() {
52
+ if (!configExists()) throw new Error("Config not found. Run `alfe login` to set up your API key.");
53
+ const parsed = parse(await readFile(CONFIG_PATH, "utf-8"));
54
+ if (typeof parsed.api_key !== "string" || !parsed.api_key) throw new Error("Invalid config: missing api_key. Run `alfe login` to reconfigure.");
55
+ return {
56
+ api_key: parsed.api_key,
57
+ gateway: parsed.gateway,
58
+ gateway_url: parsed.gateway_url
59
+ };
60
+ }
61
+ /**
62
+ * Write the Alfe config to ~/.alfe/config.toml.
63
+ * Creates the ~/.alfe directory if it doesn't exist.
64
+ */
65
+ async function writeConfig(config) {
66
+ await mkdir(ALFE_DIR, { recursive: true });
67
+ const data = { api_key: config.api_key };
68
+ if (config.gateway) data.gateway = config.gateway;
69
+ await writeFile(CONFIG_PATH, stringify(data) + "\n", "utf-8");
70
+ }
71
+ /**
72
+ * Add or update a [runtimes.<name>] section in ~/.alfe/config.toml.
73
+ * Preserves existing config values and only merges the runtime section.
74
+ */
75
+ async function writeRuntimeConfig(name, runtimeConfig) {
76
+ await mkdir(ALFE_DIR, { recursive: true });
77
+ let existing = {};
78
+ if (existsSync(CONFIG_PATH)) existing = parse(await readFile(CONFIG_PATH, "utf-8"));
79
+ const runtimes = existing.runtimes ?? {};
80
+ runtimes[name] = { workspace: runtimeConfig.workspace };
81
+ existing.runtimes = runtimes;
82
+ await writeFile(CONFIG_PATH, stringify(existing) + "\n", "utf-8");
83
+ }
84
+ //#endregion
85
+ export { configExists, getAiProxyUrlFromToken, getEndpointFromToken, readConfig, writeConfig, writeRuntimeConfig };
86
+
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @alfe.ai/config — read/write ~/.alfe/config.toml\n *\n * Shared across CLI, gateway, and other services so all can\n * resolve the user's API key without circular dependencies.\n */\n\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { parse, stringify } from \"smol-toml\";\n\nexport interface AlfeConfig {\n api_key: string;\n gateway?: string;\n gateway_url?: string;\n}\n\nconst ALFE_DIR = join(homedir(), \".alfe\");\nconst CONFIG_PATH = join(ALFE_DIR, \"config.toml\");\n\n// ── Token-based endpoint derivation ─────────────────────────\n\nconst TOKEN_PREFIX_MAP: Record<string, string> = {\n 'alfe_dev_': 'https://api.dev.alfe.ai',\n 'alfe_test_': 'https://api.test.alfe.ai',\n 'alfe_live_': 'https://api.alfe.ai',\n};\n\nconst AI_PROXY_PREFIX_MAP: Record<string, string> = {\n 'alfe_dev_': 'https://ai.dev.alfe.ai',\n 'alfe_test_': 'https://ai.test.alfe.ai',\n 'alfe_live_': 'https://ai.alfe.ai',\n};\n\n/**\n * Derive the API endpoint URL from a token's prefix.\n * Throws if the token doesn't match any known prefix.\n */\nexport function getEndpointFromToken(token: string): string {\n for (const [prefix, url] of Object.entries(TOKEN_PREFIX_MAP)) {\n if (token.startsWith(prefix)) return url;\n }\n throw new Error(\n `Unknown token prefix — expected alfe_dev_, alfe_test_, or alfe_live_`,\n );\n}\n\n/**\n * Derive the ai-proxy URL from a token's prefix.\n * Used by the local ai-proxy to know where to forward requests.\n */\nexport function getAiProxyUrlFromToken(token: string): string {\n for (const [prefix, url] of Object.entries(AI_PROXY_PREFIX_MAP)) {\n if (token.startsWith(prefix)) return url;\n }\n throw new Error(\n `Unknown token prefix — expected alfe_dev_, alfe_test_, or alfe_live_`,\n );\n}\n\n/**\n * Check if ~/.alfe/config.toml exists.\n */\nexport function configExists(): boolean {\n return existsSync(CONFIG_PATH);\n}\n\n/**\n * Read the Alfe config from ~/.alfe/config.toml.\n * Throws if the file doesn't exist or is malformed.\n */\nexport async function readConfig(): Promise<AlfeConfig> {\n if (!configExists()) {\n throw new Error(\n \"Config not found. Run `alfe login` to set up your API key.\",\n );\n }\n\n const raw = await readFile(CONFIG_PATH, \"utf-8\");\n const parsed = parse(raw);\n\n if (typeof parsed.api_key !== \"string\" || !parsed.api_key) {\n throw new Error(\n \"Invalid config: missing api_key. Run `alfe login` to reconfigure.\",\n );\n }\n\n return {\n api_key: parsed.api_key,\n gateway: parsed.gateway as string | undefined,\n gateway_url: parsed.gateway_url as string | undefined,\n };\n}\n\n/**\n * Write the Alfe config to ~/.alfe/config.toml.\n * Creates the ~/.alfe directory if it doesn't exist.\n */\nexport async function writeConfig(config: AlfeConfig): Promise<void> {\n await mkdir(ALFE_DIR, { recursive: true });\n\n const data: Record<string, string> = {\n api_key: config.api_key,\n };\n\n if (config.gateway) {\n data.gateway = config.gateway;\n }\n\n const toml = stringify(data);\n await writeFile(CONFIG_PATH, toml + \"\\n\", \"utf-8\");\n}\n\n/**\n * Add or update a [runtimes.<name>] section in ~/.alfe/config.toml.\n * Preserves existing config values and only merges the runtime section.\n */\nexport async function writeRuntimeConfig(\n name: string,\n runtimeConfig: { workspace: string },\n): Promise<void> {\n await mkdir(ALFE_DIR, { recursive: true });\n\n let existing: Record<string, unknown> = {};\n if (existsSync(CONFIG_PATH)) {\n const raw = await readFile(CONFIG_PATH, \"utf-8\");\n existing = parse(raw) as Record<string, unknown>;\n }\n\n const runtimes = (existing.runtimes ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n runtimes[name] = { workspace: runtimeConfig.workspace };\n existing.runtimes = runtimes;\n\n const toml = stringify(existing);\n await writeFile(CONFIG_PATH, toml + \"\\n\", \"utf-8\");\n}\n"],"mappings":";;;;;;;;;;;;AAmBA,MAAM,WAAW,KAAK,SAAS,EAAE,QAAQ;AACzC,MAAM,cAAc,KAAK,UAAU,cAAc;AAIjD,MAAM,mBAA2C;CAC/C,aAAc;CACd,cAAc;CACd,cAAc;CACf;AAED,MAAM,sBAA8C;CAClD,aAAc;CACd,cAAc;CACd,cAAc;CACf;;;;;AAMD,SAAgB,qBAAqB,OAAuB;AAC1D,MAAK,MAAM,CAAC,QAAQ,QAAQ,OAAO,QAAQ,iBAAiB,CAC1D,KAAI,MAAM,WAAW,OAAO,CAAE,QAAO;AAEvC,OAAM,IAAI,MACR,uEACD;;;;;;AAOH,SAAgB,uBAAuB,OAAuB;AAC5D,MAAK,MAAM,CAAC,QAAQ,QAAQ,OAAO,QAAQ,oBAAoB,CAC7D,KAAI,MAAM,WAAW,OAAO,CAAE,QAAO;AAEvC,OAAM,IAAI,MACR,uEACD;;;;;AAMH,SAAgB,eAAwB;AACtC,QAAO,WAAW,YAAY;;;;;;AAOhC,eAAsB,aAAkC;AACtD,KAAI,CAAC,cAAc,CACjB,OAAM,IAAI,MACR,6DACD;CAIH,MAAM,SAAS,MADH,MAAM,SAAS,aAAa,QAAQ,CACvB;AAEzB,KAAI,OAAO,OAAO,YAAY,YAAY,CAAC,OAAO,QAChD,OAAM,IAAI,MACR,oEACD;AAGH,QAAO;EACL,SAAS,OAAO;EAChB,SAAS,OAAO;EAChB,aAAa,OAAO;EACrB;;;;;;AAOH,eAAsB,YAAY,QAAmC;AACnE,OAAM,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;CAE1C,MAAM,OAA+B,EACnC,SAAS,OAAO,SACjB;AAED,KAAI,OAAO,QACT,MAAK,UAAU,OAAO;AAIxB,OAAM,UAAU,aADH,UAAU,KAAK,GACQ,MAAM,QAAQ;;;;;;AAOpD,eAAsB,mBACpB,MACA,eACe;AACf,OAAM,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;CAE1C,IAAI,WAAoC,EAAE;AAC1C,KAAI,WAAW,YAAY,CAEzB,YAAW,MADC,MAAM,SAAS,aAAa,QAAQ,CAC3B;CAGvB,MAAM,WAAY,SAAS,YAAY,EAAE;AAIzC,UAAS,QAAQ,EAAE,WAAW,cAAc,WAAW;AACvD,UAAS,WAAW;AAGpB,OAAM,UAAU,aADH,UAAU,SAAS,GACI,MAAM,QAAQ"}
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@alfe.ai/config",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "smol-toml": "^1.3.0"
18
+ },
19
+ "scripts": {
20
+ "build": "tsdown",
21
+ "dev": "tsdown --watch",
22
+ "typecheck": "tsc --noEmit",
23
+ "lint": "eslint ."
24
+ }
25
+ }