moltblock 0.4.0 → 0.5.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/dist/cli.js +6 -1
- package/dist/config.d.ts +17 -2
- package/dist/config.js +101 -46
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/readme.md +14 -1
package/dist/cli.js
CHANGED
|
@@ -14,6 +14,8 @@ async function main() {
|
|
|
14
14
|
.argument("<task>", "Task description (e.g. 'Implement a function add(a,b) that returns a+b.')")
|
|
15
15
|
.option("-t, --test <path>", "Path to file containing test code (e.g. vitest test module). If omitted, only syntax check.")
|
|
16
16
|
.option("--json", "Output result as JSON (draft, critique, final, verification_passed, authoritative_artifact).")
|
|
17
|
+
.option("-p, --provider <name>", "LLM provider (openai, google, zai, local). Auto-detected from env if omitted.")
|
|
18
|
+
.option("-m, --model <name>", "Model for all roles (overrides provider default).")
|
|
17
19
|
.action(async (task, options) => {
|
|
18
20
|
// Validate task input
|
|
19
21
|
const validation = validateTask(task);
|
|
@@ -30,7 +32,10 @@ async function main() {
|
|
|
30
32
|
if (options.test && fs.existsSync(options.test)) {
|
|
31
33
|
testCode = fs.readFileSync(options.test, "utf-8");
|
|
32
34
|
}
|
|
33
|
-
const entity = new CodeEntity(defaultCodeEntityBindings(
|
|
35
|
+
const entity = new CodeEntity(defaultCodeEntityBindings({
|
|
36
|
+
provider: options.provider,
|
|
37
|
+
model: options.model,
|
|
38
|
+
}));
|
|
34
39
|
const memory = await entity.run(task, { testCode });
|
|
35
40
|
if (options.json) {
|
|
36
41
|
const out = {
|
package/dist/config.d.ts
CHANGED
|
@@ -48,8 +48,23 @@ export declare function getConfigSource(): ConfigSource;
|
|
|
48
48
|
* Returns null if no file or parse error.
|
|
49
49
|
*/
|
|
50
50
|
export declare function loadMoltblockConfig(): MoltblockConfig | null;
|
|
51
|
+
/** Overrides for provider/model selection (e.g. from CLI flags). */
|
|
52
|
+
export interface BindingOverrides {
|
|
53
|
+
provider?: string;
|
|
54
|
+
model?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Auto-detect the best available provider from environment variables.
|
|
58
|
+
* Priority: explicit override > OPENAI_API_KEY > GOOGLE_API_KEY > MOLTBLOCK_ZAI_API_KEY/ZAI_API_KEY > local.
|
|
59
|
+
*/
|
|
60
|
+
export declare function detectProvider(overrideProvider?: string, overrideModel?: string): {
|
|
61
|
+
backend: string;
|
|
62
|
+
baseUrl: string;
|
|
63
|
+
model: string;
|
|
64
|
+
apiKey: string | null;
|
|
65
|
+
};
|
|
51
66
|
/**
|
|
52
67
|
* Model bindings for Code Entity. Load from moltblock.json if present, then env overrides.
|
|
53
|
-
* If no JSON,
|
|
68
|
+
* If no JSON, auto-detects provider from env vars. API keys from env win over JSON.
|
|
54
69
|
*/
|
|
55
|
-
export declare function defaultCodeEntityBindings(): Record<string, ModelBinding>;
|
|
70
|
+
export declare function defaultCodeEntityBindings(overrides?: BindingOverrides): Record<string, ModelBinding>;
|
package/dist/config.js
CHANGED
|
@@ -23,6 +23,13 @@ try {
|
|
|
23
23
|
catch {
|
|
24
24
|
// dotenv not required
|
|
25
25
|
}
|
|
26
|
+
// --- Provider defaults registry ---
|
|
27
|
+
const PROVIDER_DEFAULTS = {
|
|
28
|
+
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4o", envKey: "OPENAI_API_KEY" },
|
|
29
|
+
google: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai/", model: "gemini-2.0-flash", envKey: "GOOGLE_API_KEY" },
|
|
30
|
+
zai: { baseUrl: "https://api.z.ai/api/paas/v4", model: "glm-4.7-flash", envKey: "MOLTBLOCK_ZAI_API_KEY" },
|
|
31
|
+
local: { baseUrl: "http://localhost:1234/v1", model: "local", envKey: "" },
|
|
32
|
+
};
|
|
26
33
|
// --- Zod schemas (OpenClaw-style config) ---
|
|
27
34
|
export const BindingEntrySchema = z.object({
|
|
28
35
|
backend: z.string().describe("e.g. 'local' or 'zai' or 'openai'"),
|
|
@@ -138,18 +145,49 @@ export function loadMoltblockConfig() {
|
|
|
138
145
|
}
|
|
139
146
|
/**
|
|
140
147
|
* Parse OpenClaw config and convert to MoltblockConfig format.
|
|
141
|
-
*
|
|
148
|
+
* Handles multiple OpenClaw formats: agents.defaults.model.primary ("provider/model"),
|
|
149
|
+
* agent.bindings, providers section, and models section.
|
|
142
150
|
*/
|
|
143
151
|
function parseOpenClawConfig(data) {
|
|
144
152
|
if (!data || typeof data !== "object") {
|
|
145
153
|
return null;
|
|
146
154
|
}
|
|
147
155
|
const obj = data;
|
|
148
|
-
// OpenClaw may have agent.bindings or providers section
|
|
149
|
-
// Try to extract bindings from various possible locations
|
|
150
156
|
let bindings;
|
|
157
|
+
// Check for agents.defaults.model.primary (OpenClaw's actual format: "provider/model")
|
|
158
|
+
if (obj["agents"] && typeof obj["agents"] === "object") {
|
|
159
|
+
const agents = obj["agents"];
|
|
160
|
+
if (agents["defaults"] && typeof agents["defaults"] === "object") {
|
|
161
|
+
const defaults = agents["defaults"];
|
|
162
|
+
if (defaults["model"] && typeof defaults["model"] === "object") {
|
|
163
|
+
const modelConfig = defaults["model"];
|
|
164
|
+
const primary = modelConfig["primary"];
|
|
165
|
+
if (typeof primary === "string" && primary.includes("/")) {
|
|
166
|
+
const parts = primary.split("/");
|
|
167
|
+
const providerName = parts[0] ?? "";
|
|
168
|
+
const modelName = parts.slice(1).join("/");
|
|
169
|
+
const provider = PROVIDER_DEFAULTS[providerName.toLowerCase()];
|
|
170
|
+
if (providerName && provider) {
|
|
171
|
+
const apiKey = getApiKeyForBackend(providerName);
|
|
172
|
+
const binding = {
|
|
173
|
+
backend: providerName.toLowerCase(),
|
|
174
|
+
base_url: provider.baseUrl,
|
|
175
|
+
model: modelName || provider.model,
|
|
176
|
+
api_key: apiKey,
|
|
177
|
+
};
|
|
178
|
+
bindings = {
|
|
179
|
+
generator: binding,
|
|
180
|
+
critic: { ...binding },
|
|
181
|
+
judge: { ...binding },
|
|
182
|
+
verifier: { ...binding },
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
151
189
|
// Check for agent.bindings (same as moltblock)
|
|
152
|
-
if (obj["agent"] && typeof obj["agent"] === "object") {
|
|
190
|
+
if (!bindings && obj["agent"] && typeof obj["agent"] === "object") {
|
|
153
191
|
const agent = obj["agent"];
|
|
154
192
|
if (agent["bindings"] && typeof agent["bindings"] === "object") {
|
|
155
193
|
bindings = extractBindings(agent["bindings"]);
|
|
@@ -242,23 +280,66 @@ function getApiKeyForBackend(backend) {
|
|
|
242
280
|
return env("GOOGLE_API_KEY") || null;
|
|
243
281
|
}
|
|
244
282
|
if (backendLower === "zai") {
|
|
245
|
-
return env("MOLTBLOCK_ZAI_API_KEY") || null;
|
|
283
|
+
return env("MOLTBLOCK_ZAI_API_KEY") || env("ZAI_API_KEY") || null;
|
|
246
284
|
}
|
|
247
285
|
return null;
|
|
248
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Auto-detect the best available provider from environment variables.
|
|
289
|
+
* Priority: explicit override > OPENAI_API_KEY > GOOGLE_API_KEY > MOLTBLOCK_ZAI_API_KEY/ZAI_API_KEY > local.
|
|
290
|
+
*/
|
|
291
|
+
export function detectProvider(overrideProvider, overrideModel) {
|
|
292
|
+
if (overrideProvider) {
|
|
293
|
+
const p = PROVIDER_DEFAULTS[overrideProvider.toLowerCase()];
|
|
294
|
+
if (!p) {
|
|
295
|
+
throw new Error(`Unknown provider "${overrideProvider}". Valid providers: ${Object.keys(PROVIDER_DEFAULTS).join(", ")}`);
|
|
296
|
+
}
|
|
297
|
+
const apiKey = p.envKey ? env(p.envKey) || null : null;
|
|
298
|
+
return {
|
|
299
|
+
backend: overrideProvider.toLowerCase(),
|
|
300
|
+
baseUrl: p.baseUrl,
|
|
301
|
+
model: overrideModel || p.model,
|
|
302
|
+
apiKey,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
// Scan env vars in priority order
|
|
306
|
+
const priority = [
|
|
307
|
+
{ name: "openai", envKey: "OPENAI_API_KEY" },
|
|
308
|
+
{ name: "google", envKey: "GOOGLE_API_KEY" },
|
|
309
|
+
{ name: "zai", envKey: "MOLTBLOCK_ZAI_API_KEY" },
|
|
310
|
+
{ name: "zai", envKey: "ZAI_API_KEY" },
|
|
311
|
+
];
|
|
312
|
+
for (const { name, envKey } of priority) {
|
|
313
|
+
const key = env(envKey);
|
|
314
|
+
if (key) {
|
|
315
|
+
const p = PROVIDER_DEFAULTS[name];
|
|
316
|
+
return {
|
|
317
|
+
backend: name,
|
|
318
|
+
baseUrl: p.baseUrl,
|
|
319
|
+
model: overrideModel || p.model,
|
|
320
|
+
apiKey: key,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// Fallback to local
|
|
325
|
+
const local = PROVIDER_DEFAULTS["local"];
|
|
326
|
+
return {
|
|
327
|
+
backend: "local",
|
|
328
|
+
baseUrl: local.baseUrl,
|
|
329
|
+
model: overrideModel || local.model,
|
|
330
|
+
apiKey: null,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
249
333
|
/**
|
|
250
334
|
* Model bindings for Code Entity. Load from moltblock.json if present, then env overrides.
|
|
251
|
-
* If no JSON,
|
|
335
|
+
* If no JSON, auto-detects provider from env vars. API keys from env win over JSON.
|
|
252
336
|
*/
|
|
253
|
-
export function defaultCodeEntityBindings() {
|
|
337
|
+
export function defaultCodeEntityBindings(overrides) {
|
|
254
338
|
const cfg = loadMoltblockConfig();
|
|
255
|
-
const zaiKey = env("MOLTBLOCK_ZAI_API_KEY");
|
|
256
|
-
const localUrl = env("MOLTBLOCK_GENERATOR_BASE_URL") || "http://localhost:1234/v1";
|
|
257
|
-
const localModel = env("MOLTBLOCK_GENERATOR_MODEL") || "local";
|
|
258
339
|
const envUrl = (key, fallback) => env(key) || fallback;
|
|
259
340
|
const envModel = (key, fallback) => env(key) || fallback;
|
|
260
341
|
const bindingsFromJson = cfg?.agent?.bindings ?? {};
|
|
261
|
-
function bindingFor(role
|
|
342
|
+
function bindingFor(role) {
|
|
262
343
|
const entry = bindingsFromJson[role];
|
|
263
344
|
if (entry) {
|
|
264
345
|
const baseUrl = envUrl(`MOLTBLOCK_${role.toUpperCase()}_BASE_URL`, entry.base_url);
|
|
@@ -271,42 +352,16 @@ export function defaultCodeEntityBindings() {
|
|
|
271
352
|
const apiKey = envApiKey || entry.api_key || getApiKeyForBackend(entry.backend) || null;
|
|
272
353
|
return { backend: entry.backend, baseUrl, apiKey, model };
|
|
273
354
|
}
|
|
274
|
-
// No JSON:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const useZai = Boolean(zaiKey);
|
|
280
|
-
return {
|
|
281
|
-
backend: useZai ? "zai" : "local",
|
|
282
|
-
baseUrl: envUrl("MOLTBLOCK_CRITIC_BASE_URL", useZai ? "https://api.z.ai/api/paas/v4" : localUrl),
|
|
283
|
-
apiKey: useZai ? zaiKey : null,
|
|
284
|
-
model: envModel("MOLTBLOCK_CRITIC_MODEL", useZai ? "glm-4.7-flash" : localModel),
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
if (role === "judge") {
|
|
288
|
-
const useZai = Boolean(zaiKey);
|
|
289
|
-
return {
|
|
290
|
-
backend: useZai ? "zai" : "local",
|
|
291
|
-
baseUrl: envUrl("MOLTBLOCK_JUDGE_BASE_URL", useZai ? "https://api.z.ai/api/paas/v4" : localUrl),
|
|
292
|
-
apiKey: useZai ? zaiKey : null,
|
|
293
|
-
model: envModel("MOLTBLOCK_JUDGE_MODEL", useZai ? "glm-4.7-flash" : localModel),
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
if (role === "verifier") {
|
|
297
|
-
return {
|
|
298
|
-
backend: "local",
|
|
299
|
-
baseUrl: envUrl("MOLTBLOCK_VERIFIER_BASE_URL", localUrl),
|
|
300
|
-
apiKey: null,
|
|
301
|
-
model: envModel("MOLTBLOCK_VERIFIER_MODEL", localModel),
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
return { backend: defaultBackend, baseUrl: defaultBase, apiKey: defaultApiKey, model: defaultModel };
|
|
355
|
+
// No JSON entry for this role: auto-detect provider
|
|
356
|
+
const detected = detectProvider(overrides?.provider, overrides?.model);
|
|
357
|
+
const baseUrl = envUrl(`MOLTBLOCK_${role.toUpperCase()}_BASE_URL`, detected.baseUrl);
|
|
358
|
+
const model = envModel(`MOLTBLOCK_${role.toUpperCase()}_MODEL`, detected.model);
|
|
359
|
+
return { backend: detected.backend, baseUrl, apiKey: detected.apiKey, model };
|
|
305
360
|
}
|
|
306
361
|
return {
|
|
307
|
-
generator: bindingFor("generator"
|
|
308
|
-
critic: bindingFor("critic"
|
|
309
|
-
judge: bindingFor("judge"
|
|
310
|
-
verifier: bindingFor("verifier"
|
|
362
|
+
generator: bindingFor("generator"),
|
|
363
|
+
critic: bindingFor("critic"),
|
|
364
|
+
judge: bindingFor("judge"),
|
|
365
|
+
verifier: bindingFor("verifier"),
|
|
311
366
|
};
|
|
312
367
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Moltblock — framework for evolving composite intelligences (Entities).
|
|
3
3
|
*/
|
|
4
|
-
export declare const VERSION = "0.
|
|
4
|
+
export declare const VERSION = "0.5.0";
|
|
5
5
|
export type { ModelBinding, BindingEntry, AgentConfig, MoltblockConfig, ChatMessage, VerifiedMemoryEntry, CheckpointEntry, OutcomeEntry, InboxEntry, StrategySuggestion, ReceivedArtifact, GovernanceConfig, } from "./types.js";
|
|
6
6
|
export { WorkingMemory } from "./memory.js";
|
|
7
7
|
export { signArtifact, verifyArtifact, artifactHash } from "./signing.js";
|
|
8
|
-
export { loadMoltblockConfig, defaultCodeEntityBindings, getConfigSource, BindingEntrySchema, AgentConfigSchema, MoltblockConfigSchema, ModelBindingSchema, type ConfigSource, } from "./config.js";
|
|
8
|
+
export { loadMoltblockConfig, defaultCodeEntityBindings, detectProvider, getConfigSource, BindingEntrySchema, AgentConfigSchema, MoltblockConfigSchema, ModelBindingSchema, type BindingOverrides, type ConfigSource, } from "./config.js";
|
|
9
9
|
export { Store, hashGraph, hashMemory, auditLog, getGovernanceValue, setGovernanceValue, putInbox, getInbox, recordOutcome, getRecentOutcomes, getStrategy, setStrategy, } from "./persistence.js";
|
|
10
10
|
export { LLMGateway } from "./gateway.js";
|
|
11
11
|
export { runGenerator, runCritic, runJudge, runRole, } from "./agents.js";
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Moltblock — framework for evolving composite intelligences (Entities).
|
|
3
3
|
*/
|
|
4
|
-
export const VERSION = "0.
|
|
4
|
+
export const VERSION = "0.5.0";
|
|
5
5
|
// Memory
|
|
6
6
|
export { WorkingMemory } from "./memory.js";
|
|
7
7
|
// Signing
|
|
8
8
|
export { signArtifact, verifyArtifact, artifactHash } from "./signing.js";
|
|
9
9
|
// Config
|
|
10
|
-
export { loadMoltblockConfig, defaultCodeEntityBindings, getConfigSource, BindingEntrySchema, AgentConfigSchema, MoltblockConfigSchema, ModelBindingSchema, } from "./config.js";
|
|
10
|
+
export { loadMoltblockConfig, defaultCodeEntityBindings, detectProvider, getConfigSource, BindingEntrySchema, AgentConfigSchema, MoltblockConfigSchema, ModelBindingSchema, } from "./config.js";
|
|
11
11
|
// Persistence
|
|
12
12
|
export { Store, hashGraph, hashMemory, auditLog, getGovernanceValue, setGovernanceValue, putInbox, getInbox, recordOutcome, getRecentOutcomes, getStrategy, setStrategy, } from "./persistence.js";
|
|
13
13
|
// Gateway
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -67,7 +67,7 @@ Blockchain is optional and used only for anchoring.
|
|
|
67
67
|
|
|
68
68
|
## Run (Code Entity MVP)
|
|
69
69
|
|
|
70
|
-
Requires Node.js
|
|
70
|
+
Requires Node.js 22+, and (for full loop) any OpenAI-compatible API:
|
|
71
71
|
- **OpenAI** — `https://api.openai.com/v1` with `OPENAI_API_KEY`
|
|
72
72
|
- **Anthropic Claude** — `https://api.anthropic.com/v1` with `ANTHROPIC_API_KEY`
|
|
73
73
|
- **Google Gemini** — `https://generativelanguage.googleapis.com/v1beta/openai` with `GOOGLE_API_KEY`
|
|
@@ -105,6 +105,19 @@ npx moltblock "Implement add(a, b)."
|
|
|
105
105
|
|
|
106
106
|
## Configuration
|
|
107
107
|
|
|
108
|
+
### Zero-config (auto-detect)
|
|
109
|
+
|
|
110
|
+
If you have an API key set in your environment, moltblock detects the provider automatically — no config file needed:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
export OPENAI_API_KEY="sk-..." # auto-detects OpenAI
|
|
114
|
+
npx moltblock "Implement add(a, b)." --json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Override with CLI flags: `--provider google --model gemini-2.0-flash` or `-p zai -m glm-4.7`.
|
|
118
|
+
|
|
119
|
+
Detection priority: `OPENAI_API_KEY` > `GOOGLE_API_KEY` > `MOLTBLOCK_ZAI_API_KEY` > localhost.
|
|
120
|
+
|
|
108
121
|
### Quick setup
|
|
109
122
|
|
|
110
123
|
Create a config file at `~/.moltblock/moltblock.json` (user-wide) or `./moltblock.json` (project-specific):
|