wolbarg 0.5.4 → 0.5.6
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/CHANGELOG.md +30 -0
- package/README.md +31 -1
- package/dist/cli.js +515 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +955 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2109 -138
- package/dist/index.d.ts +2109 -138
- package/dist/index.js +940 -30
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to this project are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [0.5.6] — 2026-07-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`wolbarg` CLI** with `wolbarg init` — interactive (or `--yes`) project setup for database + embedding provider
|
|
13
|
+
- Default SQLite path: `.wolbarg/shared-memory/memory.db`
|
|
14
|
+
- Provider presets (OpenAI, Ollama, OpenRouter, LM Studio, Gemini, Together, vLLM, custom) with **visible default base URLs** the user can edit
|
|
15
|
+
- Writes `.wolbarg/config.json` and optional `.wolbarg/.env` (API key); adds `.env` paths to `.gitignore`
|
|
16
|
+
- **`createWolbargFromProjectConfig()`** / `loadProjectConfig()` to boot the SDK from init output
|
|
17
|
+
|
|
18
|
+
### Compatibility
|
|
19
|
+
|
|
20
|
+
- Additive. Existing programmatic `wolbarg({...})` usage unchanged.
|
|
21
|
+
|
|
22
|
+
## [0.5.5] — 2026-07-21
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Comprehensive JSDoc** across the SDK and official adapter packages — every exported function, method, class, interface, and notable helper now has descriptions with `@param` / `@returns` / `@example` where useful for IDE hover documentation
|
|
27
|
+
- Provider interface docs explain how to implement custom storage, telemetry, checkpoint, graph, OCR, vision, rerank, and keyword backends
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- **`SDK_VERSION`** and package version bumped to **0.5.5**
|
|
32
|
+
- Adapter packages peer-depend on `wolbarg >= 0.5.5`
|
|
33
|
+
|
|
34
|
+
### Compatibility
|
|
35
|
+
|
|
36
|
+
- Documentation-only release. No runtime API or schema changes from **0.5.4**.
|
|
37
|
+
|
|
8
38
|
## [0.5.3] — 2026-07-20
|
|
9
39
|
|
|
10
40
|
### Added
|
package/README.md
CHANGED
|
@@ -15,9 +15,39 @@
|
|
|
15
15
|
npm install wolbarg
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
### Configure with the CLI (recommended)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx wolbarg init
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
You will be prompted (all optional — Enter accepts defaults):
|
|
25
|
+
|
|
26
|
+
1. **Database** — default `.wolbarg/shared-memory/memory.db` (or a Postgres URL)
|
|
27
|
+
2. **Embedding provider** — OpenAI, Ollama, OpenRouter, LM Studio, Gemini, Together, vLLM, or custom
|
|
28
|
+
3. **Base URL** — always shown with that provider’s default (edit or keep)
|
|
29
|
+
4. **Model** — provider default pre-filled
|
|
30
|
+
5. **API key** — written to `.wolbarg/.env` (not into config JSON)
|
|
31
|
+
|
|
32
|
+
Non-interactive:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx wolbarg init --yes --provider openai --api-key "$OPENAI_API_KEY"
|
|
36
|
+
npx wolbarg init --yes --skip-embedding
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then in code:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { createWolbargFromProjectConfig } from "wolbarg";
|
|
43
|
+
|
|
44
|
+
const ctx = createWolbargFromProjectConfig();
|
|
45
|
+
await ctx.ready();
|
|
46
|
+
```
|
|
47
|
+
|
|
18
48
|
Wolbarg is **memory infrastructure**, not an agent framework. Agents call `remember()` / `recall()` (and optionally ingest, compress, subscribe, and link memories in a graph). You bring SQLite or PostgreSQL, any OpenAI-compatible embedding API, and optional peers for PDF/DOCX/OCR/Neo4j.
|
|
19
49
|
|
|
20
|
-
**Current release: [v0.5.
|
|
50
|
+
**Current release: [v0.5.6](./CHANGELOG.md)** — `wolbarg init` CLI + project config loader. Still includes official framework adapters (`@wolbarg/openai`, `@wolbarg/langchain`, `@wolbarg/llamaindex`, `@wolbarg/mastra`, `@wolbarg/vercel-ai`), experimental `rememberFromMessages()`, 0.5 graph memory (SQLite + Neo4j), `includeGraph` recall, and [Wolbarg Studio](https://wolbarg.com/docs/observability).
|
|
21
51
|
|
|
22
52
|
---
|
|
23
53
|
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
|
|
3
|
+
import { isAbsolute, resolve, dirname, join } from "node:path";
|
|
4
|
+
import * as readline from "node:readline/promises";
|
|
5
|
+
import { stdout, stdin } from 'process';
|
|
6
|
+
|
|
7
|
+
// src/version.ts
|
|
8
|
+
var SDK_VERSION = "0.5.6";
|
|
9
|
+
|
|
10
|
+
// src/config/providers.ts
|
|
11
|
+
var EMBEDDING_PROVIDER_PRESETS = [
|
|
12
|
+
{
|
|
13
|
+
id: "openai",
|
|
14
|
+
label: "OpenAI",
|
|
15
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
16
|
+
defaultModel: "text-embedding-3-small",
|
|
17
|
+
apiKeyEnv: "OPENAI_API_KEY"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "ollama",
|
|
21
|
+
label: "Ollama (local)",
|
|
22
|
+
defaultBaseUrl: "http://127.0.0.1:11434/v1",
|
|
23
|
+
defaultModel: "nomic-embed-text",
|
|
24
|
+
apiKeyEnv: "OLLAMA_API_KEY",
|
|
25
|
+
apiKeyHint: "Any non-empty value works locally (e.g. ollama)"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "openrouter",
|
|
29
|
+
label: "OpenRouter",
|
|
30
|
+
defaultBaseUrl: "https://openrouter.ai/api/v1",
|
|
31
|
+
defaultModel: "openai/text-embedding-3-small",
|
|
32
|
+
apiKeyEnv: "OPENROUTER_API_KEY"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "lmstudio",
|
|
36
|
+
label: "LM Studio (local)",
|
|
37
|
+
defaultBaseUrl: "http://127.0.0.1:1234/v1",
|
|
38
|
+
defaultModel: "text-embedding-nomic-embed-text-v1.5",
|
|
39
|
+
apiKeyEnv: "LM_STUDIO_API_KEY",
|
|
40
|
+
apiKeyHint: "Often unused locally \u2014 any non-empty value is fine"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "gemini",
|
|
44
|
+
label: "Google Gemini",
|
|
45
|
+
defaultBaseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
46
|
+
defaultModel: "text-embedding-004",
|
|
47
|
+
apiKeyEnv: "GEMINI_API_KEY"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "together",
|
|
51
|
+
label: "Together AI",
|
|
52
|
+
defaultBaseUrl: "https://api.together.xyz/v1",
|
|
53
|
+
defaultModel: "togethercomputer/m2-bert-80M-8k-retrieval",
|
|
54
|
+
apiKeyEnv: "TOGETHER_API_KEY"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "vllm",
|
|
58
|
+
label: "vLLM (local/server)",
|
|
59
|
+
defaultBaseUrl: "http://127.0.0.1:8000/v1",
|
|
60
|
+
defaultModel: "text-embedding-ada-002",
|
|
61
|
+
apiKeyEnv: "VLLM_API_KEY",
|
|
62
|
+
apiKeyHint: "Only if your server requires auth"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "custom",
|
|
66
|
+
label: "Custom OpenAI-compatible",
|
|
67
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
68
|
+
defaultModel: "text-embedding-3-small",
|
|
69
|
+
apiKeyEnv: "WOLBARG_EMBEDDING_API_KEY"
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
function getEmbeddingProviderPreset(id) {
|
|
73
|
+
return EMBEDDING_PROVIDER_PRESETS.find((p) => p.id === id);
|
|
74
|
+
}
|
|
75
|
+
var DEFAULT_SQLITE_DB_PATH = ".wolbarg/shared-memory/memory.db";
|
|
76
|
+
var DEFAULT_ORGANIZATION = "default";
|
|
77
|
+
var DEFAULT_CONFIG_PATH = ".wolbarg/config.json";
|
|
78
|
+
var DEFAULT_ENV_PATH = ".wolbarg/.env";
|
|
79
|
+
|
|
80
|
+
// src/config/project-config.ts
|
|
81
|
+
function defaultProjectConfig() {
|
|
82
|
+
return {
|
|
83
|
+
version: 1,
|
|
84
|
+
organization: DEFAULT_ORGANIZATION,
|
|
85
|
+
database: {
|
|
86
|
+
provider: "sqlite",
|
|
87
|
+
url: DEFAULT_SQLITE_DB_PATH
|
|
88
|
+
},
|
|
89
|
+
paths: {
|
|
90
|
+
config: DEFAULT_CONFIG_PATH
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function resolveConfigPath(cwd = process.cwd(), configPath) {
|
|
95
|
+
const rel = configPath ?? DEFAULT_CONFIG_PATH;
|
|
96
|
+
return isAbsolute(rel) ? rel : resolve(cwd, rel);
|
|
97
|
+
}
|
|
98
|
+
function resolveEnvPath(cwd = process.cwd(), envPath) {
|
|
99
|
+
const rel = envPath ?? DEFAULT_ENV_PATH;
|
|
100
|
+
return isAbsolute(rel) ? rel : resolve(cwd, rel);
|
|
101
|
+
}
|
|
102
|
+
function saveProjectConfig(config, options = {}) {
|
|
103
|
+
const cwd = options.cwd ?? process.cwd();
|
|
104
|
+
const configPath = resolveConfigPath(cwd, options.configPath);
|
|
105
|
+
const dir = dirname(configPath);
|
|
106
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
107
|
+
if (existsSync(configPath) && options.overwrite === false) {
|
|
108
|
+
throw new Error(`Config already exists: ${configPath} (pass --force to overwrite)`);
|
|
109
|
+
}
|
|
110
|
+
const toWrite = {
|
|
111
|
+
...config,
|
|
112
|
+
paths: {
|
|
113
|
+
config: options.configPath ?? DEFAULT_CONFIG_PATH,
|
|
114
|
+
...options.envPath || options.apiKey ? { env: options.envPath ?? DEFAULT_ENV_PATH } : config.paths?.env ? { env: config.paths.env } : {}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
writeFileSync(configPath, `${JSON.stringify(toWrite, null, 2)}
|
|
118
|
+
`, "utf8");
|
|
119
|
+
let envPath;
|
|
120
|
+
if (options.apiKey && config.embedding?.apiKeyEnv) {
|
|
121
|
+
envPath = resolveEnvPath(cwd, options.envPath);
|
|
122
|
+
ensureParent(envPath);
|
|
123
|
+
upsertEnvVar(envPath, config.embedding.apiKeyEnv, options.apiKey);
|
|
124
|
+
ensureGitignore(cwd, [DEFAULT_ENV_PATH, ".env"]);
|
|
125
|
+
}
|
|
126
|
+
if (config.database.provider === "sqlite" && !config.database.url.includes("://")) {
|
|
127
|
+
const dbPath = isAbsolute(config.database.url) ? config.database.url : resolve(cwd, config.database.url);
|
|
128
|
+
ensureParent(dbPath);
|
|
129
|
+
}
|
|
130
|
+
return { configPath, envPath };
|
|
131
|
+
}
|
|
132
|
+
function ensureParent(filePath) {
|
|
133
|
+
const dir = dirname(filePath);
|
|
134
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
function upsertEnvVar(envPath, key, value) {
|
|
137
|
+
ensureParent(envPath);
|
|
138
|
+
let text = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
|
|
139
|
+
const line = `${key}=${shellQuoteEnv(value)}`;
|
|
140
|
+
const re = new RegExp(`^${escapeRegExp(key)}=.*$`, "m");
|
|
141
|
+
if (re.test(text)) {
|
|
142
|
+
text = text.replace(re, line);
|
|
143
|
+
} else {
|
|
144
|
+
if (text && !text.endsWith("\n")) text += "\n";
|
|
145
|
+
text += `${line}
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
writeFileSync(envPath, text, "utf8");
|
|
149
|
+
}
|
|
150
|
+
function shellQuoteEnv(value) {
|
|
151
|
+
if (/[\s#"']/.test(value)) {
|
|
152
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
function escapeRegExp(s) {
|
|
157
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
158
|
+
}
|
|
159
|
+
function ensureGitignore(cwd, entries) {
|
|
160
|
+
const gi = join(cwd, ".gitignore");
|
|
161
|
+
let text = existsSync(gi) ? readFileSync(gi, "utf8") : "";
|
|
162
|
+
let changed = false;
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (text.split(/\r?\n/).some((l) => l.trim() === entry)) continue;
|
|
165
|
+
if (text && !text.endsWith("\n")) text += "\n";
|
|
166
|
+
text += `${entry}
|
|
167
|
+
`;
|
|
168
|
+
changed = true;
|
|
169
|
+
}
|
|
170
|
+
if (changed) writeFileSync(gi, text, "utf8");
|
|
171
|
+
}
|
|
172
|
+
async function withReadline(fn) {
|
|
173
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
174
|
+
try {
|
|
175
|
+
return await fn(rl);
|
|
176
|
+
} finally {
|
|
177
|
+
rl.close();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function askText(rl, label, defaultValue2) {
|
|
181
|
+
const hint = defaultValue2 !== void 0 && defaultValue2 !== "" ? ` [${defaultValue2}]` : "";
|
|
182
|
+
const answer = (await rl.question(`${label}${hint}: `)).trim();
|
|
183
|
+
if (answer === "") return defaultValue2 ?? "";
|
|
184
|
+
return answer;
|
|
185
|
+
}
|
|
186
|
+
async function askOptionalText(rl, label, defaultValue2) {
|
|
187
|
+
const hintParts = [];
|
|
188
|
+
if (defaultValue2 !== void 0 && defaultValue2 !== "") {
|
|
189
|
+
hintParts.push(`default: ${defaultValue2}`);
|
|
190
|
+
}
|
|
191
|
+
hintParts.push("Enter to accept", '"-" to skip/clear');
|
|
192
|
+
const answer = (await rl.question(`${label} (${hintParts.join(", ")}): `)).trim();
|
|
193
|
+
if (answer === "-") return void 0;
|
|
194
|
+
if (answer === "") {
|
|
195
|
+
return defaultValue2 === "" ? void 0 : defaultValue2;
|
|
196
|
+
}
|
|
197
|
+
return answer;
|
|
198
|
+
}
|
|
199
|
+
async function askSelect(rl, label, choices, defaultValue2, allowSkip = true) {
|
|
200
|
+
console.log(`
|
|
201
|
+
${label}`);
|
|
202
|
+
choices.forEach((c, i) => {
|
|
203
|
+
const mark = c.value === defaultValue2 ? " (default)" : "";
|
|
204
|
+
console.log(` ${i + 1}) ${c.label}${mark}`);
|
|
205
|
+
});
|
|
206
|
+
if (allowSkip) {
|
|
207
|
+
console.log(` 0) Skip`);
|
|
208
|
+
}
|
|
209
|
+
const defIndex = choices.findIndex((c) => c.value === defaultValue2) + 1 ;
|
|
210
|
+
const raw = (await rl.question(
|
|
211
|
+
`Choose [0-${choices.length}]${defIndex >= 0 ? ` (default ${defIndex})` : ""}: `
|
|
212
|
+
)).trim();
|
|
213
|
+
if (raw === "" && defIndex === 0 && allowSkip) return void 0;
|
|
214
|
+
if (raw === "" && defIndex > 0) return choices[defIndex - 1].value;
|
|
215
|
+
if (raw === "0" && allowSkip) return void 0;
|
|
216
|
+
const n = Number(raw);
|
|
217
|
+
if (!Number.isInteger(n) || n < 1 || n > choices.length) {
|
|
218
|
+
console.log("Invalid choice \u2014 skipped.");
|
|
219
|
+
return allowSkip ? void 0 : defaultValue2;
|
|
220
|
+
}
|
|
221
|
+
return choices[n - 1].value;
|
|
222
|
+
}
|
|
223
|
+
async function askConfirm(rl, label, defaultYes = true) {
|
|
224
|
+
const hint = defaultValue ? "Y/n" : "y/N";
|
|
225
|
+
const answer = (await rl.question(`${label} (${hint}): `)).trim().toLowerCase();
|
|
226
|
+
if (answer === "") return defaultValue;
|
|
227
|
+
if (answer === "y" || answer === "yes") return true;
|
|
228
|
+
if (answer === "n" || answer === "no") return false;
|
|
229
|
+
return defaultValue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/cli/init.ts
|
|
233
|
+
function printHelp() {
|
|
234
|
+
console.log(`Usage: wolbarg init [options]
|
|
235
|
+
|
|
236
|
+
Configure Wolbarg for this project (database + optional embedding provider).
|
|
237
|
+
|
|
238
|
+
All prompts are optional \u2014 press Enter to accept defaults, or skip embedding.
|
|
239
|
+
|
|
240
|
+
Options:
|
|
241
|
+
-y, --yes Non-interactive; use defaults / flags
|
|
242
|
+
-f, --force Overwrite existing .wolbarg/config.json
|
|
243
|
+
--org <name> Organization id (default: ${DEFAULT_ORGANIZATION})
|
|
244
|
+
--db <path-or-url> SQLite path or Postgres URL
|
|
245
|
+
(default: ${DEFAULT_SQLITE_DB_PATH})
|
|
246
|
+
--db-provider <sqlite|postgres>
|
|
247
|
+
--provider <id> Embedding provider preset
|
|
248
|
+
(${EMBEDDING_PROVIDER_PRESETS.map((p) => p.id).join("|")})
|
|
249
|
+
--base-url <url> Embedding API base URL (shown with provider default)
|
|
250
|
+
--model <id> Embedding model id
|
|
251
|
+
--api-key <key> Write API key into .wolbarg/.env
|
|
252
|
+
--api-key-env <NAME> Env var name for the key
|
|
253
|
+
--skip-embedding Do not configure embedding
|
|
254
|
+
-h, --help Show help
|
|
255
|
+
|
|
256
|
+
Examples:
|
|
257
|
+
wolbarg init
|
|
258
|
+
wolbarg init --yes
|
|
259
|
+
wolbarg init --provider ollama --model nomic-embed-text --api-key ollama
|
|
260
|
+
wolbarg init --db postgresql://user:pass@localhost:5432/wolbarg --db-provider postgres
|
|
261
|
+
`);
|
|
262
|
+
}
|
|
263
|
+
function parseInitArgs(argv) {
|
|
264
|
+
const opts = {};
|
|
265
|
+
for (let i = 0; i < argv.length; i++) {
|
|
266
|
+
const a = argv[i];
|
|
267
|
+
const next = () => {
|
|
268
|
+
const v = argv[++i];
|
|
269
|
+
if (v === void 0) throw new Error(`Missing value after ${a}`);
|
|
270
|
+
return v;
|
|
271
|
+
};
|
|
272
|
+
switch (a) {
|
|
273
|
+
case "-h":
|
|
274
|
+
case "--help":
|
|
275
|
+
return { help: true };
|
|
276
|
+
case "-y":
|
|
277
|
+
case "--yes":
|
|
278
|
+
opts.yes = true;
|
|
279
|
+
break;
|
|
280
|
+
case "-f":
|
|
281
|
+
case "--force":
|
|
282
|
+
opts.force = true;
|
|
283
|
+
break;
|
|
284
|
+
case "--org":
|
|
285
|
+
opts.organization = next();
|
|
286
|
+
break;
|
|
287
|
+
case "--db":
|
|
288
|
+
opts.db = next();
|
|
289
|
+
break;
|
|
290
|
+
case "--db-provider": {
|
|
291
|
+
const p = next();
|
|
292
|
+
if (p !== "sqlite" && p !== "postgres") {
|
|
293
|
+
throw new Error(`--db-provider must be sqlite|postgres`);
|
|
294
|
+
}
|
|
295
|
+
opts.dbProvider = p;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
case "--provider":
|
|
299
|
+
opts.provider = next();
|
|
300
|
+
break;
|
|
301
|
+
case "--base-url":
|
|
302
|
+
opts.baseUrl = next();
|
|
303
|
+
break;
|
|
304
|
+
case "--model":
|
|
305
|
+
opts.model = next();
|
|
306
|
+
break;
|
|
307
|
+
case "--api-key":
|
|
308
|
+
opts.apiKey = next();
|
|
309
|
+
break;
|
|
310
|
+
case "--api-key-env":
|
|
311
|
+
opts.apiKeyEnv = next();
|
|
312
|
+
break;
|
|
313
|
+
case "--skip-embedding":
|
|
314
|
+
opts.skipEmbedding = true;
|
|
315
|
+
break;
|
|
316
|
+
default:
|
|
317
|
+
throw new Error(`Unknown argument: ${a}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return opts;
|
|
321
|
+
}
|
|
322
|
+
function inferDbProvider(url, explicit) {
|
|
323
|
+
if (explicit) return explicit;
|
|
324
|
+
if (/^postgres(ql)?:\/\//i.test(url)) return "postgres";
|
|
325
|
+
return "sqlite";
|
|
326
|
+
}
|
|
327
|
+
async function runInit(options = {}) {
|
|
328
|
+
const cwd = options.cwd ?? process.cwd();
|
|
329
|
+
const configPath = resolveConfigPath(cwd);
|
|
330
|
+
if (existsSync(configPath) && !options.force && !options.yes) {
|
|
331
|
+
const overwrite = await withReadline(
|
|
332
|
+
(rl) => askConfirm(
|
|
333
|
+
rl,
|
|
334
|
+
`Config already exists at ${configPath}. Overwrite?`,
|
|
335
|
+
false
|
|
336
|
+
)
|
|
337
|
+
);
|
|
338
|
+
if (!overwrite) {
|
|
339
|
+
console.log("Aborted. Pass --force to overwrite.");
|
|
340
|
+
return 1;
|
|
341
|
+
}
|
|
342
|
+
} else if (existsSync(configPath) && options.yes && !options.force) {
|
|
343
|
+
console.error(
|
|
344
|
+
`Config already exists at ${configPath}. Re-run with --force to overwrite.`
|
|
345
|
+
);
|
|
346
|
+
return 1;
|
|
347
|
+
}
|
|
348
|
+
const config = defaultProjectConfig();
|
|
349
|
+
let apiKey;
|
|
350
|
+
if (options.yes) {
|
|
351
|
+
config.organization = options.organization ?? DEFAULT_ORGANIZATION;
|
|
352
|
+
const dbUrl = options.db ?? DEFAULT_SQLITE_DB_PATH;
|
|
353
|
+
config.database = {
|
|
354
|
+
provider: inferDbProvider(dbUrl, options.dbProvider),
|
|
355
|
+
url: dbUrl
|
|
356
|
+
};
|
|
357
|
+
if (!options.skipEmbedding) {
|
|
358
|
+
const providerId = options.provider ?? "openai";
|
|
359
|
+
const preset = getEmbeddingProviderPreset(providerId);
|
|
360
|
+
if (!preset) {
|
|
361
|
+
console.error(`Unknown provider: ${providerId}`);
|
|
362
|
+
return 1;
|
|
363
|
+
}
|
|
364
|
+
const baseUrl = options.baseUrl ?? preset.defaultBaseUrl;
|
|
365
|
+
const model = options.model ?? preset.defaultModel;
|
|
366
|
+
config.embedding = {
|
|
367
|
+
provider: preset.id,
|
|
368
|
+
baseUrl,
|
|
369
|
+
model,
|
|
370
|
+
apiKeyEnv: options.apiKeyEnv ?? preset.apiKeyEnv
|
|
371
|
+
};
|
|
372
|
+
apiKey = options.apiKey;
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
await withReadline(async (rl) => {
|
|
376
|
+
console.log("\nWolbarg init \u2014 all fields optional (Enter = default / skip).\n");
|
|
377
|
+
const org = await askOptionalText(
|
|
378
|
+
rl,
|
|
379
|
+
"Organization",
|
|
380
|
+
options.organization ?? DEFAULT_ORGANIZATION
|
|
381
|
+
);
|
|
382
|
+
config.organization = org ?? DEFAULT_ORGANIZATION;
|
|
383
|
+
const dbUrl = await askOptionalText(
|
|
384
|
+
rl,
|
|
385
|
+
"Database path or Postgres URL",
|
|
386
|
+
options.db ?? DEFAULT_SQLITE_DB_PATH
|
|
387
|
+
);
|
|
388
|
+
const resolvedDb = dbUrl ?? DEFAULT_SQLITE_DB_PATH;
|
|
389
|
+
config.database = {
|
|
390
|
+
provider: inferDbProvider(resolvedDb, options.dbProvider),
|
|
391
|
+
url: resolvedDb
|
|
392
|
+
};
|
|
393
|
+
if (options.skipEmbedding) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const providerId = options.provider ?? await askSelect(
|
|
397
|
+
rl,
|
|
398
|
+
"Embedding provider",
|
|
399
|
+
EMBEDDING_PROVIDER_PRESETS.map((p) => ({
|
|
400
|
+
value: p.id,
|
|
401
|
+
label: `${p.label} \u2014 ${p.defaultBaseUrl}`
|
|
402
|
+
})),
|
|
403
|
+
"openai",
|
|
404
|
+
true
|
|
405
|
+
);
|
|
406
|
+
if (!providerId) {
|
|
407
|
+
console.log("Skipping embedding configuration.");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const preset = getEmbeddingProviderPreset(providerId);
|
|
411
|
+
if (!preset) {
|
|
412
|
+
console.log(`Unknown provider ${providerId}; skipping embedding.`);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
console.log(
|
|
416
|
+
`
|
|
417
|
+
Provider default base URL for ${preset.label}: ${preset.defaultBaseUrl}`
|
|
418
|
+
);
|
|
419
|
+
const baseUrl = options.baseUrl ?? await askText(
|
|
420
|
+
rl,
|
|
421
|
+
"Embedding base URL",
|
|
422
|
+
preset.defaultBaseUrl
|
|
423
|
+
);
|
|
424
|
+
const model = options.model ?? await askText(rl, "Embedding model", preset.defaultModel);
|
|
425
|
+
const apiKeyEnv = options.apiKeyEnv ?? await askText(rl, "API key environment variable", preset.apiKeyEnv);
|
|
426
|
+
const keyPrompt = preset.apiKeyHint ? `API key (${preset.apiKeyHint})` : `API key (stored in ${DEFAULT_ENV_PATH} as ${apiKeyEnv})`;
|
|
427
|
+
const key = options.apiKey ?? await askOptionalText(rl, keyPrompt, void 0);
|
|
428
|
+
config.embedding = {
|
|
429
|
+
provider: preset.id,
|
|
430
|
+
baseUrl: baseUrl || preset.defaultBaseUrl,
|
|
431
|
+
model: model || preset.defaultModel,
|
|
432
|
+
apiKeyEnv: apiKeyEnv || preset.apiKeyEnv
|
|
433
|
+
};
|
|
434
|
+
if (key) apiKey = key;
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
const saved = saveProjectConfig(config, {
|
|
438
|
+
cwd,
|
|
439
|
+
overwrite: true,
|
|
440
|
+
apiKey,
|
|
441
|
+
envPath: DEFAULT_ENV_PATH
|
|
442
|
+
});
|
|
443
|
+
console.log("\nWolbarg configured.\n");
|
|
444
|
+
console.log(` config: ${saved.configPath}`);
|
|
445
|
+
if (saved.envPath) console.log(` env: ${saved.envPath}`);
|
|
446
|
+
console.log(` db: ${config.database.provider} \u2192 ${config.database.url}`);
|
|
447
|
+
if (config.embedding) {
|
|
448
|
+
console.log(` embed: ${config.embedding.provider}`);
|
|
449
|
+
console.log(` base: ${config.embedding.baseUrl}`);
|
|
450
|
+
console.log(` model: ${config.embedding.model}`);
|
|
451
|
+
console.log(` key: $${config.embedding.apiKeyEnv}`);
|
|
452
|
+
} else {
|
|
453
|
+
console.log(" embed: (not configured)");
|
|
454
|
+
}
|
|
455
|
+
console.log(`
|
|
456
|
+
Next:
|
|
457
|
+
import { createWolbargFromProjectConfig } from "wolbarg";
|
|
458
|
+
const ctx = createWolbargFromProjectConfig();
|
|
459
|
+
await ctx.ready();
|
|
460
|
+
`);
|
|
461
|
+
return 0;
|
|
462
|
+
}
|
|
463
|
+
async function initCommand(argv) {
|
|
464
|
+
try {
|
|
465
|
+
const parsed = parseInitArgs(argv);
|
|
466
|
+
if ("help" in parsed) {
|
|
467
|
+
printHelp();
|
|
468
|
+
return 0;
|
|
469
|
+
}
|
|
470
|
+
return await runInit(parsed);
|
|
471
|
+
} catch (err) {
|
|
472
|
+
console.error(err instanceof Error ? err.message : err);
|
|
473
|
+
return 1;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// src/cli/index.ts
|
|
478
|
+
function printRootHelp() {
|
|
479
|
+
console.log(`wolbarg ${SDK_VERSION}
|
|
480
|
+
|
|
481
|
+
Usage:
|
|
482
|
+
wolbarg init [options] Configure project database + embedding provider
|
|
483
|
+
wolbarg --version Print version
|
|
484
|
+
wolbarg --help Show help
|
|
485
|
+
|
|
486
|
+
Run \`wolbarg init --help\` for init options.
|
|
487
|
+
`);
|
|
488
|
+
}
|
|
489
|
+
async function cliMain(argv) {
|
|
490
|
+
const [cmd, ...rest] = argv;
|
|
491
|
+
if (!cmd || cmd === "-h" || cmd === "--help") {
|
|
492
|
+
printRootHelp();
|
|
493
|
+
return 0;
|
|
494
|
+
}
|
|
495
|
+
if (cmd === "-V" || cmd === "--version" || cmd === "version") {
|
|
496
|
+
console.log(SDK_VERSION);
|
|
497
|
+
return 0;
|
|
498
|
+
}
|
|
499
|
+
if (cmd === "init") {
|
|
500
|
+
return initCommand(rest);
|
|
501
|
+
}
|
|
502
|
+
console.error(`Unknown command: ${cmd}`);
|
|
503
|
+
printRootHelp();
|
|
504
|
+
return 1;
|
|
505
|
+
}
|
|
506
|
+
cliMain(process.argv.slice(2)).then((code) => {
|
|
507
|
+
process.exit(code);
|
|
508
|
+
}).catch((err) => {
|
|
509
|
+
console.error(err);
|
|
510
|
+
process.exit(1);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
export { cliMain };
|
|
514
|
+
//# sourceMappingURL=cli.js.map
|
|
515
|
+
//# sourceMappingURL=cli.js.map
|