verybot 0.1.3
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.
Potentially problematic release.
This version of verybot might be problematic. Click here for more details.
- package/dist/brain/agent-registry.d.ts +75 -0
- package/dist/brain/agent-registry.js +124 -0
- package/dist/brain/agent.d.ts +146 -0
- package/dist/brain/agent.js +680 -0
- package/dist/brain/channel-store.d.ts +27 -0
- package/dist/brain/channel-store.js +78 -0
- package/dist/brain/compaction.d.ts +37 -0
- package/dist/brain/compaction.js +214 -0
- package/dist/brain/context.d.ts +33 -0
- package/dist/brain/context.js +77 -0
- package/dist/brain/delegation-store.d.ts +33 -0
- package/dist/brain/delegation-store.js +106 -0
- package/dist/brain/loop.d.ts +21 -0
- package/dist/brain/loop.js +161 -0
- package/dist/brain/mcp-adapter.d.ts +39 -0
- package/dist/brain/mcp-adapter.js +227 -0
- package/dist/brain/memory-extractor.d.ts +26 -0
- package/dist/brain/memory-extractor.js +82 -0
- package/dist/brain/providers.d.ts +10 -0
- package/dist/brain/providers.js +69 -0
- package/dist/brain/queue.d.ts +18 -0
- package/dist/brain/queue.js +84 -0
- package/dist/brain/run-tools.d.ts +47 -0
- package/dist/brain/run-tools.js +84 -0
- package/dist/brain/session-key.d.ts +23 -0
- package/dist/brain/session-key.js +41 -0
- package/dist/brain/session-state.d.ts +36 -0
- package/dist/brain/session-state.js +51 -0
- package/dist/brain/session-store.d.ts +50 -0
- package/dist/brain/session-store.js +207 -0
- package/dist/brain/session.d.ts +32 -0
- package/dist/brain/session.js +75 -0
- package/dist/brain/utils.d.ts +4 -0
- package/dist/brain/utils.js +26 -0
- package/dist/brain/worker-coordinator.d.ts +25 -0
- package/dist/brain/worker-coordinator.js +83 -0
- package/dist/channels/commands.d.ts +35 -0
- package/dist/channels/commands.js +65 -0
- package/dist/channels/discord/channel.d.ts +18 -0
- package/dist/channels/discord/channel.js +154 -0
- package/dist/channels/discord/markdown.d.ts +19 -0
- package/dist/channels/discord/markdown.js +62 -0
- package/dist/channels/manager.d.ts +29 -0
- package/dist/channels/manager.js +100 -0
- package/dist/channels/slack/channel.d.ts +26 -0
- package/dist/channels/slack/channel.js +207 -0
- package/dist/channels/slack/markdown.d.ts +19 -0
- package/dist/channels/slack/markdown.js +62 -0
- package/dist/channels/specs.d.ts +21 -0
- package/dist/channels/specs.js +96 -0
- package/dist/channels/telegram/channel.d.ts +18 -0
- package/dist/channels/telegram/channel.js +156 -0
- package/dist/channels/telegram/markdown.d.ts +17 -0
- package/dist/channels/telegram/markdown.js +66 -0
- package/dist/channels/types.d.ts +26 -0
- package/dist/channels/types.js +1 -0
- package/dist/channels/whatsapp/channel.d.ts +23 -0
- package/dist/channels/whatsapp/channel.js +242 -0
- package/dist/channels/whatsapp/markdown.d.ts +20 -0
- package/dist/channels/whatsapp/markdown.js +51 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.js +78 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +13 -0
- package/dist/computer/browser/actions.d.ts +31 -0
- package/dist/computer/browser/actions.js +148 -0
- package/dist/computer/browser/manager.d.ts +55 -0
- package/dist/computer/browser/manager.js +496 -0
- package/dist/computer/browser/profile-badge.d.ts +13 -0
- package/dist/computer/browser/profile-badge.js +67 -0
- package/dist/computer/browser/screenshot.d.ts +5 -0
- package/dist/computer/browser/screenshot.js +21 -0
- package/dist/computer/browser/snapshot.d.ts +30 -0
- package/dist/computer/browser/snapshot.js +242 -0
- package/dist/computer/browser/tools.d.ts +5 -0
- package/dist/computer/browser/tools.js +167 -0
- package/dist/computer/desktop/adapter.d.ts +25 -0
- package/dist/computer/desktop/adapter.js +11 -0
- package/dist/computer/desktop/macos.d.ts +24 -0
- package/dist/computer/desktop/macos.js +223 -0
- package/dist/computer/desktop/tools.d.ts +25 -0
- package/dist/computer/desktop/tools.js +114 -0
- package/dist/config/agent-config.d.ts +41 -0
- package/dist/config/agent-config.js +14 -0
- package/dist/config/model-catalog.d.ts +22 -0
- package/dist/config/model-catalog.js +99 -0
- package/dist/config/store.d.ts +25 -0
- package/dist/config/store.js +143 -0
- package/dist/config.d.ts +103 -0
- package/dist/config.js +224 -0
- package/dist/control-ui/assets/index-BANXNUyt.js +143 -0
- package/dist/control-ui/assets/index-BSUFrP9R.css +1 -0
- package/dist/control-ui/assets/noto-sans-cyrillic-ext-wght-normal-DSNfmdVt.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-cyrillic-wght-normal-B2hlT84T.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-devanagari-wght-normal-Cv-Vwajv.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-greek-ext-wght-normal-12T8GTDR.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-greek-wght-normal-Ymb6dZNd.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-latin-ext-wght-normal-W1qJv59z.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-latin-wght-normal-BYSzYMf3.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-vietnamese-wght-normal-DLTJy58D.woff2 +0 -0
- package/dist/control-ui/index.html +14 -0
- package/dist/control-ui/vite.svg +1 -0
- package/dist/events.d.ts +2 -0
- package/dist/events.js +11 -0
- package/dist/gateway/broadcast.d.ts +5 -0
- package/dist/gateway/broadcast.js +33 -0
- package/dist/gateway/methods/chat.d.ts +24 -0
- package/dist/gateway/methods/chat.js +19 -0
- package/dist/gateway/methods/config.d.ts +13 -0
- package/dist/gateway/methods/config.js +14 -0
- package/dist/gateway/methods/models.d.ts +10 -0
- package/dist/gateway/methods/models.js +14 -0
- package/dist/gateway/methods/prompt-templates.d.ts +23 -0
- package/dist/gateway/methods/prompt-templates.js +82 -0
- package/dist/gateway/methods/scheduler.d.ts +62 -0
- package/dist/gateway/methods/scheduler.js +129 -0
- package/dist/gateway/methods/sessions.d.ts +26 -0
- package/dist/gateway/methods/sessions.js +54 -0
- package/dist/gateway/methods/skills.d.ts +35 -0
- package/dist/gateway/methods/skills.js +202 -0
- package/dist/gateway/methods/system.d.ts +12 -0
- package/dist/gateway/methods/system.js +39 -0
- package/dist/gateway/methods/tasks.d.ts +21 -0
- package/dist/gateway/methods/tasks.js +46 -0
- package/dist/gateway/methods/teams.d.ts +70 -0
- package/dist/gateway/methods/teams.js +374 -0
- package/dist/gateway/methods/tools.d.ts +6 -0
- package/dist/gateway/methods/tools.js +7 -0
- package/dist/gateway/methods/whatsapp.d.ts +19 -0
- package/dist/gateway/methods/whatsapp.js +35 -0
- package/dist/gateway/rpc.d.ts +38 -0
- package/dist/gateway/rpc.js +75 -0
- package/dist/gateway/server.d.ts +4 -0
- package/dist/gateway/server.js +133 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +212 -0
- package/dist/integrations/github.d.ts +7 -0
- package/dist/integrations/github.js +133 -0
- package/dist/integrations/mcp.d.ts +7 -0
- package/dist/integrations/mcp.js +106 -0
- package/dist/integrations/registry.d.ts +43 -0
- package/dist/integrations/registry.js +258 -0
- package/dist/integrations/scanner.d.ts +10 -0
- package/dist/integrations/scanner.js +122 -0
- package/dist/integrations/twitter.d.ts +10 -0
- package/dist/integrations/twitter.js +120 -0
- package/dist/integrations/types.d.ts +72 -0
- package/dist/integrations/types.js +1 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.js +104 -0
- package/dist/markdown/chunk.d.ts +9 -0
- package/dist/markdown/chunk.js +52 -0
- package/dist/markdown/ir.d.ts +37 -0
- package/dist/markdown/ir.js +529 -0
- package/dist/markdown/render.d.ts +22 -0
- package/dist/markdown/render.js +148 -0
- package/dist/markdown/table-render.d.ts +43 -0
- package/dist/markdown/table-render.js +219 -0
- package/dist/markdown/tables.d.ts +17 -0
- package/dist/markdown/tables.js +27 -0
- package/dist/memory/embedding.d.ts +16 -0
- package/dist/memory/embedding.js +66 -0
- package/dist/memory/extractor.d.ts +6 -0
- package/dist/memory/extractor.js +72 -0
- package/dist/memory/search.d.ts +15 -0
- package/dist/memory/search.js +57 -0
- package/dist/memory/store.d.ts +34 -0
- package/dist/memory/store.js +328 -0
- package/dist/memory/types.d.ts +9 -0
- package/dist/memory/types.js +2 -0
- package/dist/paths.d.ts +20 -0
- package/dist/paths.js +29 -0
- package/dist/prompt-templates/builtins.d.ts +2 -0
- package/dist/prompt-templates/builtins.js +72 -0
- package/dist/prompt-templates/store.d.ts +39 -0
- package/dist/prompt-templates/store.js +174 -0
- package/dist/prompt-templates/types.d.ts +10 -0
- package/dist/prompt-templates/types.js +1 -0
- package/dist/scheduler/connected-channels.d.ts +24 -0
- package/dist/scheduler/connected-channels.js +57 -0
- package/dist/scheduler/scheduler.d.ts +22 -0
- package/dist/scheduler/scheduler.js +132 -0
- package/dist/scheduler/store.d.ts +27 -0
- package/dist/scheduler/store.js +205 -0
- package/dist/scheduler/types.d.ts +29 -0
- package/dist/scheduler/types.js +1 -0
- package/dist/security/command-validator.d.ts +22 -0
- package/dist/security/command-validator.js +160 -0
- package/dist/security/docker-sandbox.d.ts +48 -0
- package/dist/security/docker-sandbox.js +218 -0
- package/dist/security/env-filter.d.ts +8 -0
- package/dist/security/env-filter.js +41 -0
- package/dist/skills/loader.d.ts +33 -0
- package/dist/skills/loader.js +132 -0
- package/dist/skills/prompt.d.ts +6 -0
- package/dist/skills/prompt.js +17 -0
- package/dist/skills/read-tool.d.ts +7 -0
- package/dist/skills/read-tool.js +24 -0
- package/dist/skills/scanner.d.ts +6 -0
- package/dist/skills/scanner.js +73 -0
- package/dist/skills/types.d.ts +15 -0
- package/dist/skills/types.js +1 -0
- package/dist/tasks/store.d.ts +47 -0
- package/dist/tasks/store.js +193 -0
- package/dist/tasks/types.d.ts +75 -0
- package/dist/tasks/types.js +32 -0
- package/dist/teams/store.d.ts +78 -0
- package/dist/teams/store.js +420 -0
- package/dist/teams/types.d.ts +23 -0
- package/dist/teams/types.js +1 -0
- package/dist/tools/bash.d.ts +16 -0
- package/dist/tools/bash.js +62 -0
- package/dist/tools/channel-history.d.ts +10 -0
- package/dist/tools/channel-history.js +43 -0
- package/dist/tools/delegate.d.ts +16 -0
- package/dist/tools/delegate.js +216 -0
- package/dist/tools/fs.d.ts +4 -0
- package/dist/tools/fs.js +335 -0
- package/dist/tools/integration-toggle.d.ts +14 -0
- package/dist/tools/integration-toggle.js +47 -0
- package/dist/tools/memory.d.ts +13 -0
- package/dist/tools/memory.js +65 -0
- package/dist/tools/registry.d.ts +6 -0
- package/dist/tools/registry.js +9 -0
- package/dist/tools/schedule.d.ts +8 -0
- package/dist/tools/schedule.js +219 -0
- package/dist/tools/speak.d.ts +10 -0
- package/dist/tools/speak.js +56 -0
- package/dist/tools/tasks.d.ts +29 -0
- package/dist/tools/tasks.js +92 -0
- package/dist/tools/teams.d.ts +7 -0
- package/dist/tools/teams.js +180 -0
- package/dist/tools/web-fetch.d.ts +3 -0
- package/dist/tools/web-fetch.js +22 -0
- package/dist/tts/edge.d.ts +10 -0
- package/dist/tts/edge.js +60 -0
- package/dist/tts/speak.d.ts +12 -0
- package/dist/tts/speak.js +81 -0
- package/dist/tts/transcribe.d.ts +5 -0
- package/dist/tts/transcribe.js +40 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +22 -0
- package/package.json +90 -0
- package/verybot.js +2 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { logger } from "../logger.js";
|
|
6
|
+
/** Patterns that identify sensitive config keys by name. */
|
|
7
|
+
const SENSITIVE_PATTERNS = [/token/i, /password/i, /secret/i, /api.?key/i];
|
|
8
|
+
/** Check whether a config key name looks sensitive. */
|
|
9
|
+
function isSensitiveKey(key) {
|
|
10
|
+
return SENSITIVE_PATTERNS.some((p) => p.test(key));
|
|
11
|
+
}
|
|
12
|
+
/** Minimum chars to show prefix/suffix in redaction. */
|
|
13
|
+
const REDACT_MIN_LENGTH = 10;
|
|
14
|
+
const REDACT_PREFIX = 6;
|
|
15
|
+
const REDACT_SUFFIX = 4;
|
|
16
|
+
const REDACT_MARKER = "...";
|
|
17
|
+
/**
|
|
18
|
+
* Manages a single `config.json` file on disk.
|
|
19
|
+
* Handles reading, writing, patching, and redaction of secret values.
|
|
20
|
+
*/
|
|
21
|
+
export class ConfigStore {
|
|
22
|
+
filePath;
|
|
23
|
+
constructor(baseDir) {
|
|
24
|
+
this.filePath = join(baseDir, "config.json");
|
|
25
|
+
}
|
|
26
|
+
/** Read config from disk. Returns empty object if file doesn't exist. */
|
|
27
|
+
load() {
|
|
28
|
+
try {
|
|
29
|
+
if (!existsSync(this.filePath))
|
|
30
|
+
return {};
|
|
31
|
+
const raw = readFileSync(this.filePath, "utf-8");
|
|
32
|
+
return JSON.parse(raw);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
logger.warn(`Failed to read config.json: ${err instanceof Error ? err.message : err}`);
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Write full config to disk atomically (temp file → rename). */
|
|
40
|
+
save(data) {
|
|
41
|
+
const dir = dirname(this.filePath);
|
|
42
|
+
if (!existsSync(dir))
|
|
43
|
+
mkdirSync(dir, { recursive: true });
|
|
44
|
+
const tmp = join(tmpdir(), `config-${randomUUID()}.json`);
|
|
45
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
46
|
+
renameSync(tmp, this.filePath);
|
|
47
|
+
logger.info(`Config saved to ${this.filePath}`);
|
|
48
|
+
}
|
|
49
|
+
/** Deep-merge a partial update into the existing config and save. */
|
|
50
|
+
patch(partial) {
|
|
51
|
+
const existing = this.load();
|
|
52
|
+
const merged = deepMerge(existing, partial);
|
|
53
|
+
this.save(merged);
|
|
54
|
+
return merged;
|
|
55
|
+
}
|
|
56
|
+
/** Return config with secret values redacted. */
|
|
57
|
+
getRedacted() {
|
|
58
|
+
const data = this.load();
|
|
59
|
+
return redactSecrets(data);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Given an incoming config (possibly with redacted values from the UI),
|
|
63
|
+
* restore redacted secrets from the existing disk values before saving.
|
|
64
|
+
*/
|
|
65
|
+
patchFromUI(incoming) {
|
|
66
|
+
const existing = this.load();
|
|
67
|
+
const restored = restoreRedacted(incoming, existing);
|
|
68
|
+
return this.patch(restored);
|
|
69
|
+
}
|
|
70
|
+
/** Return file mtime in ms, or null if file doesn't exist. */
|
|
71
|
+
mtime() {
|
|
72
|
+
try {
|
|
73
|
+
return statSync(this.filePath).mtimeMs;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
getFilePath() {
|
|
80
|
+
return this.filePath;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Redact secret values in a config object. */
|
|
84
|
+
function redactSecrets(data) {
|
|
85
|
+
const result = { ...data };
|
|
86
|
+
for (const key of Object.keys(result)) {
|
|
87
|
+
if (isSensitiveKey(key) && typeof result[key] === "string") {
|
|
88
|
+
result[key] = redactValue(result[key]);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/** Mask a secret string: show prefix...suffix for long values, **** for short ones. */
|
|
94
|
+
function redactValue(value) {
|
|
95
|
+
if (!value)
|
|
96
|
+
return "";
|
|
97
|
+
if (value.length < REDACT_MIN_LENGTH)
|
|
98
|
+
return "****";
|
|
99
|
+
return (value.slice(0, REDACT_PREFIX) + REDACT_MARKER + value.slice(-REDACT_SUFFIX));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* If a value in `incoming` looks like it's still redacted (matches the pattern
|
|
103
|
+
* from `redactValue`), replace it with the original from `existing`.
|
|
104
|
+
*/
|
|
105
|
+
function restoreRedacted(incoming, existing) {
|
|
106
|
+
const result = { ...incoming };
|
|
107
|
+
for (const key of Object.keys(result)) {
|
|
108
|
+
if (!isSensitiveKey(key))
|
|
109
|
+
continue;
|
|
110
|
+
const inVal = result[key];
|
|
111
|
+
const exVal = existing[key];
|
|
112
|
+
if (typeof inVal !== "string" || typeof exVal !== "string")
|
|
113
|
+
continue;
|
|
114
|
+
// If the incoming value matches the redacted form of the existing value, keep existing
|
|
115
|
+
if (inVal === redactValue(exVal)) {
|
|
116
|
+
result[key] = exVal;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
/** Keys that should be replaced wholesale instead of deep-merged. */
|
|
122
|
+
const REPLACE_KEYS = new Set(["mcpServers"]);
|
|
123
|
+
/** Simple deep merge: objects are merged recursively, primitives/arrays are overwritten. */
|
|
124
|
+
function deepMerge(target, source) {
|
|
125
|
+
const result = { ...target };
|
|
126
|
+
for (const [key, val] of Object.entries(source)) {
|
|
127
|
+
if (REPLACE_KEYS.has(key)) {
|
|
128
|
+
result[key] = val;
|
|
129
|
+
}
|
|
130
|
+
else if (val !== null &&
|
|
131
|
+
typeof val === "object" &&
|
|
132
|
+
!Array.isArray(val) &&
|
|
133
|
+
typeof result[key] === "object" &&
|
|
134
|
+
result[key] !== null &&
|
|
135
|
+
!Array.isArray(result[key])) {
|
|
136
|
+
result[key] = deepMerge(result[key], val);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
result[key] = val;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { ConfigStore } from "./config/store.js";
|
|
2
|
+
import type { MarkdownTableMode } from "./markdown/ir.js";
|
|
3
|
+
export type BashSecurityMode = "deny" | "allowlist" | "full";
|
|
4
|
+
export interface BashConfig {
|
|
5
|
+
security: BashSecurityMode;
|
|
6
|
+
safeBins: string[];
|
|
7
|
+
allowlist: string[];
|
|
8
|
+
}
|
|
9
|
+
interface SandboxConfig {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
image: string;
|
|
12
|
+
memoryLimit: string;
|
|
13
|
+
pidsLimit: number;
|
|
14
|
+
idleTimeoutMs: number;
|
|
15
|
+
}
|
|
16
|
+
interface DesktopConfig {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface McpServerConfig {
|
|
20
|
+
/** Command to spawn (stdio transport — inferred when present). */
|
|
21
|
+
command?: string;
|
|
22
|
+
/** Arguments for the command (stdio only). */
|
|
23
|
+
args?: string[];
|
|
24
|
+
/** Extra environment variables for the subprocess (stdio only). */
|
|
25
|
+
env?: Record<string, string>;
|
|
26
|
+
/** Server URL (SSE transport — inferred when present). */
|
|
27
|
+
url?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface Config {
|
|
30
|
+
gateway: {
|
|
31
|
+
port: number;
|
|
32
|
+
token: string;
|
|
33
|
+
};
|
|
34
|
+
model: {
|
|
35
|
+
provider: string;
|
|
36
|
+
id: string;
|
|
37
|
+
maxSteps: number;
|
|
38
|
+
contextWindow: number;
|
|
39
|
+
};
|
|
40
|
+
browserHeadless: boolean;
|
|
41
|
+
browserUserAgent: string;
|
|
42
|
+
language: string;
|
|
43
|
+
identity: string;
|
|
44
|
+
bash: BashConfig;
|
|
45
|
+
sandbox: SandboxConfig;
|
|
46
|
+
desktop: DesktopConfig;
|
|
47
|
+
memory: {
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
maxResults: number;
|
|
50
|
+
};
|
|
51
|
+
channels: {
|
|
52
|
+
telegram?: {
|
|
53
|
+
token: string;
|
|
54
|
+
markdown?: {
|
|
55
|
+
tables?: MarkdownTableMode;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
discord?: {
|
|
59
|
+
token: string;
|
|
60
|
+
markdown?: {
|
|
61
|
+
tables?: MarkdownTableMode;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
slack?: {
|
|
65
|
+
botToken: string;
|
|
66
|
+
appToken: string;
|
|
67
|
+
markdown?: {
|
|
68
|
+
tables?: MarkdownTableMode;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
whatsapp?: {
|
|
72
|
+
phoneId: string;
|
|
73
|
+
selfOnly?: boolean;
|
|
74
|
+
markdown?: {
|
|
75
|
+
tables?: MarkdownTableMode;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
mcpServers: Record<string, McpServerConfig>;
|
|
80
|
+
tts: {
|
|
81
|
+
enabled: boolean;
|
|
82
|
+
voice: string;
|
|
83
|
+
replyMode: "text" | "voice" | "inbound";
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Inject API keys from config.json into process.env so AI SDK providers work.
|
|
88
|
+
* Only sets values that are non-empty and not already set in the environment.
|
|
89
|
+
*/
|
|
90
|
+
export declare function injectSecretsIntoEnv(store: ConfigStore): void;
|
|
91
|
+
/** Generate a cryptographically random gateway token (URL-safe base64, 32 bytes). */
|
|
92
|
+
export declare function generateGatewayToken(): string;
|
|
93
|
+
/**
|
|
94
|
+
* Create initial config.json with all configurable keys and defaults.
|
|
95
|
+
* Only runs when config.json doesn't exist yet.
|
|
96
|
+
*/
|
|
97
|
+
export declare function seedConfigStore(store: ConfigStore): void;
|
|
98
|
+
/**
|
|
99
|
+
* Load config exclusively from config.json (via ConfigStore).
|
|
100
|
+
* No .env fallbacks — config.json is the sole source of truth.
|
|
101
|
+
*/
|
|
102
|
+
export declare function loadConfig(store: ConfigStore): Config;
|
|
103
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
function parseModel(raw) {
|
|
4
|
+
const [provider, ...rest] = raw.split(":");
|
|
5
|
+
return { provider, id: rest.join(":") };
|
|
6
|
+
}
|
|
7
|
+
function parseMcpServers(raw) {
|
|
8
|
+
if (!raw)
|
|
9
|
+
return {};
|
|
10
|
+
if (typeof raw === "object" && !Array.isArray(raw))
|
|
11
|
+
return raw;
|
|
12
|
+
if (typeof raw === "string") {
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(raw);
|
|
15
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
16
|
+
return parsed;
|
|
17
|
+
}
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
/** Safely read a nested value with a fallback. */
|
|
27
|
+
function get(val, fallback) {
|
|
28
|
+
return val !== undefined && val !== null ? val : fallback;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Secrets in config.json that must be injected into process.env
|
|
32
|
+
* so AI SDKs can find them. Key = config field, value = env var name.
|
|
33
|
+
*/
|
|
34
|
+
const ENV_SECRET_MAP = {
|
|
35
|
+
ANTHROPIC_API_KEY: "ANTHROPIC_API_KEY",
|
|
36
|
+
OPENAI_API_KEY: "OPENAI_API_KEY",
|
|
37
|
+
GOOGLE_GENERATIVE_AI_API_KEY: "GOOGLE_GENERATIVE_AI_API_KEY",
|
|
38
|
+
XAI_API_KEY: "XAI_API_KEY",
|
|
39
|
+
MISTRAL_API_KEY: "MISTRAL_API_KEY",
|
|
40
|
+
GROQ_API_KEY: "GROQ_API_KEY",
|
|
41
|
+
TOGETHER_AI_API_KEY: "TOGETHER_AI_API_KEY",
|
|
42
|
+
DEEPSEEK_API_KEY: "DEEPSEEK_API_KEY",
|
|
43
|
+
OPENROUTER_API_KEY: "OPENROUTER_API_KEY",
|
|
44
|
+
OLLAMA_BASE_URL: "OLLAMA_BASE_URL",
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Inject API keys from config.json into process.env so AI SDK providers work.
|
|
48
|
+
* Only sets values that are non-empty and not already set in the environment.
|
|
49
|
+
*/
|
|
50
|
+
export function injectSecretsIntoEnv(store) {
|
|
51
|
+
const data = store.load();
|
|
52
|
+
for (const [configKey, envKey] of Object.entries(ENV_SECRET_MAP)) {
|
|
53
|
+
const val = data[configKey];
|
|
54
|
+
if (typeof val === "string" && val) {
|
|
55
|
+
process.env[envKey] = val;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const GATEWAY_TOKEN_BYTES = 32;
|
|
60
|
+
/** Generate a cryptographically random gateway token (URL-safe base64, 32 bytes). */
|
|
61
|
+
export function generateGatewayToken() {
|
|
62
|
+
return randomBytes(GATEWAY_TOKEN_BYTES).toString("base64url");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create initial config.json with all configurable keys and defaults.
|
|
66
|
+
* Only runs when config.json doesn't exist yet.
|
|
67
|
+
*/
|
|
68
|
+
export function seedConfigStore(store) {
|
|
69
|
+
const existing = store.load();
|
|
70
|
+
if (Object.keys(existing).length > 0)
|
|
71
|
+
return;
|
|
72
|
+
const seed = {
|
|
73
|
+
// Model
|
|
74
|
+
model: "anthropic:claude-sonnet-4-5-20250929",
|
|
75
|
+
maxSteps: 20,
|
|
76
|
+
browserHeadless: true,
|
|
77
|
+
browserUserAgent: "",
|
|
78
|
+
// Agent
|
|
79
|
+
language: "auto",
|
|
80
|
+
identity: "You are a helpful personal assistant.",
|
|
81
|
+
// Gateway
|
|
82
|
+
gateway: { port: 28789 },
|
|
83
|
+
// Bash
|
|
84
|
+
bash: { security: "full", safeBins: [], allowlist: [] },
|
|
85
|
+
// Sandbox
|
|
86
|
+
sandbox: {
|
|
87
|
+
enabled: false,
|
|
88
|
+
image: "ubuntu:24.04",
|
|
89
|
+
memoryLimit: "256m",
|
|
90
|
+
pidsLimit: 64,
|
|
91
|
+
idleTimeoutMs: 300_000,
|
|
92
|
+
},
|
|
93
|
+
// Desktop
|
|
94
|
+
desktop: { enabled: false },
|
|
95
|
+
// Memory
|
|
96
|
+
memory: { enabled: true, maxResults: 5 },
|
|
97
|
+
// TTS
|
|
98
|
+
tts: { enabled: true, voice: "en-US-AriaNeural", replyMode: "inbound" },
|
|
99
|
+
// MCP servers
|
|
100
|
+
mcpServers: {},
|
|
101
|
+
// Secrets (empty — set via web UI)
|
|
102
|
+
ANTHROPIC_API_KEY: "",
|
|
103
|
+
OPENAI_API_KEY: "",
|
|
104
|
+
GOOGLE_GENERATIVE_AI_API_KEY: "",
|
|
105
|
+
XAI_API_KEY: "",
|
|
106
|
+
MISTRAL_API_KEY: "",
|
|
107
|
+
GROQ_API_KEY: "",
|
|
108
|
+
TOGETHER_AI_API_KEY: "",
|
|
109
|
+
DEEPSEEK_API_KEY: "",
|
|
110
|
+
OPENROUTER_API_KEY: "",
|
|
111
|
+
OLLAMA_BASE_URL: "",
|
|
112
|
+
GATEWAY_TOKEN: generateGatewayToken(),
|
|
113
|
+
TELEGRAM_BOT_TOKEN: "",
|
|
114
|
+
DISCORD_BOT_TOKEN: "",
|
|
115
|
+
SLACK_BOT_TOKEN: "",
|
|
116
|
+
SLACK_APP_TOKEN: "",
|
|
117
|
+
WHATSAPP_PHONE_ID: "",
|
|
118
|
+
TWITTER_BEARER_TOKEN: "",
|
|
119
|
+
TWITTER_API_KEY: "",
|
|
120
|
+
TWITTER_API_SECRET: "",
|
|
121
|
+
TWITTER_ACCESS_TOKEN: "",
|
|
122
|
+
TWITTER_ACCESS_SECRET: "",
|
|
123
|
+
GITHUB_TOKEN: "",
|
|
124
|
+
GITHUB_DEFAULT_OWNER: "",
|
|
125
|
+
};
|
|
126
|
+
store.save(seed);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Load config exclusively from config.json (via ConfigStore).
|
|
130
|
+
* No .env fallbacks — config.json is the sole source of truth.
|
|
131
|
+
*/
|
|
132
|
+
export function loadConfig(store) {
|
|
133
|
+
const s = store.load();
|
|
134
|
+
const modelRaw = get(s.model, "anthropic:claude-sonnet-4-5-20250929");
|
|
135
|
+
const gateway = (s.gateway ?? {});
|
|
136
|
+
const bash = (s.bash ?? {});
|
|
137
|
+
const sandbox = (s.sandbox ?? {});
|
|
138
|
+
const memory = (s.memory ?? {});
|
|
139
|
+
const tts = (s.tts ?? {});
|
|
140
|
+
const legacyMcp = s.mcp ?? {};
|
|
141
|
+
const identityStr = get(s.identity, "You are a helpful personal assistant.");
|
|
142
|
+
const telegramToken = get(s.TELEGRAM_BOT_TOKEN, "");
|
|
143
|
+
const discordToken = get(s.DISCORD_BOT_TOKEN, "");
|
|
144
|
+
const slackBotToken = get(s.SLACK_BOT_TOKEN, "");
|
|
145
|
+
const slackAppToken = get(s.SLACK_APP_TOKEN, "");
|
|
146
|
+
const whatsappPhoneId = get(s.WHATSAPP_PHONE_ID, "");
|
|
147
|
+
const channelsCfg = (s.channels ?? {});
|
|
148
|
+
// Auto-generate a gateway token if missing or empty
|
|
149
|
+
let gatewayToken = s.GATEWAY_TOKEN || "";
|
|
150
|
+
if (!gatewayToken) {
|
|
151
|
+
gatewayToken = generateGatewayToken();
|
|
152
|
+
store.patch({ GATEWAY_TOKEN: gatewayToken });
|
|
153
|
+
logger.info(`Generated new \x1b[36mGATEWAY_TOKEN\x1b[0m: \x1b[1m\x1b[33m${gatewayToken}\x1b[0m`);
|
|
154
|
+
}
|
|
155
|
+
logger.info(`\x1b[36mGATEWAY_TOKEN\x1b[0m: \x1b[1m\x1b[33m${gatewayToken}\x1b[0m`);
|
|
156
|
+
return {
|
|
157
|
+
gateway: {
|
|
158
|
+
port: Number(get(gateway.port, 28789)),
|
|
159
|
+
token: gatewayToken,
|
|
160
|
+
},
|
|
161
|
+
model: {
|
|
162
|
+
...parseModel(modelRaw),
|
|
163
|
+
maxSteps: Number(get(s.maxSteps, 20)),
|
|
164
|
+
contextWindow: Number(get(s.contextWindow, 0)),
|
|
165
|
+
},
|
|
166
|
+
browserHeadless: get(s.browserHeadless, true),
|
|
167
|
+
browserUserAgent: get(s.browserUserAgent, ""),
|
|
168
|
+
language: get(s.language, "auto"),
|
|
169
|
+
identity: identityStr,
|
|
170
|
+
bash: {
|
|
171
|
+
security: get(bash.security, "full"),
|
|
172
|
+
safeBins: get(bash.safeBins, []),
|
|
173
|
+
allowlist: get(bash.allowlist, []),
|
|
174
|
+
},
|
|
175
|
+
sandbox: {
|
|
176
|
+
enabled: get(sandbox.enabled, false),
|
|
177
|
+
image: get(sandbox.image, "ubuntu:24.04"),
|
|
178
|
+
memoryLimit: get(sandbox.memoryLimit, "256m"),
|
|
179
|
+
pidsLimit: Number(get(sandbox.pidsLimit, 64)),
|
|
180
|
+
idleTimeoutMs: Number(get(sandbox.idleTimeoutMs, 300_000)),
|
|
181
|
+
},
|
|
182
|
+
desktop: {
|
|
183
|
+
enabled: get(s.desktop?.enabled, false),
|
|
184
|
+
},
|
|
185
|
+
memory: {
|
|
186
|
+
enabled: get(memory.enabled, true),
|
|
187
|
+
maxResults: Number(get(memory.maxResults, 5)),
|
|
188
|
+
},
|
|
189
|
+
channels: {
|
|
190
|
+
telegram: telegramToken
|
|
191
|
+
? {
|
|
192
|
+
token: telegramToken,
|
|
193
|
+
markdown: channelsCfg.telegram?.markdown ?? undefined,
|
|
194
|
+
}
|
|
195
|
+
: undefined,
|
|
196
|
+
discord: discordToken
|
|
197
|
+
? {
|
|
198
|
+
token: discordToken,
|
|
199
|
+
markdown: channelsCfg.discord?.markdown ?? undefined,
|
|
200
|
+
}
|
|
201
|
+
: undefined,
|
|
202
|
+
slack: slackBotToken && slackAppToken
|
|
203
|
+
? {
|
|
204
|
+
botToken: slackBotToken,
|
|
205
|
+
appToken: slackAppToken,
|
|
206
|
+
markdown: channelsCfg.slack?.markdown ?? undefined,
|
|
207
|
+
}
|
|
208
|
+
: undefined,
|
|
209
|
+
whatsapp: whatsappPhoneId
|
|
210
|
+
? {
|
|
211
|
+
phoneId: whatsappPhoneId,
|
|
212
|
+
selfOnly: get(channelsCfg.whatsapp?.selfOnly, false),
|
|
213
|
+
markdown: channelsCfg.whatsapp?.markdown ?? undefined,
|
|
214
|
+
}
|
|
215
|
+
: undefined,
|
|
216
|
+
},
|
|
217
|
+
mcpServers: parseMcpServers(s.mcpServers ?? legacyMcp.servers),
|
|
218
|
+
tts: {
|
|
219
|
+
enabled: get(tts.enabled, true),
|
|
220
|
+
voice: get(tts.voice, "en-US-AriaNeural"),
|
|
221
|
+
replyMode: get(tts.replyMode, "inbound"),
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|