@lobu/cli 6.0.1 → 6.1.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 +20 -27
- package/dist/bundled-skills/lobu/SKILL.md +11 -11
- package/dist/commands/_lib/apply/apply-cmd.d.ts +2 -0
- package/dist/commands/_lib/apply/apply-cmd.d.ts.map +1 -1
- package/dist/commands/_lib/apply/apply-cmd.js +26 -0
- package/dist/commands/_lib/apply/apply-cmd.js.map +1 -1
- package/dist/commands/_lib/apply/client.d.ts +1 -1
- package/dist/commands/_lib/apply/client.d.ts.map +1 -1
- package/dist/commands/_lib/apply/desired-state.js +4 -4
- package/dist/commands/_lib/apply/desired-state.js.map +1 -1
- package/dist/commands/agent.d.ts +7 -0
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +65 -1
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/chat.d.ts +12 -9
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +117 -56
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/dev.d.ts +15 -7
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +79 -44
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +136 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/eval.d.ts +8 -0
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +56 -1
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/init.d.ts +20 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +332 -183
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/link.d.ts +11 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +28 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +14 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/memory/_lib/browser-auth-cmd.d.ts.map +1 -1
- package/dist/commands/memory/_lib/browser-auth-cmd.js +3 -3
- package/dist/commands/memory/_lib/browser-auth-cmd.js.map +1 -1
- package/dist/commands/memory/_lib/mcp.d.ts +2 -2
- package/dist/commands/memory/_lib/mcp.d.ts.map +1 -1
- package/dist/commands/memory/_lib/mcp.js +24 -12
- package/dist/commands/memory/_lib/mcp.js.map +1 -1
- package/dist/commands/memory/_lib/openclaw-auth.d.ts +1 -0
- package/dist/commands/memory/_lib/openclaw-auth.d.ts.map +1 -1
- package/dist/commands/memory/_lib/openclaw-auth.js +14 -3
- package/dist/commands/memory/_lib/openclaw-auth.js.map +1 -1
- package/dist/commands/memory/_lib/openclaw-cmd.js +1 -1
- package/dist/commands/memory/_lib/openclaw-cmd.js.map +1 -1
- package/dist/commands/memory/_lib/schema.d.ts +1 -1
- package/dist/commands/memory/_lib/schema.js +1 -1
- package/dist/commands/memory/_lib/seed-cmd.d.ts.map +1 -1
- package/dist/commands/memory/_lib/seed-cmd.js +5 -6
- package/dist/commands/memory/_lib/seed-cmd.js.map +1 -1
- package/dist/commands/memory/run.d.ts.map +1 -1
- package/dist/commands/memory/run.js +2 -2
- package/dist/commands/memory/run.js.map +1 -1
- package/dist/commands/platforms/platform-prompts.d.ts +0 -1
- package/dist/commands/platforms/platform-prompts.d.ts.map +1 -1
- package/dist/commands/platforms/platform-prompts.js +54 -8
- package/dist/commands/platforms/platform-prompts.js.map +1 -1
- package/dist/commands/telemetry.d.ts +10 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +68 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/connectors/README.md +534 -0
- package/dist/connectors/__tests__/browser-scraper-utils.test.ts +186 -0
- package/dist/connectors/browser-scraper-utils.ts +214 -0
- package/dist/connectors/capterra.ts +273 -0
- package/dist/connectors/g2.ts +286 -0
- package/dist/connectors/github.ts +1553 -0
- package/dist/connectors/glassdoor.ts +291 -0
- package/dist/connectors/gmaps.ts +197 -0
- package/dist/connectors/google_calendar.ts +631 -0
- package/dist/connectors/google_gmail.ts +751 -0
- package/dist/connectors/google_photos.ts +776 -0
- package/dist/connectors/google_play.ts +342 -0
- package/dist/connectors/hackernews.ts +471 -0
- package/dist/connectors/index.ts +23 -0
- package/dist/connectors/ios_appstore.ts +226 -0
- package/dist/connectors/linkedin.ts +471 -0
- package/dist/connectors/microsoft_outlook.ts +410 -0
- package/dist/connectors/producthunt.ts +471 -0
- package/dist/connectors/reddit.ts +600 -0
- package/dist/connectors/rss.ts +448 -0
- package/dist/connectors/spotify.ts +590 -0
- package/dist/connectors/trustpilot.ts +199 -0
- package/dist/connectors/website.ts +629 -0
- package/dist/connectors/whatsapp.ts +1073 -0
- package/dist/connectors/x.ts +526 -0
- package/dist/connectors/youtube.ts +666 -0
- package/dist/db/migrations/00000000000000_baseline.sql +4867 -0
- package/dist/db/migrations/20260405193000_add_mcp_sessions.sql +33 -0
- package/dist/db/migrations/20260408120000_remove_system_connectors.sql +48 -0
- package/dist/db/migrations/20260408120001_optional_compiled_code.sql +6 -0
- package/dist/db/migrations/20260409110000_add_active_watcher_run_index.sql +9 -0
- package/dist/db/migrations/20260409130000_connector_default_config.sql +5 -0
- package/dist/db/migrations/20260410120000_add_agent_secrets.sql +25 -0
- package/dist/db/migrations/20260413170000_add_watcher_group_id.sql +67 -0
- package/dist/db/migrations/20260416120000_add_entity_wa_jid_index.sql +14 -0
- package/dist/db/migrations/20260417100000_add_entity_identities.sql +77 -0
- package/dist/db/migrations/20260418100000_add_auth_runs.sql +83 -0
- package/dist/db/migrations/20260418110000_add_runs_created_by_user.sql +18 -0
- package/dist/db/migrations/20260419120000_add_event_identity_indexes.sql +56 -0
- package/dist/db/migrations/20260420120000_extend_reserved_org_slugs.sql +56 -0
- package/dist/db/migrations/20260424030000_add_watcher_run_correlation.sql +52 -0
- package/dist/db/migrations/20260424130000_relax_events_client_id_fk.sql +47 -0
- package/dist/db/migrations/20260425100000_normalize_watcher_feedback.sql +91 -0
- package/dist/db/migrations/20260425120000_add_run_diagnostics.sql +20 -0
- package/dist/db/migrations/20260425130000_add_repair_agent_plumbing.sql +46 -0
- package/dist/db/migrations/20260426120000_entities_entity_type_fk.sql +101 -0
- package/dist/db/migrations/20260426130000_db_integrity_cleanup.sql +104 -0
- package/dist/db/migrations/20260426130001_db_integrity_cleanup_concurrent.sql +187 -0
- package/dist/db/migrations/20260427133000_events_created_by_nullable.sql +74 -0
- package/dist/db/migrations/20260427140000_identity_engine_indexes.sql +140 -0
- package/dist/db/migrations/20260427150000_drop_events_source_id.sql +177 -0
- package/dist/db/migrations/20260427160000_drop_dead_schema.sql +76 -0
- package/dist/db/migrations/20260427170000_market_founder_to_member.sql +364 -0
- package/dist/db/migrations/20260428040000_cascade_events_watchers_org_fk.sql +66 -0
- package/dist/db/migrations/20260428050000_add_runs_approved_input.sql +9 -0
- package/dist/db/migrations/20260429010000_auth_profile_tenant_scoped_fk.sql +79 -0
- package/dist/db/migrations/20260429060000_extend_runs_for_lobu_queue.sql +108 -0
- package/dist/db/migrations/20260429120000_agent_changed_notify.sql +97 -0
- package/dist/db/migrations/20260429120100_user_auth_profiles_and_model_prefs.sql +36 -0
- package/dist/db/migrations/20260429120200_fix_notify_old_keys.sql +130 -0
- package/dist/db/migrations/20260429130000_oauth_states_cli_sessions_rate_limits.sql +83 -0
- package/dist/db/migrations/20260429140000_phase8_grants_chat_connections_mcp_sessions.sql +84 -0
- package/dist/db/migrations/20260429140100_runs_priority_expires_at_retry_delay.sql +44 -0
- package/dist/db/migrations/20260429180000_drop_invalidatable_cache_triggers.sql +25 -0
- package/dist/db/migrations/20260430005614_agents_apply_fields.sql +21 -0
- package/dist/db/migrations/20260430022231_fix_connection_config_encryption.sql +69 -0
- package/dist/db/migrations/20260430151215_add_task_run_type.sql +77 -0
- package/dist/db/migrations/20260501000000_drop_cli_sessions.sql +27 -0
- package/dist/db/migrations/20260501133000_lobu_memory_mcp_id.sql +117 -0
- package/dist/db/migrations/20260502000000_drop_chat_connections.sql +60 -0
- package/dist/db/migrations/20260503000000_agent_secrets_org_scope.sql +56 -0
- package/dist/db/migrations/20260504000000_flatten_agents_drop_sandbox_model.sql +48 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +147 -23
- package/dist/index.js.map +1 -1
- package/dist/internal/api-client.d.ts +4 -8
- package/dist/internal/api-client.d.ts.map +1 -1
- package/dist/internal/api-client.js +1 -1
- package/dist/internal/api-client.js.map +1 -1
- package/dist/internal/context.js +2 -2
- package/dist/internal/context.js.map +1 -1
- package/dist/internal/credentials.d.ts.map +1 -1
- package/dist/internal/credentials.js +6 -1
- package/dist/internal/credentials.js.map +1 -1
- package/dist/internal/index.d.ts +2 -3
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +2 -2
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/oauth.d.ts +6 -5
- package/dist/internal/oauth.d.ts.map +1 -1
- package/dist/internal/oauth.js +2 -2
- package/dist/internal/project-link.d.ts +10 -0
- package/dist/internal/project-link.d.ts.map +1 -0
- package/dist/internal/project-link.js +48 -0
- package/dist/internal/project-link.js.map +1 -0
- package/dist/providers.json +2 -2
- package/dist/server.bundle.mjs +3090 -4321
- package/dist/start-local.bundle.mjs +71481 -0
- package/dist/templates/README.md.tmpl +10 -11
- package/package.json +14 -12
- package/dist/__tests__/chat.integration.test.d.ts +0 -2
- package/dist/__tests__/chat.integration.test.d.ts.map +0 -1
- package/dist/__tests__/chat.integration.test.js +0 -337
- package/dist/__tests__/chat.integration.test.js.map +0 -1
- package/dist/__tests__/dev.test.d.ts +0 -2
- package/dist/__tests__/dev.test.d.ts.map +0 -1
- package/dist/__tests__/dev.test.js +0 -25
- package/dist/__tests__/dev.test.js.map +0 -1
- package/dist/__tests__/init-memory.test.d.ts +0 -2
- package/dist/__tests__/init-memory.test.d.ts.map +0 -1
- package/dist/__tests__/init-memory.test.js +0 -45
- package/dist/__tests__/init-memory.test.js.map +0 -1
- package/dist/__tests__/token.test.d.ts +0 -2
- package/dist/__tests__/token.test.d.ts.map +0 -1
- package/dist/__tests__/token.test.js +0 -52
- package/dist/__tests__/token.test.js.map +0 -1
- package/dist/commands/_lib/apply/__tests__/client.test.d.ts +0 -2
- package/dist/commands/_lib/apply/__tests__/client.test.d.ts.map +0 -1
- package/dist/commands/_lib/apply/__tests__/client.test.js +0 -23
- package/dist/commands/_lib/apply/__tests__/client.test.js.map +0 -1
- package/dist/commands/_lib/apply/__tests__/desired-state.test.d.ts +0 -2
- package/dist/commands/_lib/apply/__tests__/desired-state.test.d.ts.map +0 -1
- package/dist/commands/_lib/apply/__tests__/desired-state.test.js +0 -140
- package/dist/commands/_lib/apply/__tests__/desired-state.test.js.map +0 -1
- package/dist/commands/_lib/apply/__tests__/diff.test.d.ts +0 -2
- package/dist/commands/_lib/apply/__tests__/diff.test.d.ts.map +0 -1
- package/dist/commands/_lib/apply/__tests__/diff.test.js +0 -378
- package/dist/commands/_lib/apply/__tests__/diff.test.js.map +0 -1
- package/dist/commands/apply.d.ts +0 -3
- package/dist/commands/apply.d.ts.map +0 -1
- package/dist/commands/apply.js +0 -5
- package/dist/commands/apply.js.map +0 -1
- package/dist/commands/memory/_lib/openclaw-auth.test.d.ts +0 -2
- package/dist/commands/memory/_lib/openclaw-auth.test.d.ts.map +0 -1
- package/dist/commands/memory/_lib/openclaw-auth.test.js +0 -9
- package/dist/commands/memory/_lib/openclaw-auth.test.js.map +0 -1
- package/dist/internal/__tests__/api-client.test.d.ts +0 -2
- package/dist/internal/__tests__/api-client.test.d.ts.map +0 -1
- package/dist/internal/__tests__/api-client.test.js +0 -95
- package/dist/internal/__tests__/api-client.test.js.map +0 -1
- package/dist/internal/__tests__/context.test.d.ts +0 -2
- package/dist/internal/__tests__/context.test.d.ts.map +0 -1
- package/dist/internal/__tests__/context.test.js +0 -77
- package/dist/internal/__tests__/context.test.js.map +0 -1
package/dist/commands/init.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { constants } from "node:fs";
|
|
3
|
-
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
-
import { join } from "node:path";
|
|
3
|
+
import { access, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
5
|
import { confirm, input, password, select } from "@inquirer/prompts";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import ora from "ora";
|
|
@@ -9,76 +9,138 @@ import { promptPlatformConfig } from "../commands/platforms/platform-prompts.js"
|
|
|
9
9
|
import { setLocalEnvValue } from "../internal/local-env.js";
|
|
10
10
|
import { getProviderById, loadProviderRegistry, } from "../commands/providers/registry.js";
|
|
11
11
|
import { renderTemplate } from "../utils/template.js";
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const DEFAULT_LOBU_MCP_URL = "https://lobu.ai/mcp";
|
|
13
|
+
const PROJECT_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
14
|
+
const PLATFORM_CHOICES = [
|
|
15
|
+
"telegram",
|
|
16
|
+
"slack",
|
|
17
|
+
"discord",
|
|
18
|
+
"whatsapp",
|
|
19
|
+
"teams",
|
|
20
|
+
"gchat",
|
|
21
|
+
];
|
|
22
|
+
const NETWORK_CHOICES = ["restricted", "open", "isolated"];
|
|
23
|
+
const MEMORY_CHOICES = ["none", "lobu-cloud", "lobu-custom"];
|
|
24
|
+
export async function initCommand(cwd = process.cwd(), projectNameArg, options = {}) {
|
|
16
25
|
const cliVersion = await getCliVersion();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
26
|
+
const useDefaults = options.yes === true;
|
|
27
|
+
// Catch flag combos that can't satisfy a prompt before we mkdir anything.
|
|
28
|
+
if (useDefaults && options.memory === "lobu-custom" && !options.memoryUrl) {
|
|
29
|
+
console.error(chalk.red("\n✗ --memory lobu-custom requires --memory-url <url>.\n"));
|
|
20
30
|
process.exit(1);
|
|
21
31
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
const here = options.here || projectNameArg === ".";
|
|
33
|
+
let projectName;
|
|
34
|
+
let projectDir;
|
|
35
|
+
if (here) {
|
|
36
|
+
projectDir = cwd;
|
|
37
|
+
projectName = basename(resolve(cwd));
|
|
38
|
+
if (!PROJECT_NAME_PATTERN.test(projectName)) {
|
|
39
|
+
// Common when cwd is e.g. "My Project". Force user to pick a slug.
|
|
40
|
+
projectName =
|
|
41
|
+
projectNameArg && projectNameArg !== "."
|
|
42
|
+
? projectNameArg
|
|
43
|
+
: await promptOrDefault({
|
|
44
|
+
flag: undefined,
|
|
45
|
+
useDefaults,
|
|
46
|
+
defaultValue: slugify(basename(resolve(cwd))) || "my-lobu",
|
|
47
|
+
prompt: () => input({
|
|
48
|
+
message: "Project slug?",
|
|
49
|
+
default: slugify(basename(resolve(cwd))) || "my-lobu",
|
|
50
|
+
validate: validateProjectName,
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const entries = await readdir(projectDir).catch(() => []);
|
|
55
|
+
const conflict = entries.some((n) => n === "lobu.toml" || n === "agents" || n === ".env");
|
|
56
|
+
if (conflict) {
|
|
57
|
+
console.log(chalk.red(`\n✗ ${projectDir} already contains a Lobu project (lobu.toml / agents/ / .env).\n Remove them or pick another directory.\n`));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
console.log(chalk.dim(`\nScaffolding into current directory: ${chalk.cyan(projectDir)}\n`));
|
|
39
61
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
else {
|
|
63
|
+
if (projectNameArg && !PROJECT_NAME_PATTERN.test(projectNameArg)) {
|
|
64
|
+
console.log(chalk.red(`\n✗ Project name must be lowercase alphanumeric with hyphens only (got: ${projectNameArg}).\n`));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
projectName =
|
|
68
|
+
projectNameArg ??
|
|
69
|
+
(await promptOrDefault({
|
|
70
|
+
flag: undefined,
|
|
71
|
+
useDefaults,
|
|
72
|
+
defaultValue: "my-lobu",
|
|
73
|
+
prompt: () => input({
|
|
74
|
+
message: "Project name?",
|
|
75
|
+
default: "my-lobu",
|
|
76
|
+
validate: validateProjectName,
|
|
77
|
+
}),
|
|
78
|
+
}));
|
|
79
|
+
projectDir = join(cwd, projectName);
|
|
80
|
+
try {
|
|
81
|
+
await access(projectDir, constants.F_OK);
|
|
82
|
+
console.log(chalk.red(`\n✗ Directory "${projectName}" already exists. Pick a different name, remove it, or pass \`--here\` to scaffold into the current directory.\n`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
await mkdir(projectDir, { recursive: true });
|
|
87
|
+
console.log(chalk.dim(`\nCreating project in: ${chalk.cyan(projectDir)}\n`));
|
|
88
|
+
}
|
|
44
89
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
90
|
+
const gatewayPort = await promptOrDefault({
|
|
91
|
+
flag: options.port,
|
|
92
|
+
useDefaults,
|
|
93
|
+
defaultValue: "8787",
|
|
49
94
|
validate: (value) => {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return true;
|
|
95
|
+
const p = Number(value);
|
|
96
|
+
return Number.isInteger(p) && p >= 1 && p <= 65535
|
|
97
|
+
? true
|
|
98
|
+
: "Please enter a valid port (1-65535)";
|
|
55
99
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
choices: [
|
|
66
|
-
{
|
|
67
|
-
name: "Restricted (recommended) — common registries only (npm, GitHub, PyPI)",
|
|
68
|
-
value: "restricted",
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: "Open — workers can access any domain",
|
|
72
|
-
value: "open",
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
name: "Isolated — workers have no internet access",
|
|
76
|
-
value: "isolated",
|
|
100
|
+
prompt: () => input({
|
|
101
|
+
message: "Gateway port?",
|
|
102
|
+
default: "8787",
|
|
103
|
+
validate: (value) => {
|
|
104
|
+
const p = Number(value);
|
|
105
|
+
if (!Number.isInteger(p) || p < 1 || p > 65535) {
|
|
106
|
+
return "Please enter a valid port number (1-65535)";
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
77
109
|
},
|
|
78
|
-
|
|
79
|
-
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
const publicGatewayUrl = await promptOrDefault({
|
|
113
|
+
flag: options.publicUrl,
|
|
114
|
+
useDefaults,
|
|
115
|
+
defaultValue: "",
|
|
116
|
+
prompt: () => input({
|
|
117
|
+
message: "Public gateway URL? (leave empty for local dev, set for OAuth/webhooks)",
|
|
118
|
+
default: "",
|
|
119
|
+
}),
|
|
80
120
|
});
|
|
81
|
-
|
|
121
|
+
const networkPolicy = (await promptOrDefault({
|
|
122
|
+
flag: options.network,
|
|
123
|
+
useDefaults,
|
|
124
|
+
defaultValue: "restricted",
|
|
125
|
+
validate: (v) => NETWORK_CHOICES.includes(v)
|
|
126
|
+
? true
|
|
127
|
+
: `Must be one of: ${NETWORK_CHOICES.join(", ")}`,
|
|
128
|
+
prompt: () => select({
|
|
129
|
+
message: "Worker network access?",
|
|
130
|
+
choices: [
|
|
131
|
+
{
|
|
132
|
+
name: "Restricted (recommended) — common registries only (npm, GitHub, PyPI)",
|
|
133
|
+
value: "restricted",
|
|
134
|
+
},
|
|
135
|
+
{ name: "Open — workers can access any domain", value: "open" },
|
|
136
|
+
{
|
|
137
|
+
name: "Isolated — workers have no internet access",
|
|
138
|
+
value: "isolated",
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
default: "restricted",
|
|
142
|
+
}),
|
|
143
|
+
}));
|
|
82
144
|
const providerSkills = loadProviderRegistry();
|
|
83
145
|
const providerChoices = [
|
|
84
146
|
{ name: "Skip — I'll add a provider later", value: "" },
|
|
@@ -87,10 +149,21 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
87
149
|
value: s.id,
|
|
88
150
|
})),
|
|
89
151
|
];
|
|
90
|
-
const providerId = await
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
152
|
+
const providerId = await promptOrDefault({
|
|
153
|
+
flag: options.provider,
|
|
154
|
+
useDefaults,
|
|
155
|
+
defaultValue: "",
|
|
156
|
+
validate: (v) => v === "" || providerChoices.some((c) => c.value === v)
|
|
157
|
+
? true
|
|
158
|
+
: `Unknown provider "${v}". Available: ${providerChoices
|
|
159
|
+
.filter((c) => c.value)
|
|
160
|
+
.map((c) => c.value)
|
|
161
|
+
.join(", ")}`,
|
|
162
|
+
prompt: () => select({
|
|
163
|
+
message: "AI provider?",
|
|
164
|
+
choices: providerChoices,
|
|
165
|
+
default: "",
|
|
166
|
+
}),
|
|
94
167
|
});
|
|
95
168
|
let providerApiKey = "";
|
|
96
169
|
let selectedProvider;
|
|
@@ -98,15 +171,21 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
98
171
|
selectedProvider = getProviderById(providerId);
|
|
99
172
|
const p = selectedProvider?.providers?.[0];
|
|
100
173
|
if (p) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
174
|
+
if (options.providerKey) {
|
|
175
|
+
providerApiKey = options.providerKey;
|
|
176
|
+
}
|
|
177
|
+
else if (process.env[p.envVarName]) {
|
|
178
|
+
// Inherit from env so `--yes` can pick up keys set in the shell.
|
|
179
|
+
providerApiKey = process.env[p.envVarName] ?? "";
|
|
180
|
+
}
|
|
181
|
+
else if (!useDefaults) {
|
|
182
|
+
providerApiKey = await password({
|
|
183
|
+
message: `${p.displayName} API key:`,
|
|
184
|
+
mask: true,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
105
187
|
}
|
|
106
188
|
}
|
|
107
|
-
// Define skills locally via skills/<name>/SKILL.md or
|
|
108
|
-
// agents/<id>/skills/<name>/SKILL.md.
|
|
109
|
-
// Chat platform selection
|
|
110
189
|
const platformChoices = [
|
|
111
190
|
{ name: "Skip — I'll connect a platform later", value: "" },
|
|
112
191
|
{ name: "Telegram", value: "telegram" },
|
|
@@ -116,42 +195,72 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
116
195
|
{ name: "Microsoft Teams", value: "teams" },
|
|
117
196
|
{ name: "Google Chat", value: "gchat" },
|
|
118
197
|
];
|
|
119
|
-
const platformType = await
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
{ name: "None (filesystem memory)", value: "none" },
|
|
132
|
-
{ name: "Lobu Cloud (app.lobu.ai)", value: "owletto-cloud" },
|
|
133
|
-
{ name: "Custom Lobu memory URL", value: "owletto-custom" },
|
|
134
|
-
],
|
|
135
|
-
default: "none",
|
|
198
|
+
const platformType = await promptOrDefault({
|
|
199
|
+
flag: options.platform,
|
|
200
|
+
useDefaults,
|
|
201
|
+
defaultValue: "",
|
|
202
|
+
validate: (v) => v === "" || PLATFORM_CHOICES.includes(v)
|
|
203
|
+
? true
|
|
204
|
+
: `Unknown platform "${v}". Available: ${PLATFORM_CHOICES.join(", ")}`,
|
|
205
|
+
prompt: () => select({
|
|
206
|
+
message: "Connect a chat platform?",
|
|
207
|
+
choices: platformChoices,
|
|
208
|
+
default: "",
|
|
209
|
+
}),
|
|
136
210
|
});
|
|
211
|
+
// Interactive: prompt for real secrets. --yes: write placeholder env-var
|
|
212
|
+
// refs into lobu.toml; the user fills .env afterwards.
|
|
213
|
+
let platformConfig = {};
|
|
214
|
+
let platformSecrets = [];
|
|
215
|
+
if (platformType) {
|
|
216
|
+
if (useDefaults) {
|
|
217
|
+
platformConfig = PLATFORM_PLACEHOLDERS[platformType];
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
({ platformConfig, platformSecrets } =
|
|
221
|
+
await promptPlatformConfig(platformType));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const memoryChoice = (await promptOrDefault({
|
|
225
|
+
flag: options.memory,
|
|
226
|
+
useDefaults,
|
|
227
|
+
defaultValue: "none",
|
|
228
|
+
validate: (v) => MEMORY_CHOICES.includes(v)
|
|
229
|
+
? true
|
|
230
|
+
: `Must be one of: ${MEMORY_CHOICES.join(", ")}`,
|
|
231
|
+
prompt: () => select({
|
|
232
|
+
message: "Memory:",
|
|
233
|
+
choices: [
|
|
234
|
+
{ name: "None (filesystem memory)", value: "none" },
|
|
235
|
+
{ name: "Lobu Cloud (app.lobu.ai)", value: "lobu-cloud" },
|
|
236
|
+
{ name: "Custom Lobu memory URL", value: "lobu-custom" },
|
|
237
|
+
],
|
|
238
|
+
default: "none",
|
|
239
|
+
}),
|
|
240
|
+
}));
|
|
137
241
|
const envSecrets = [];
|
|
138
|
-
const
|
|
139
|
-
let
|
|
140
|
-
if (memoryChoice === "
|
|
141
|
-
|
|
242
|
+
const includeLobuMemory = memoryChoice !== "none";
|
|
243
|
+
let lobuUrl = "";
|
|
244
|
+
if (memoryChoice === "lobu-cloud") {
|
|
245
|
+
lobuUrl = DEFAULT_LOBU_MCP_URL;
|
|
142
246
|
}
|
|
143
|
-
else if (memoryChoice === "
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
247
|
+
else if (memoryChoice === "lobu-custom") {
|
|
248
|
+
lobuUrl =
|
|
249
|
+
options.memoryUrl ??
|
|
250
|
+
(await input({
|
|
251
|
+
message: "Lobu memory MCP URL:",
|
|
252
|
+
validate: (v) => (v ? true : "URL is required"),
|
|
253
|
+
}));
|
|
254
|
+
envSecrets.push({ envVar: "MEMORY_URL", value: lobuUrl });
|
|
149
255
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
256
|
+
const otelEndpoint = await promptOrDefault({
|
|
257
|
+
flag: options.otelEndpoint,
|
|
258
|
+
useDefaults,
|
|
259
|
+
defaultValue: "",
|
|
260
|
+
prompt: () => input({
|
|
261
|
+
message: "OpenTelemetry collector endpoint? (leave empty to disable tracing)",
|
|
262
|
+
default: "",
|
|
263
|
+
}),
|
|
155
264
|
});
|
|
156
265
|
if (otelEndpoint) {
|
|
157
266
|
envSecrets.push({
|
|
@@ -159,18 +268,25 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
159
268
|
value: otelEndpoint,
|
|
160
269
|
});
|
|
161
270
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
271
|
+
let enableSentry = false;
|
|
272
|
+
if (options.sentry === true) {
|
|
273
|
+
enableSentry = true;
|
|
274
|
+
}
|
|
275
|
+
else if (options.noSentry === true) {
|
|
276
|
+
enableSentry = false;
|
|
277
|
+
}
|
|
278
|
+
else if (!useDefaults) {
|
|
279
|
+
enableSentry = await confirm({
|
|
280
|
+
message: "Share anonymous error reports with Sentry to help improve Lobu?",
|
|
281
|
+
default: false,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
167
284
|
if (enableSentry) {
|
|
168
285
|
envSecrets.push({
|
|
169
286
|
envVar: "SENTRY_DSN",
|
|
170
287
|
value: "https://c5910e58d1a134d64ff93a95a9c535bb@o4507291398897664.ingest.us.sentry.io/4511097466781696",
|
|
171
288
|
});
|
|
172
289
|
}
|
|
173
|
-
// Compute network domains from selected policy
|
|
174
290
|
let allowedDomains;
|
|
175
291
|
let disallowedDomains;
|
|
176
292
|
if (networkPolicy === "open") {
|
|
@@ -182,7 +298,6 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
182
298
|
disallowedDomains = "";
|
|
183
299
|
}
|
|
184
300
|
else {
|
|
185
|
-
// restricted (default)
|
|
186
301
|
allowedDomains = [
|
|
187
302
|
"registry.npmjs.org",
|
|
188
303
|
".npmjs.org",
|
|
@@ -204,9 +319,8 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
204
319
|
};
|
|
205
320
|
const spinner = ora("Creating Lobu project...").start();
|
|
206
321
|
try {
|
|
207
|
-
// Create data directory in project directory
|
|
208
322
|
await mkdir(join(projectDir, "data"), { recursive: true });
|
|
209
|
-
if (
|
|
323
|
+
if (includeLobuMemory) {
|
|
210
324
|
await mkdir(join(projectDir, "models"), { recursive: true });
|
|
211
325
|
await mkdir(join(projectDir, "data", "entities"), { recursive: true });
|
|
212
326
|
await mkdir(join(projectDir, "data", "relationships"), {
|
|
@@ -216,7 +330,6 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
216
330
|
await writeFile(join(projectDir, "data", "entities", ".gitkeep"), "");
|
|
217
331
|
await writeFile(join(projectDir, "data", "relationships", ".gitkeep"), "");
|
|
218
332
|
}
|
|
219
|
-
// Generate lobu.toml
|
|
220
333
|
await generateLobuToml(projectDir, {
|
|
221
334
|
agentName: projectName,
|
|
222
335
|
allowedDomains: answers.allowedDomains,
|
|
@@ -225,9 +338,9 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
225
338
|
providerModel: selectedProvider?.providers?.[0]?.defaultModel,
|
|
226
339
|
platformType: platformType || undefined,
|
|
227
340
|
platformConfig: Object.keys(platformConfig).length > 0 ? platformConfig : undefined,
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
341
|
+
includeLobuMemory,
|
|
342
|
+
lobuOrg: includeLobuMemory ? projectName : undefined,
|
|
343
|
+
lobuName: includeLobuMemory ? humanizeSlug(projectName) : undefined,
|
|
231
344
|
});
|
|
232
345
|
const variables = {
|
|
233
346
|
PROJECT_NAME: projectName,
|
|
@@ -237,40 +350,68 @@ export async function initCommand(cwd = process.cwd(), projectNameArg) {
|
|
|
237
350
|
WORKER_ALLOWED_DOMAINS: answers.allowedDomains,
|
|
238
351
|
WORKER_DISALLOWED_DOMAINS: answers.disallowedDomains,
|
|
239
352
|
};
|
|
240
|
-
// Create .env file
|
|
241
353
|
await renderTemplate(".env.tmpl", variables, join(projectDir, ".env"));
|
|
242
|
-
|
|
354
|
+
const envVarsToFill = new Set();
|
|
355
|
+
if (selectedProvider?.providers?.[0]?.envVarName) {
|
|
356
|
+
envVarsToFill.add(selectedProvider.providers[0].envVarName);
|
|
357
|
+
}
|
|
358
|
+
for (const value of Object.values(platformConfig)) {
|
|
359
|
+
const envVar = extractEnvVarRef(value);
|
|
360
|
+
if (envVar)
|
|
361
|
+
envVarsToFill.add(envVar);
|
|
362
|
+
}
|
|
363
|
+
for (const envVar of envVarsToFill) {
|
|
364
|
+
await setLocalEnvValue(projectDir, envVar, "");
|
|
365
|
+
}
|
|
243
366
|
if (publicGatewayUrl) {
|
|
244
367
|
await setLocalEnvValue(projectDir, "PUBLIC_GATEWAY_URL", publicGatewayUrl);
|
|
245
368
|
}
|
|
246
|
-
// Save provider API key to .env
|
|
247
369
|
if (providerApiKey && selectedProvider?.providers?.[0]?.envVarName) {
|
|
248
370
|
await setLocalEnvValue(projectDir, selectedProvider.providers[0].envVarName, providerApiKey);
|
|
249
371
|
}
|
|
250
|
-
// Save platform secrets to .env
|
|
251
372
|
for (const secret of platformSecrets) {
|
|
252
373
|
await setLocalEnvValue(projectDir, secret.envVar, secret.value);
|
|
253
374
|
}
|
|
254
|
-
// Save OAuth secrets to .env
|
|
255
375
|
for (const secret of envSecrets) {
|
|
256
376
|
await setLocalEnvValue(projectDir, secret.envVar, secret.value);
|
|
257
377
|
}
|
|
258
|
-
// Create .gitignore
|
|
259
378
|
await renderTemplate(".gitignore.tmpl", {}, join(projectDir, ".gitignore"));
|
|
260
|
-
// Create README
|
|
261
379
|
await renderTemplate("README.md.tmpl", variables, join(projectDir, "README.md"));
|
|
262
|
-
// Create agent directory with instruction files
|
|
263
380
|
const agentDir = join(projectDir, "agents", projectName);
|
|
264
381
|
await mkdir(agentDir, { recursive: true });
|
|
265
382
|
await writeFile(join(agentDir, "IDENTITY.md"), `# Identity\n\nYou are ${projectName}, a helpful AI assistant.\n`);
|
|
266
383
|
await writeFile(join(agentDir, "SOUL.md"), `# Instructions\n\nBe concise and helpful. Ask clarifying questions when the request is ambiguous.\n`);
|
|
267
384
|
await writeFile(join(agentDir, "USER.md"), `# User Context\n\n<!-- Add user-specific preferences, timezone, environment details here -->\n`);
|
|
268
|
-
// Create agent-specific skills directory
|
|
269
385
|
await mkdir(join(agentDir, "skills"), { recursive: true });
|
|
270
386
|
await writeFile(join(agentDir, "skills", ".gitkeep"), "");
|
|
271
|
-
// Create evals directory with sample eval
|
|
272
387
|
await mkdir(join(agentDir, "evals"), { recursive: true });
|
|
273
|
-
await writeFile(join(agentDir, "evals", "ping.yaml"),
|
|
388
|
+
await writeFile(join(agentDir, "evals", "ping.yaml"), DEFAULT_EVAL_YAML);
|
|
389
|
+
await mkdir(join(projectDir, "skills"), { recursive: true });
|
|
390
|
+
await writeFile(join(projectDir, "skills", ".gitkeep"), "");
|
|
391
|
+
await renderTemplate("AGENTS.md.tmpl", variables, join(projectDir, "AGENTS.md"));
|
|
392
|
+
await renderTemplate("TESTING.md.tmpl", variables, join(projectDir, "TESTING.md"));
|
|
393
|
+
spinner.succeed("Project created successfully!");
|
|
394
|
+
const gatewayUrl = `http://localhost:${gatewayPort}`;
|
|
395
|
+
console.log(chalk.green("\n✓ Lobu initialized!\n"));
|
|
396
|
+
console.log(chalk.bold("Next steps:\n"));
|
|
397
|
+
let n = 1;
|
|
398
|
+
if (!here) {
|
|
399
|
+
console.log(chalk.cyan(` ${n++}. cd ${projectName}`));
|
|
400
|
+
}
|
|
401
|
+
console.log(chalk.cyan(` ${n++}. Start the local stack: lobu run (uses PGlite by default)`));
|
|
402
|
+
console.log(chalk.dim(" Optional: set DATABASE_URL in .env to use external Postgres instead."));
|
|
403
|
+
if (lobuUrl) {
|
|
404
|
+
console.log(chalk.cyan(` ${n++}. Wire memory clients: lobu memory init`));
|
|
405
|
+
}
|
|
406
|
+
console.log(chalk.cyan(` ${n++}. API docs: ${gatewayUrl}/api/docs`));
|
|
407
|
+
console.log(chalk.dim("\n See README.md for layout, AGENTS.md for the agent contract.\n"));
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
spinner.fail("Failed to create project");
|
|
411
|
+
throw error;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const DEFAULT_EVAL_YAML = `version: 1
|
|
274
415
|
name: ping
|
|
275
416
|
description: Agent responds to a simple greeting
|
|
276
417
|
trials: 3
|
|
@@ -287,53 +428,62 @@ turns:
|
|
|
287
428
|
- type: llm-rubric
|
|
288
429
|
value: "Response is friendly and acknowledges the greeting"
|
|
289
430
|
weight: 0.7
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
// Create AGENTS.md
|
|
295
|
-
await renderTemplate("AGENTS.md.tmpl", variables, join(projectDir, "AGENTS.md"));
|
|
296
|
-
// Create TESTING.md
|
|
297
|
-
await renderTemplate("TESTING.md.tmpl", variables, join(projectDir, "TESTING.md"));
|
|
298
|
-
spinner.succeed("Project created successfully!");
|
|
299
|
-
// Print next steps
|
|
300
|
-
console.log(chalk.green("\n✓ Lobu initialized!\n"));
|
|
301
|
-
console.log(chalk.bold("Next steps:\n"));
|
|
302
|
-
console.log(chalk.cyan(" 1. Navigate to your project:"));
|
|
303
|
-
console.log(chalk.dim(` cd ${projectName}\n`));
|
|
304
|
-
console.log(chalk.cyan(" 2. Review your configuration:"));
|
|
305
|
-
console.log(chalk.dim(" - lobu.toml (agents, providers, skills, network)"));
|
|
306
|
-
console.log(chalk.dim(` - agents/${projectName}/ (IDENTITY.md, SOUL.md, USER.md, skills/)`));
|
|
307
|
-
console.log(chalk.dim(" - skills/ (shared skills — all agents)"));
|
|
308
|
-
if (includeOwlettoMemory) {
|
|
309
|
-
console.log(chalk.dim(" - models/ (memory model files)"));
|
|
310
|
-
console.log(chalk.dim(" - data/ (memory seed data)"));
|
|
311
|
-
}
|
|
312
|
-
console.log(chalk.dim(" - .env (secrets)"));
|
|
313
|
-
console.log();
|
|
314
|
-
const gatewayUrl = `http://localhost:${gatewayPort}`;
|
|
315
|
-
console.log(chalk.cyan(" 3. Set DATABASE_URL in .env:"));
|
|
316
|
-
console.log(chalk.dim(" Lobu connects to a user-provided Postgres. Run one yourself"));
|
|
317
|
-
console.log(chalk.dim(" (managed instance or local: e.g. `brew services start postgresql`)\n"));
|
|
318
|
-
if (owlettoUrl) {
|
|
319
|
-
console.log(chalk.cyan(" Lobu memory:"));
|
|
320
|
-
console.log(chalk.dim(` ${owlettoUrl}`));
|
|
321
|
-
console.log(chalk.dim(" Run `lobu memory init` to configure local MCP clients.\n"));
|
|
322
|
-
}
|
|
323
|
-
console.log(chalk.cyan(" 4. Start the services:"));
|
|
324
|
-
console.log(chalk.dim(" npx @lobu/cli@latest run\n"));
|
|
325
|
-
console.log(chalk.cyan(" 5. Open the API docs:"));
|
|
326
|
-
console.log(chalk.dim(` ${gatewayUrl}/api/docs\n`));
|
|
327
|
-
console.log(chalk.cyan(" 6. Build with a coding agent:"));
|
|
328
|
-
console.log(chalk.dim(" Ask Codex or Claude Code to read AGENTS.md, lobu.toml, and agents/*/{IDENTITY,SOUL,USER}.md"));
|
|
329
|
-
console.log(chalk.dim(" Optional external skill: lobu-builder\n"));
|
|
330
|
-
console.log(chalk.cyan(" 7. Stop the services:"));
|
|
331
|
-
console.log(chalk.dim(" Ctrl+C in the terminal running `lobu run`\n"));
|
|
431
|
+
`;
|
|
432
|
+
function validateProjectName(value) {
|
|
433
|
+
if (!PROJECT_NAME_PATTERN.test(value)) {
|
|
434
|
+
return "Project name must be lowercase alphanumeric with hyphens only";
|
|
332
435
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
function slugify(s) {
|
|
439
|
+
return s
|
|
440
|
+
.toLowerCase()
|
|
441
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
442
|
+
.replace(/-+/g, "-")
|
|
443
|
+
.replace(/^-|-$/g, "");
|
|
444
|
+
}
|
|
445
|
+
async function promptOrDefault(opts) {
|
|
446
|
+
if (opts.flag !== undefined) {
|
|
447
|
+
if (opts.validate) {
|
|
448
|
+
const result = opts.validate(opts.flag);
|
|
449
|
+
if (result !== true) {
|
|
450
|
+
throw new Error(result);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return opts.flag;
|
|
336
454
|
}
|
|
455
|
+
if (opts.useDefaults)
|
|
456
|
+
return opts.defaultValue;
|
|
457
|
+
return opts.prompt();
|
|
458
|
+
}
|
|
459
|
+
// Placeholder env-var refs for `--yes` mode; the user fills the values into .env.
|
|
460
|
+
const PLATFORM_PLACEHOLDERS = {
|
|
461
|
+
telegram: { botToken: "$TELEGRAM_BOT_TOKEN" },
|
|
462
|
+
slack: {
|
|
463
|
+
botToken: "$SLACK_BOT_TOKEN",
|
|
464
|
+
signingSecret: "$SLACK_SIGNING_SECRET",
|
|
465
|
+
},
|
|
466
|
+
discord: {
|
|
467
|
+
botToken: "$DISCORD_BOT_TOKEN",
|
|
468
|
+
applicationId: "$DISCORD_APPLICATION_ID",
|
|
469
|
+
publicKey: "$DISCORD_PUBLIC_KEY",
|
|
470
|
+
},
|
|
471
|
+
whatsapp: {
|
|
472
|
+
accessToken: "$WHATSAPP_ACCESS_TOKEN",
|
|
473
|
+
phoneNumberId: "$WHATSAPP_PHONE_NUMBER_ID",
|
|
474
|
+
verifyToken: "$WHATSAPP_WEBHOOK_VERIFY_TOKEN",
|
|
475
|
+
appSecret: "$WHATSAPP_APP_SECRET",
|
|
476
|
+
},
|
|
477
|
+
teams: {
|
|
478
|
+
appId: "$TEAMS_APP_ID",
|
|
479
|
+
appPassword: "$TEAMS_APP_PASSWORD",
|
|
480
|
+
appType: "MultiTenant",
|
|
481
|
+
},
|
|
482
|
+
gchat: { credentials: "$GOOGLE_CHAT_CREDENTIALS" },
|
|
483
|
+
};
|
|
484
|
+
function extractEnvVarRef(value) {
|
|
485
|
+
const match = value.match(/^\$([A-Z_][A-Z0-9_]*)$/);
|
|
486
|
+
return match?.[1] ?? null;
|
|
337
487
|
}
|
|
338
488
|
function humanizeSlug(slug) {
|
|
339
489
|
return slug
|
|
@@ -363,7 +513,7 @@ export async function generateLobuToml(projectDir, options) {
|
|
|
363
513
|
lines.push(`[[agents.${id}.providers]]`, `id = "${options.providerId}"`, ...(options.providerModel ? [`model = "${options.providerModel}"`] : []), `key = "$${options.providerEnvVar}"`);
|
|
364
514
|
}
|
|
365
515
|
else {
|
|
366
|
-
lines.push("# Add providers via the gateway configuration APIs or uncomment below:", `# [[agents.${id}.providers]]`, '# id = "
|
|
516
|
+
lines.push("# Add providers via the gateway configuration APIs or uncomment below:", `# [[agents.${id}.providers]]`, '# id = "openrouter"', '# key = "$OPENROUTER_API_KEY"');
|
|
367
517
|
}
|
|
368
518
|
lines.push("");
|
|
369
519
|
if (options.platformType && options.platformConfig) {
|
|
@@ -377,7 +527,6 @@ export async function generateLobuToml(projectDir, options) {
|
|
|
377
527
|
lines.push("# Chat platform (add via the gateway configuration APIs or uncomment below):", `# [[agents.${id}.platforms]]`, '# type = "telegram"', `# [agents.${id}.platforms.config]`, '# botToken = "$TELEGRAM_BOT_TOKEN"');
|
|
378
528
|
}
|
|
379
529
|
lines.push("", "# Local skills live in skills/<name>/SKILL.md or agents/<id>/skills/<name>/SKILL.md", `[agents.${id}.skills]`, "", "# MCP servers (add custom tool servers with optional OAuth):", `# [agents.${id}.skills.mcp.my-mcp]`, '# url = "https://my-mcp.example.com"', `# [agents.${id}.skills.mcp.my-mcp.oauth]`, '# auth_url = "https://auth.example.com/authorize"', '# token_url = "https://auth.example.com/token"', '# client_id = "$MY_MCP_CLIENT_ID"');
|
|
380
|
-
// Network
|
|
381
530
|
lines.push("", `[agents.${id}.network]`);
|
|
382
531
|
if (options.allowedDomains) {
|
|
383
532
|
const domains = options.allowedDomains
|
|
@@ -389,14 +538,14 @@ export async function generateLobuToml(projectDir, options) {
|
|
|
389
538
|
else {
|
|
390
539
|
lines.push("allowed = []");
|
|
391
540
|
}
|
|
392
|
-
if (options.
|
|
393
|
-
const org = options.
|
|
394
|
-
const name = options.
|
|
395
|
-
lines.push("", "# Project-scoped Lobu memory", `[memory
|
|
396
|
-
? [`description = ${JSON.stringify(options.
|
|
541
|
+
if (options.includeLobuMemory) {
|
|
542
|
+
const org = options.lobuOrg ?? options.agentName;
|
|
543
|
+
const name = options.lobuName ?? humanizeSlug(options.agentName);
|
|
544
|
+
lines.push("", "# Project-scoped Lobu memory", `[memory]`, "enabled = true", `org = ${JSON.stringify(org)}`, `name = ${JSON.stringify(name)}`, ...(options.lobuDescription
|
|
545
|
+
? [`description = ${JSON.stringify(options.lobuDescription)}`]
|
|
397
546
|
: []), 'models = "./models"', 'data = "./data"');
|
|
398
547
|
}
|
|
399
|
-
lines.push("");
|
|
548
|
+
lines.push("");
|
|
400
549
|
await writeFile(join(projectDir, "lobu.toml"), lines.join("\n"));
|
|
401
550
|
}
|
|
402
551
|
async function getCliVersion() {
|