clementine-agent 1.0.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/.env.example +44 -0
- package/LICENSE +21 -0
- package/README.md +795 -0
- package/dist/agent/agent-manager.d.ts +69 -0
- package/dist/agent/agent-manager.js +441 -0
- package/dist/agent/assistant.d.ts +225 -0
- package/dist/agent/assistant.js +3888 -0
- package/dist/agent/auto-update.d.ts +32 -0
- package/dist/agent/auto-update.js +186 -0
- package/dist/agent/daily-planner.d.ts +24 -0
- package/dist/agent/daily-planner.js +379 -0
- package/dist/agent/execution-advisor.d.ts +10 -0
- package/dist/agent/execution-advisor.js +272 -0
- package/dist/agent/hooks.d.ts +45 -0
- package/dist/agent/hooks.js +564 -0
- package/dist/agent/insight-engine.d.ts +66 -0
- package/dist/agent/insight-engine.js +225 -0
- package/dist/agent/intent-classifier.d.ts +48 -0
- package/dist/agent/intent-classifier.js +214 -0
- package/dist/agent/link-extractor.d.ts +19 -0
- package/dist/agent/link-extractor.js +90 -0
- package/dist/agent/mcp-bridge.d.ts +62 -0
- package/dist/agent/mcp-bridge.js +435 -0
- package/dist/agent/metacognition.d.ts +66 -0
- package/dist/agent/metacognition.js +221 -0
- package/dist/agent/orchestrator.d.ts +81 -0
- package/dist/agent/orchestrator.js +790 -0
- package/dist/agent/profiles.d.ts +22 -0
- package/dist/agent/profiles.js +91 -0
- package/dist/agent/prompt-cache.d.ts +24 -0
- package/dist/agent/prompt-cache.js +68 -0
- package/dist/agent/prompt-evolver.d.ts +28 -0
- package/dist/agent/prompt-evolver.js +279 -0
- package/dist/agent/role-scaffolds.d.ts +28 -0
- package/dist/agent/role-scaffolds.js +433 -0
- package/dist/agent/safe-restart.d.ts +41 -0
- package/dist/agent/safe-restart.js +150 -0
- package/dist/agent/self-improve.d.ts +66 -0
- package/dist/agent/self-improve.js +1706 -0
- package/dist/agent/session-event-log.d.ts +114 -0
- package/dist/agent/session-event-log.js +233 -0
- package/dist/agent/skill-extractor.d.ts +72 -0
- package/dist/agent/skill-extractor.js +435 -0
- package/dist/agent/source-mods.d.ts +61 -0
- package/dist/agent/source-mods.js +230 -0
- package/dist/agent/source-preflight.d.ts +25 -0
- package/dist/agent/source-preflight.js +100 -0
- package/dist/agent/stall-guard.d.ts +62 -0
- package/dist/agent/stall-guard.js +109 -0
- package/dist/agent/strategic-planner.d.ts +60 -0
- package/dist/agent/strategic-planner.js +352 -0
- package/dist/agent/team-bus.d.ts +89 -0
- package/dist/agent/team-bus.js +556 -0
- package/dist/agent/team-router.d.ts +26 -0
- package/dist/agent/team-router.js +37 -0
- package/dist/agent/tool-loop-detector.d.ts +59 -0
- package/dist/agent/tool-loop-detector.js +242 -0
- package/dist/agent/workflow-runner.d.ts +36 -0
- package/dist/agent/workflow-runner.js +317 -0
- package/dist/agent/workflow-variables.d.ts +16 -0
- package/dist/agent/workflow-variables.js +62 -0
- package/dist/channels/discord-agent-bot.d.ts +101 -0
- package/dist/channels/discord-agent-bot.js +881 -0
- package/dist/channels/discord-bot-manager.d.ts +80 -0
- package/dist/channels/discord-bot-manager.js +262 -0
- package/dist/channels/discord-utils.d.ts +51 -0
- package/dist/channels/discord-utils.js +293 -0
- package/dist/channels/discord.d.ts +12 -0
- package/dist/channels/discord.js +1832 -0
- package/dist/channels/slack-agent-bot.d.ts +73 -0
- package/dist/channels/slack-agent-bot.js +320 -0
- package/dist/channels/slack-bot-manager.d.ts +66 -0
- package/dist/channels/slack-bot-manager.js +236 -0
- package/dist/channels/slack-utils.d.ts +39 -0
- package/dist/channels/slack-utils.js +189 -0
- package/dist/channels/slack.d.ts +11 -0
- package/dist/channels/slack.js +196 -0
- package/dist/channels/telegram.d.ts +10 -0
- package/dist/channels/telegram.js +235 -0
- package/dist/channels/webhook.d.ts +9 -0
- package/dist/channels/webhook.js +78 -0
- package/dist/channels/whatsapp.d.ts +11 -0
- package/dist/channels/whatsapp.js +181 -0
- package/dist/cli/chat.d.ts +14 -0
- package/dist/cli/chat.js +220 -0
- package/dist/cli/cron.d.ts +17 -0
- package/dist/cli/cron.js +552 -0
- package/dist/cli/dashboard.d.ts +15 -0
- package/dist/cli/dashboard.js +17677 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +2474 -0
- package/dist/cli/routes/delegations.d.ts +19 -0
- package/dist/cli/routes/delegations.js +154 -0
- package/dist/cli/routes/digest.d.ts +17 -0
- package/dist/cli/routes/digest.js +375 -0
- package/dist/cli/routes/goals.d.ts +14 -0
- package/dist/cli/routes/goals.js +258 -0
- package/dist/cli/routes/workflows.d.ts +18 -0
- package/dist/cli/routes/workflows.js +97 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +619 -0
- package/dist/cli/tunnel.d.ts +35 -0
- package/dist/cli/tunnel.js +141 -0
- package/dist/config.d.ts +145 -0
- package/dist/config.js +278 -0
- package/dist/events/bus.d.ts +43 -0
- package/dist/events/bus.js +136 -0
- package/dist/gateway/cron-scheduler.d.ts +166 -0
- package/dist/gateway/cron-scheduler.js +1767 -0
- package/dist/gateway/delivery-queue.d.ts +30 -0
- package/dist/gateway/delivery-queue.js +110 -0
- package/dist/gateway/heartbeat-scheduler.d.ts +99 -0
- package/dist/gateway/heartbeat-scheduler.js +1298 -0
- package/dist/gateway/heartbeat.d.ts +3 -0
- package/dist/gateway/heartbeat.js +3 -0
- package/dist/gateway/lanes.d.ts +24 -0
- package/dist/gateway/lanes.js +76 -0
- package/dist/gateway/notifications.d.ts +29 -0
- package/dist/gateway/notifications.js +75 -0
- package/dist/gateway/router.d.ts +210 -0
- package/dist/gateway/router.js +1330 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1015 -0
- package/dist/memory/chunker.d.ts +28 -0
- package/dist/memory/chunker.js +226 -0
- package/dist/memory/consolidation.d.ts +44 -0
- package/dist/memory/consolidation.js +171 -0
- package/dist/memory/context-assembler.d.ts +50 -0
- package/dist/memory/context-assembler.js +149 -0
- package/dist/memory/embeddings.d.ts +38 -0
- package/dist/memory/embeddings.js +180 -0
- package/dist/memory/graph-store.d.ts +66 -0
- package/dist/memory/graph-store.js +613 -0
- package/dist/memory/mmr.d.ts +21 -0
- package/dist/memory/mmr.js +75 -0
- package/dist/memory/search.d.ts +26 -0
- package/dist/memory/search.js +67 -0
- package/dist/memory/store.d.ts +530 -0
- package/dist/memory/store.js +2022 -0
- package/dist/security/integrity.d.ts +24 -0
- package/dist/security/integrity.js +58 -0
- package/dist/security/patterns.d.ts +34 -0
- package/dist/security/patterns.js +110 -0
- package/dist/security/scanner.d.ts +32 -0
- package/dist/security/scanner.js +263 -0
- package/dist/tools/admin-tools.d.ts +12 -0
- package/dist/tools/admin-tools.js +1278 -0
- package/dist/tools/external-tools.d.ts +11 -0
- package/dist/tools/external-tools.js +1327 -0
- package/dist/tools/goal-tools.d.ts +9 -0
- package/dist/tools/goal-tools.js +159 -0
- package/dist/tools/mcp-server.d.ts +13 -0
- package/dist/tools/mcp-server.js +141 -0
- package/dist/tools/memory-tools.d.ts +10 -0
- package/dist/tools/memory-tools.js +568 -0
- package/dist/tools/session-tools.d.ts +6 -0
- package/dist/tools/session-tools.js +146 -0
- package/dist/tools/shared.d.ts +216 -0
- package/dist/tools/shared.js +340 -0
- package/dist/tools/team-tools.d.ts +6 -0
- package/dist/tools/team-tools.js +447 -0
- package/dist/tools/tool-meta.d.ts +34 -0
- package/dist/tools/tool-meta.js +133 -0
- package/dist/tools/vault-tools.d.ts +8 -0
- package/dist/tools/vault-tools.js +457 -0
- package/dist/types.d.ts +716 -0
- package/dist/types.js +16 -0
- package/dist/vault-migrations/0001-add-execution-framework.d.ts +10 -0
- package/dist/vault-migrations/0001-add-execution-framework.js +47 -0
- package/dist/vault-migrations/0002-add-agentic-communication.d.ts +12 -0
- package/dist/vault-migrations/0002-add-agentic-communication.js +79 -0
- package/dist/vault-migrations/0003-update-execution-pipeline-narration.d.ts +11 -0
- package/dist/vault-migrations/0003-update-execution-pipeline-narration.js +73 -0
- package/dist/vault-migrations/helpers.d.ts +14 -0
- package/dist/vault-migrations/helpers.js +44 -0
- package/dist/vault-migrations/runner.d.ts +14 -0
- package/dist/vault-migrations/runner.js +139 -0
- package/dist/vault-migrations/types.d.ts +42 -0
- package/dist/vault-migrations/types.js +9 -0
- package/install.sh +320 -0
- package/package.json +84 -0
- package/scripts/postinstall.js +125 -0
- package/vault/00-System/AGENTS.md +66 -0
- package/vault/00-System/CRON.md +71 -0
- package/vault/00-System/HEARTBEAT.md +58 -0
- package/vault/00-System/MEMORY.md +16 -0
- package/vault/00-System/SOUL.md +96 -0
- package/vault/05-Tasks/TASKS.md +19 -0
- package/vault/06-Templates/_Daily-Template.md +28 -0
- package/vault/06-Templates/_People-Template.md +22 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Cloudflare Tunnel Manager.
|
|
3
|
+
*
|
|
4
|
+
* Manages a cloudflared quick tunnel to expose the dashboard remotely.
|
|
5
|
+
* No Cloudflare account required — uses free quick tunnels that generate
|
|
6
|
+
* a random *.trycloudflare.com URL.
|
|
7
|
+
*
|
|
8
|
+
* Security: The tunnel only points at localhost. Combined with the
|
|
9
|
+
* dashboard's session-cookie auth, remote users must know the access
|
|
10
|
+
* token before they can see anything.
|
|
11
|
+
*/
|
|
12
|
+
import { spawn, execSync } from 'node:child_process';
|
|
13
|
+
import { EventEmitter } from 'node:events';
|
|
14
|
+
import pino from 'pino';
|
|
15
|
+
const logger = pino({ name: 'clementine.tunnel' });
|
|
16
|
+
export class TunnelManager extends EventEmitter {
|
|
17
|
+
process = null;
|
|
18
|
+
_url = null;
|
|
19
|
+
port;
|
|
20
|
+
restartCount = 0;
|
|
21
|
+
maxRestarts = 3;
|
|
22
|
+
stopping = false;
|
|
23
|
+
constructor(port) {
|
|
24
|
+
super();
|
|
25
|
+
this.port = port;
|
|
26
|
+
}
|
|
27
|
+
/** Check if cloudflared is installed. */
|
|
28
|
+
static isInstalled() {
|
|
29
|
+
try {
|
|
30
|
+
execSync('which cloudflared', { stdio: 'pipe' });
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Get install instructions for the current platform. */
|
|
38
|
+
static getInstallInstructions() {
|
|
39
|
+
if (process.platform === 'darwin') {
|
|
40
|
+
return 'brew install cloudflared';
|
|
41
|
+
}
|
|
42
|
+
return 'See https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/';
|
|
43
|
+
}
|
|
44
|
+
/** Start the tunnel. Resolves with the public URL. */
|
|
45
|
+
async start() {
|
|
46
|
+
if (this.process) {
|
|
47
|
+
throw new Error('Tunnel is already running');
|
|
48
|
+
}
|
|
49
|
+
if (!TunnelManager.isInstalled()) {
|
|
50
|
+
throw new Error(`cloudflared is not installed. Install with: ${TunnelManager.getInstallInstructions()}`);
|
|
51
|
+
}
|
|
52
|
+
this.stopping = false;
|
|
53
|
+
this.restartCount = 0;
|
|
54
|
+
return this._spawn();
|
|
55
|
+
}
|
|
56
|
+
_spawn() {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const proc = spawn('cloudflared', ['tunnel', '--url', `http://localhost:${this.port}`], {
|
|
59
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
60
|
+
});
|
|
61
|
+
this.process = proc;
|
|
62
|
+
let resolved = false;
|
|
63
|
+
const urlPattern = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/;
|
|
64
|
+
const onData = (chunk) => {
|
|
65
|
+
const text = chunk.toString();
|
|
66
|
+
const match = text.match(urlPattern);
|
|
67
|
+
if (match && !resolved) {
|
|
68
|
+
resolved = true;
|
|
69
|
+
this._url = match[0];
|
|
70
|
+
logger.info({ url: this._url }, 'Tunnel established');
|
|
71
|
+
this.emit('url', this._url);
|
|
72
|
+
resolve(this._url);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
proc.stdout?.on('data', onData);
|
|
76
|
+
proc.stderr?.on('data', onData);
|
|
77
|
+
proc.on('close', (code) => {
|
|
78
|
+
this.process = null;
|
|
79
|
+
const oldUrl = this._url;
|
|
80
|
+
this._url = null;
|
|
81
|
+
if (!resolved) {
|
|
82
|
+
reject(new Error(`cloudflared exited (code ${code}) before establishing tunnel`));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (!this.stopping && this.restartCount < this.maxRestarts) {
|
|
86
|
+
this.restartCount++;
|
|
87
|
+
logger.warn({ attempt: this.restartCount }, 'Tunnel closed — restarting');
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
if (!this.stopping) {
|
|
90
|
+
this._spawn().catch((err) => {
|
|
91
|
+
logger.error({ err }, 'Tunnel restart failed');
|
|
92
|
+
this.emit('error', err);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}, 5_000);
|
|
96
|
+
}
|
|
97
|
+
else if (!this.stopping) {
|
|
98
|
+
logger.error('Tunnel closed — max restarts exceeded');
|
|
99
|
+
this.emit('error', new Error('Max tunnel restarts exceeded'));
|
|
100
|
+
}
|
|
101
|
+
this.emit('close', oldUrl);
|
|
102
|
+
});
|
|
103
|
+
proc.on('error', (err) => {
|
|
104
|
+
this.process = null;
|
|
105
|
+
if (!resolved) {
|
|
106
|
+
reject(err);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
this.emit('error', err);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// Timeout: if no URL after 30s, fail
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (!resolved) {
|
|
115
|
+
resolved = true;
|
|
116
|
+
proc.kill();
|
|
117
|
+
reject(new Error('Tunnel startup timed out (30s)'));
|
|
118
|
+
}
|
|
119
|
+
}, 30_000);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/** Stop the tunnel gracefully. */
|
|
123
|
+
stop() {
|
|
124
|
+
this.stopping = true;
|
|
125
|
+
if (this.process) {
|
|
126
|
+
this.process.kill('SIGTERM');
|
|
127
|
+
this.process = null;
|
|
128
|
+
this._url = null;
|
|
129
|
+
logger.info('Tunnel stopped');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/** Get the current public URL (null if not running). */
|
|
133
|
+
getUrl() {
|
|
134
|
+
return this._url;
|
|
135
|
+
}
|
|
136
|
+
/** Whether the tunnel process is alive. */
|
|
137
|
+
isRunning() {
|
|
138
|
+
return this.process !== null && !this.process.killed;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=tunnel.js.map
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Configuration and paths.
|
|
3
|
+
*
|
|
4
|
+
* Reads .env into a local record — never pollutes process.env.
|
|
5
|
+
* The Claude Code SDK subprocess inherits process.env, so keeping
|
|
6
|
+
* secrets out of it prevents accidental leakage.
|
|
7
|
+
*/
|
|
8
|
+
import type { Models } from './types.js';
|
|
9
|
+
/** Package/code root (wherever npm installed the package). */
|
|
10
|
+
export declare const PKG_DIR: string;
|
|
11
|
+
/** Data home — user data, vault, .env, logs, sessions. */
|
|
12
|
+
export declare const BASE_DIR: string;
|
|
13
|
+
export declare const VAULT_DIR: string;
|
|
14
|
+
export declare const SYSTEM_DIR: string;
|
|
15
|
+
export declare const DAILY_NOTES_DIR: string;
|
|
16
|
+
export declare const PEOPLE_DIR: string;
|
|
17
|
+
export declare const PROJECTS_DIR: string;
|
|
18
|
+
export declare const TOPICS_DIR: string;
|
|
19
|
+
export declare const TASKS_DIR: string;
|
|
20
|
+
export declare const TEMPLATES_DIR: string;
|
|
21
|
+
export declare const INBOX_DIR: string;
|
|
22
|
+
export declare const PROFILES_DIR: string;
|
|
23
|
+
export declare const AGENTS_DIR: string;
|
|
24
|
+
export declare const SOUL_FILE: string;
|
|
25
|
+
export declare const AGENTS_FILE: string;
|
|
26
|
+
export declare const MEMORY_FILE: string;
|
|
27
|
+
export declare const HEARTBEAT_FILE: string;
|
|
28
|
+
export declare const CRON_FILE: string;
|
|
29
|
+
export declare const WORKFLOWS_DIR: string;
|
|
30
|
+
export declare const TASKS_FILE: string;
|
|
31
|
+
export declare const DAILY_TEMPLATE: string;
|
|
32
|
+
export declare const PEOPLE_TEMPLATE: string;
|
|
33
|
+
export declare const PROJECTS_META_FILE: string;
|
|
34
|
+
export declare const WORKING_MEMORY_FILE: string;
|
|
35
|
+
export declare const IDENTITY_FILE: string;
|
|
36
|
+
export declare const ASSISTANT_NAME: string;
|
|
37
|
+
export declare const ASSISTANT_NICKNAME: string;
|
|
38
|
+
export declare const OWNER_NAME: string;
|
|
39
|
+
export declare function shellEscape(s: string): string;
|
|
40
|
+
export declare const MODELS: Models;
|
|
41
|
+
export declare const BUDGET: {
|
|
42
|
+
readonly heartbeat: 0.5;
|
|
43
|
+
readonly cronT1: 2;
|
|
44
|
+
readonly cronT2: 5;
|
|
45
|
+
readonly chat: 5;
|
|
46
|
+
readonly unleashedPhase: undefined;
|
|
47
|
+
readonly memoryExtraction: undefined;
|
|
48
|
+
readonly summarization: undefined;
|
|
49
|
+
readonly reflection: undefined;
|
|
50
|
+
};
|
|
51
|
+
export declare const DEFAULT_MODEL_TIER: keyof Models;
|
|
52
|
+
export declare const MODEL: string;
|
|
53
|
+
/** Enable 1M context window for Sonnet (beta). Toggle via ENABLE_1M_CONTEXT=true in .env or dashboard. */
|
|
54
|
+
export declare let ENABLE_1M_CONTEXT: boolean;
|
|
55
|
+
/** Update 1M context flag at runtime (called from dashboard settings API). */
|
|
56
|
+
export declare function setEnable1MContext(value: boolean): void;
|
|
57
|
+
export declare const DISCORD_TOKEN: string;
|
|
58
|
+
export declare const DISCORD_OWNER_ID: string;
|
|
59
|
+
export declare const DISCORD_WATCHED_CHANNELS: string[];
|
|
60
|
+
export declare const SLACK_BOT_TOKEN: string;
|
|
61
|
+
export declare const SLACK_APP_TOKEN: string;
|
|
62
|
+
export declare const SLACK_OWNER_USER_ID: string;
|
|
63
|
+
export declare const TELEGRAM_BOT_TOKEN: string;
|
|
64
|
+
export declare const TELEGRAM_OWNER_ID: string;
|
|
65
|
+
export declare const TWILIO_ACCOUNT_SID: string;
|
|
66
|
+
export declare const TWILIO_AUTH_TOKEN: string;
|
|
67
|
+
export declare const WHATSAPP_OWNER_PHONE: string;
|
|
68
|
+
export declare const WHATSAPP_FROM_PHONE: string;
|
|
69
|
+
export declare const WHATSAPP_WEBHOOK_PORT: number;
|
|
70
|
+
export declare const WEBHOOK_ENABLED: boolean;
|
|
71
|
+
export declare const WEBHOOK_PORT: number;
|
|
72
|
+
export declare const WEBHOOK_SECRET: string;
|
|
73
|
+
export declare const GROQ_API_KEY: string;
|
|
74
|
+
export declare const ELEVENLABS_API_KEY: string;
|
|
75
|
+
export declare const ELEVENLABS_VOICE_ID: string;
|
|
76
|
+
export declare const GOOGLE_API_KEY: string;
|
|
77
|
+
export declare const MS_TENANT_ID: string;
|
|
78
|
+
export declare const MS_CLIENT_ID: string;
|
|
79
|
+
export declare const MS_CLIENT_SECRET: string;
|
|
80
|
+
export declare const MS_USER_EMAIL: string;
|
|
81
|
+
export declare const SF_INSTANCE_URL: string;
|
|
82
|
+
export declare const SF_CLIENT_ID: string;
|
|
83
|
+
export declare const SF_CLIENT_SECRET: string;
|
|
84
|
+
export declare const SF_USERNAME: string;
|
|
85
|
+
export declare const SF_PASSWORD: string;
|
|
86
|
+
export declare const SF_API_VERSION: string;
|
|
87
|
+
export declare const ALLOW_ALL_USERS: boolean;
|
|
88
|
+
/** User-configurable timezone. Falls back to system-detected timezone. */
|
|
89
|
+
export declare const TIMEZONE: string;
|
|
90
|
+
export declare const HEARTBEAT_INTERVAL_MINUTES: number;
|
|
91
|
+
export declare const HEARTBEAT_ACTIVE_START: number;
|
|
92
|
+
export declare const HEARTBEAT_ACTIVE_END: number;
|
|
93
|
+
export declare const HEARTBEAT_MAX_TURNS = 5;
|
|
94
|
+
export declare const HEARTBEAT_WORK_QUEUE_FILE: string;
|
|
95
|
+
/** Max turns per phase in unleashed mode before checkpointing. */
|
|
96
|
+
export declare const UNLEASHED_PHASE_TURNS = 75;
|
|
97
|
+
/** Default max duration for unleashed tasks (hours). */
|
|
98
|
+
export declare const UNLEASHED_DEFAULT_MAX_HOURS = 6;
|
|
99
|
+
/** Max phases before forcing completion. */
|
|
100
|
+
export declare const UNLEASHED_MAX_PHASES = 50;
|
|
101
|
+
export declare const WORKSPACE_DIRS: string[];
|
|
102
|
+
export declare const CHANNEL_DISCORD: boolean;
|
|
103
|
+
export declare const CHANNEL_SLACK: boolean;
|
|
104
|
+
export declare const CHANNEL_TELEGRAM: boolean;
|
|
105
|
+
export declare const CHANNEL_WHATSAPP: boolean;
|
|
106
|
+
export declare const CHANNEL_WEBHOOK: boolean;
|
|
107
|
+
export declare const CHANNEL_OUTLOOK: boolean;
|
|
108
|
+
export declare const CHANNEL_SALESFORCE: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Validate that explicitly configured secrets actually resolved.
|
|
111
|
+
* Call at startup — throws on misconfiguration.
|
|
112
|
+
*/
|
|
113
|
+
export declare function validateSecrets(): string[];
|
|
114
|
+
export declare const TEAM_COMMS_CHANNEL: string;
|
|
115
|
+
export declare const TEAM_COMMS_LOG: string;
|
|
116
|
+
export declare const LINK_EXTRACT_MAX_URLS = 3;
|
|
117
|
+
export declare const LINK_EXTRACT_MAX_CHARS = 4000;
|
|
118
|
+
export declare const MEMORY_DB_PATH: string;
|
|
119
|
+
export declare const GRAPH_DB_DIR: string;
|
|
120
|
+
export declare const SEARCH_CONTEXT_LIMIT = 3;
|
|
121
|
+
export declare const SEARCH_RECENCY_LIMIT = 3;
|
|
122
|
+
export declare const SYSTEM_PROMPT_MAX_CONTEXT_CHARS = 12000;
|
|
123
|
+
export declare const SESSION_EXCHANGE_HISTORY_SIZE = 10;
|
|
124
|
+
export declare const SESSION_EXCHANGE_MAX_CHARS = 2000;
|
|
125
|
+
export declare const INJECTED_CONTEXT_MAX_CHARS = 6000;
|
|
126
|
+
export declare const TEMPORAL_DECAY_HALF_LIFE_DAYS = 30;
|
|
127
|
+
export declare const EPISODIC_DECAY_HALF_LIFE_DAYS = 7;
|
|
128
|
+
export declare const SELF_IMPROVE_DIR: string;
|
|
129
|
+
export declare const SOURCE_MODS_DIR: string;
|
|
130
|
+
export declare const PENDING_SKILLS_DIR: string;
|
|
131
|
+
export declare const GOALS_DIR: string;
|
|
132
|
+
export declare const SEEN_CHANNELS_FILE: string;
|
|
133
|
+
export declare const CRON_PROGRESS_DIR: string;
|
|
134
|
+
export declare const CRON_REFLECTIONS_DIR: string;
|
|
135
|
+
export declare const DELEGATIONS_DIR: string;
|
|
136
|
+
export declare const HANDOFFS_DIR: string;
|
|
137
|
+
export declare const PLAN_STATE_DIR: string;
|
|
138
|
+
export declare const VAULT_MIGRATIONS_STATE: string;
|
|
139
|
+
export declare const PLANS_DIR: string;
|
|
140
|
+
export declare const ADVISOR_LOG_PATH: string;
|
|
141
|
+
export declare const REMOTE_ACCESS_CONFIG: string;
|
|
142
|
+
export declare const STAGING_DIR: string;
|
|
143
|
+
export declare const CLAUDE_CODE_OAUTH_TOKEN: string;
|
|
144
|
+
export declare const ANTHROPIC_API_KEY: string;
|
|
145
|
+
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Configuration and paths.
|
|
3
|
+
*
|
|
4
|
+
* Reads .env into a local record — never pollutes process.env.
|
|
5
|
+
* The Claude Code SDK subprocess inherits process.env, so keeping
|
|
6
|
+
* secrets out of it prevents accidental leakage.
|
|
7
|
+
*/
|
|
8
|
+
import { execSync } from 'node:child_process';
|
|
9
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
// ── Path split: code vs data ────────────────────────────────────────
|
|
16
|
+
/** Package/code root (wherever npm installed the package). */
|
|
17
|
+
export const PKG_DIR = path.resolve(__dirname, '..');
|
|
18
|
+
/** Data home — user data, vault, .env, logs, sessions. */
|
|
19
|
+
export const BASE_DIR = process.env.CLEMENTINE_HOME || path.join(os.homedir(), '.clementine');
|
|
20
|
+
// ── .env parser (never sets process.env) ────────────────────────────
|
|
21
|
+
function readEnvFile() {
|
|
22
|
+
const envPath = path.join(BASE_DIR, '.env');
|
|
23
|
+
if (!existsSync(envPath))
|
|
24
|
+
return {};
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
|
|
27
|
+
const trimmed = line.trim();
|
|
28
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
29
|
+
continue;
|
|
30
|
+
const eqIndex = trimmed.indexOf('=');
|
|
31
|
+
if (eqIndex === -1)
|
|
32
|
+
continue;
|
|
33
|
+
const key = trimmed.slice(0, eqIndex);
|
|
34
|
+
let value = trimmed.slice(eqIndex + 1);
|
|
35
|
+
// Strip surrounding quotes
|
|
36
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
37
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
38
|
+
value = value.slice(1, -1);
|
|
39
|
+
}
|
|
40
|
+
result[key] = value;
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
const env = readEnvFile();
|
|
45
|
+
/** Look up a config value: local .env first, then process.env fallback. */
|
|
46
|
+
function getEnv(key, fallback = '') {
|
|
47
|
+
return env[key] ?? process.env[key] ?? fallback;
|
|
48
|
+
}
|
|
49
|
+
// ── Paths ────────────────────────────────────────────────────────────
|
|
50
|
+
export const VAULT_DIR = path.join(BASE_DIR, 'vault');
|
|
51
|
+
export const SYSTEM_DIR = path.join(VAULT_DIR, '00-System');
|
|
52
|
+
export const DAILY_NOTES_DIR = path.join(VAULT_DIR, '01-Daily-Notes');
|
|
53
|
+
export const PEOPLE_DIR = path.join(VAULT_DIR, '02-People');
|
|
54
|
+
export const PROJECTS_DIR = path.join(VAULT_DIR, '03-Projects');
|
|
55
|
+
export const TOPICS_DIR = path.join(VAULT_DIR, '04-Topics');
|
|
56
|
+
export const TASKS_DIR = path.join(VAULT_DIR, '05-Tasks');
|
|
57
|
+
export const TEMPLATES_DIR = path.join(VAULT_DIR, '06-Templates');
|
|
58
|
+
export const INBOX_DIR = path.join(VAULT_DIR, '07-Inbox');
|
|
59
|
+
export const PROFILES_DIR = path.join(SYSTEM_DIR, 'profiles');
|
|
60
|
+
export const AGENTS_DIR = path.join(SYSTEM_DIR, 'agents');
|
|
61
|
+
export const SOUL_FILE = path.join(SYSTEM_DIR, 'SOUL.md');
|
|
62
|
+
export const AGENTS_FILE = path.join(SYSTEM_DIR, 'AGENTS.md');
|
|
63
|
+
export const MEMORY_FILE = path.join(SYSTEM_DIR, 'MEMORY.md');
|
|
64
|
+
export const HEARTBEAT_FILE = path.join(SYSTEM_DIR, 'HEARTBEAT.md');
|
|
65
|
+
export const CRON_FILE = path.join(SYSTEM_DIR, 'CRON.md');
|
|
66
|
+
export const WORKFLOWS_DIR = path.join(SYSTEM_DIR, 'workflows');
|
|
67
|
+
export const TASKS_FILE = path.join(TASKS_DIR, 'TASKS.md');
|
|
68
|
+
export const DAILY_TEMPLATE = path.join(TEMPLATES_DIR, '_Daily-Template.md');
|
|
69
|
+
export const PEOPLE_TEMPLATE = path.join(TEMPLATES_DIR, '_People-Template.md');
|
|
70
|
+
export const PROJECTS_META_FILE = path.join(BASE_DIR, 'projects.json');
|
|
71
|
+
export const WORKING_MEMORY_FILE = path.join(BASE_DIR, 'working-memory.md');
|
|
72
|
+
export const IDENTITY_FILE = path.join(SYSTEM_DIR, 'IDENTITY.md');
|
|
73
|
+
// ── Assistant identity ───────────────────────────────────────────────
|
|
74
|
+
export const ASSISTANT_NAME = getEnv('ASSISTANT_NAME', 'Clementine');
|
|
75
|
+
export const ASSISTANT_NICKNAME = getEnv('ASSISTANT_NICKNAME', 'Clemmy');
|
|
76
|
+
export const OWNER_NAME = getEnv('OWNER_NAME');
|
|
77
|
+
// ── Secrets (with macOS Keychain fallback) ───────────────────────────
|
|
78
|
+
export function shellEscape(s) {
|
|
79
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
80
|
+
}
|
|
81
|
+
function getSecret(envKey, keychainService) {
|
|
82
|
+
const value = env[envKey] ?? '';
|
|
83
|
+
if (value)
|
|
84
|
+
return value;
|
|
85
|
+
const service = keychainService ?? ASSISTANT_NAME.toLowerCase();
|
|
86
|
+
try {
|
|
87
|
+
const result = execSync(`security find-generic-password -s ${shellEscape(service)} -a ${shellEscape(envKey)} -w`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
88
|
+
return result.trim();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return '';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ── Models ───────────────────────────────────────────────────────────
|
|
95
|
+
export const MODELS = {
|
|
96
|
+
haiku: 'claude-haiku-4-5-20251001',
|
|
97
|
+
sonnet: 'claude-sonnet-4-6',
|
|
98
|
+
opus: 'claude-opus-4-6',
|
|
99
|
+
};
|
|
100
|
+
// ── Budget caps (USD per query) ──────────────────────────────────────
|
|
101
|
+
export const BUDGET = {
|
|
102
|
+
heartbeat: 0.50, // $0.50 per heartbeat (Haiku, cheap)
|
|
103
|
+
cronT1: 2.00, // $2 per tier-1 cron job (needs room for outlook+search)
|
|
104
|
+
cronT2: 5.00, // $5 per tier-2 cron job
|
|
105
|
+
chat: 5.00, // $5 per interactive chat message
|
|
106
|
+
unleashedPhase: undefined,
|
|
107
|
+
memoryExtraction: undefined,
|
|
108
|
+
summarization: undefined,
|
|
109
|
+
reflection: undefined,
|
|
110
|
+
};
|
|
111
|
+
export const DEFAULT_MODEL_TIER = (getEnv('DEFAULT_MODEL_TIER', 'sonnet'));
|
|
112
|
+
export const MODEL = MODELS[DEFAULT_MODEL_TIER] ?? MODELS.sonnet;
|
|
113
|
+
/** Enable 1M context window for Sonnet (beta). Toggle via ENABLE_1M_CONTEXT=true in .env or dashboard. */
|
|
114
|
+
export let ENABLE_1M_CONTEXT = getEnv('ENABLE_1M_CONTEXT', 'false').toLowerCase() === 'true';
|
|
115
|
+
/** Update 1M context flag at runtime (called from dashboard settings API). */
|
|
116
|
+
export function setEnable1MContext(value) {
|
|
117
|
+
ENABLE_1M_CONTEXT = value;
|
|
118
|
+
}
|
|
119
|
+
// ── Discord ──────────────────────────────────────────────────────────
|
|
120
|
+
export const DISCORD_TOKEN = getSecret('DISCORD_TOKEN');
|
|
121
|
+
export const DISCORD_OWNER_ID = getEnv('DISCORD_OWNER_ID', '0');
|
|
122
|
+
export const DISCORD_WATCHED_CHANNELS = getEnv('DISCORD_WATCHED_CHANNELS')
|
|
123
|
+
.split(',')
|
|
124
|
+
.map((s) => s.trim())
|
|
125
|
+
.filter(Boolean);
|
|
126
|
+
// ── Slack ────────────────────────────────────────────────────────────
|
|
127
|
+
export const SLACK_BOT_TOKEN = getSecret('SLACK_BOT_TOKEN');
|
|
128
|
+
export const SLACK_APP_TOKEN = getSecret('SLACK_APP_TOKEN');
|
|
129
|
+
export const SLACK_OWNER_USER_ID = getEnv('SLACK_OWNER_USER_ID');
|
|
130
|
+
// ── Telegram ─────────────────────────────────────────────────────────
|
|
131
|
+
export const TELEGRAM_BOT_TOKEN = getSecret('TELEGRAM_BOT_TOKEN');
|
|
132
|
+
export const TELEGRAM_OWNER_ID = getEnv('TELEGRAM_OWNER_ID', '0');
|
|
133
|
+
// ── WhatsApp (Twilio) ────────────────────────────────────────────────
|
|
134
|
+
export const TWILIO_ACCOUNT_SID = getSecret('TWILIO_ACCOUNT_SID');
|
|
135
|
+
export const TWILIO_AUTH_TOKEN = getSecret('TWILIO_AUTH_TOKEN');
|
|
136
|
+
export const WHATSAPP_OWNER_PHONE = getEnv('WHATSAPP_OWNER_PHONE');
|
|
137
|
+
export const WHATSAPP_FROM_PHONE = getEnv('WHATSAPP_FROM_PHONE');
|
|
138
|
+
export const WHATSAPP_WEBHOOK_PORT = parseInt(getEnv('WHATSAPP_WEBHOOK_PORT', '8421'), 10);
|
|
139
|
+
// ── Webhook ──────────────────────────────────────────────────────────
|
|
140
|
+
export const WEBHOOK_ENABLED = getEnv('WEBHOOK_ENABLED', 'false').toLowerCase() === 'true';
|
|
141
|
+
export const WEBHOOK_PORT = parseInt(getEnv('WEBHOOK_PORT', '8420'), 10);
|
|
142
|
+
export const WEBHOOK_SECRET = getSecret('WEBHOOK_SECRET');
|
|
143
|
+
// ── Voice ────────────────────────────────────────────────────────────
|
|
144
|
+
export const GROQ_API_KEY = getSecret('GROQ_API_KEY');
|
|
145
|
+
export const ELEVENLABS_API_KEY = getSecret('ELEVENLABS_API_KEY');
|
|
146
|
+
export const ELEVENLABS_VOICE_ID = getEnv('ELEVENLABS_VOICE_ID');
|
|
147
|
+
// ── Video ────────────────────────────────────────────────────────────
|
|
148
|
+
export const GOOGLE_API_KEY = getSecret('GOOGLE_API_KEY');
|
|
149
|
+
// ── Outlook (Microsoft Graph) ───────────────────────────────────────
|
|
150
|
+
export const MS_TENANT_ID = getEnv('MS_TENANT_ID');
|
|
151
|
+
export const MS_CLIENT_ID = getEnv('MS_CLIENT_ID');
|
|
152
|
+
export const MS_CLIENT_SECRET = getSecret('MS_CLIENT_SECRET');
|
|
153
|
+
export const MS_USER_EMAIL = getEnv('MS_USER_EMAIL');
|
|
154
|
+
// ── Salesforce CRM ─────────────────────────────────────────────────
|
|
155
|
+
export const SF_INSTANCE_URL = getEnv('SF_INSTANCE_URL');
|
|
156
|
+
export const SF_CLIENT_ID = getEnv('SF_CLIENT_ID');
|
|
157
|
+
export const SF_CLIENT_SECRET = getSecret('SF_CLIENT_SECRET');
|
|
158
|
+
export const SF_USERNAME = getEnv('SF_USERNAME');
|
|
159
|
+
export const SF_PASSWORD = getSecret('SF_PASSWORD');
|
|
160
|
+
export const SF_API_VERSION = getEnv('SF_API_VERSION', 'v62.0');
|
|
161
|
+
// ── Security ─────────────────────────────────────────────────────────
|
|
162
|
+
export const ALLOW_ALL_USERS = getEnv('ALLOW_ALL_USERS', 'false').toLowerCase() === 'true';
|
|
163
|
+
// ── Timezone ─────────────────────────────────────────────────────────
|
|
164
|
+
/** User-configurable timezone. Falls back to system-detected timezone. */
|
|
165
|
+
export const TIMEZONE = getEnv('TIMEZONE') || Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
166
|
+
// ── Heartbeat ────────────────────────────────────────────────────────
|
|
167
|
+
export const HEARTBEAT_INTERVAL_MINUTES = parseInt(getEnv('HEARTBEAT_INTERVAL_MINUTES', '30'), 10) || 30;
|
|
168
|
+
export const HEARTBEAT_ACTIVE_START = parseInt(getEnv('HEARTBEAT_ACTIVE_START', '8'), 10);
|
|
169
|
+
export const HEARTBEAT_ACTIVE_END = parseInt(getEnv('HEARTBEAT_ACTIVE_END', '22'), 10);
|
|
170
|
+
export const HEARTBEAT_MAX_TURNS = 5;
|
|
171
|
+
export const HEARTBEAT_WORK_QUEUE_FILE = path.join(BASE_DIR, 'heartbeat', 'work-queue.json');
|
|
172
|
+
// ── Unleashed mode ──────────────────────────────────────────────────
|
|
173
|
+
/** Max turns per phase in unleashed mode before checkpointing. */
|
|
174
|
+
export const UNLEASHED_PHASE_TURNS = 75;
|
|
175
|
+
/** Default max duration for unleashed tasks (hours). */
|
|
176
|
+
export const UNLEASHED_DEFAULT_MAX_HOURS = 6;
|
|
177
|
+
/** Max phases before forcing completion. */
|
|
178
|
+
export const UNLEASHED_MAX_PHASES = 50;
|
|
179
|
+
// ── Workspace ───────────────────────────────────────────────────────
|
|
180
|
+
export const WORKSPACE_DIRS = getEnv('WORKSPACE_DIRS')
|
|
181
|
+
.split(',')
|
|
182
|
+
.map((s) => s.trim())
|
|
183
|
+
.filter(Boolean);
|
|
184
|
+
// ── Channel availability flags ───────────────────────────────────────
|
|
185
|
+
export const CHANNEL_DISCORD = Boolean(DISCORD_TOKEN);
|
|
186
|
+
export const CHANNEL_SLACK = Boolean(SLACK_BOT_TOKEN && SLACK_APP_TOKEN);
|
|
187
|
+
export const CHANNEL_TELEGRAM = Boolean(TELEGRAM_BOT_TOKEN);
|
|
188
|
+
export const CHANNEL_WHATSAPP = Boolean(TWILIO_ACCOUNT_SID && TWILIO_AUTH_TOKEN && WHATSAPP_OWNER_PHONE);
|
|
189
|
+
export const CHANNEL_WEBHOOK = WEBHOOK_ENABLED && Boolean(WEBHOOK_SECRET);
|
|
190
|
+
export const CHANNEL_OUTLOOK = Boolean(MS_TENANT_ID && MS_CLIENT_ID && MS_CLIENT_SECRET && MS_USER_EMAIL);
|
|
191
|
+
export const CHANNEL_SALESFORCE = Boolean(SF_INSTANCE_URL && SF_CLIENT_ID && SF_CLIENT_SECRET);
|
|
192
|
+
const SECRET_VALIDATIONS = [
|
|
193
|
+
{ key: 'DISCORD_TOKEN', channel: 'Discord' },
|
|
194
|
+
{ key: 'SLACK_BOT_TOKEN', channel: 'Slack', requiredWith: ['SLACK_APP_TOKEN'] },
|
|
195
|
+
{ key: 'SLACK_APP_TOKEN', channel: 'Slack', requiredWith: ['SLACK_BOT_TOKEN'] },
|
|
196
|
+
{ key: 'TELEGRAM_BOT_TOKEN', channel: 'Telegram' },
|
|
197
|
+
{ key: 'TWILIO_ACCOUNT_SID', channel: 'WhatsApp', requiredWith: ['TWILIO_AUTH_TOKEN', 'WHATSAPP_OWNER_PHONE'] },
|
|
198
|
+
// Auth is optional here — clementine login sets CLAUDE_CODE_OAUTH_TOKEN (preferred).
|
|
199
|
+
// SDK subprocess reads CLAUDE_CODE_OAUTH_TOKEN > ANTHROPIC_AUTH_TOKEN > ANTHROPIC_API_KEY > Keychain.
|
|
200
|
+
{ key: 'CLAUDE_CODE_OAUTH_TOKEN', channel: 'API (preferred — set via `clementine login`)' },
|
|
201
|
+
{ key: 'ANTHROPIC_API_KEY', channel: 'API (legacy — use `clementine login` for OAuth instead)' },
|
|
202
|
+
{ key: 'SF_CLIENT_SECRET', channel: 'Salesforce', requiredWith: ['SF_CLIENT_ID', 'SF_INSTANCE_URL'] },
|
|
203
|
+
];
|
|
204
|
+
/**
|
|
205
|
+
* Validate that explicitly configured secrets actually resolved.
|
|
206
|
+
* Call at startup — throws on misconfiguration.
|
|
207
|
+
*/
|
|
208
|
+
export function validateSecrets() {
|
|
209
|
+
const warnings = [];
|
|
210
|
+
for (const v of SECRET_VALIDATIONS) {
|
|
211
|
+
// Only check if the key is explicitly present in .env (not process.env fallback)
|
|
212
|
+
const explicitlyConfigured = v.key in env;
|
|
213
|
+
if (!explicitlyConfigured)
|
|
214
|
+
continue;
|
|
215
|
+
const value = getSecret(v.key);
|
|
216
|
+
if (!value) {
|
|
217
|
+
warnings.push(`${v.channel}: ${v.key} is configured in .env but resolved to empty. ` +
|
|
218
|
+
`Check your .env file or Keychain entry.`);
|
|
219
|
+
}
|
|
220
|
+
// Check companion keys
|
|
221
|
+
if (value && v.requiredWith) {
|
|
222
|
+
for (const companion of v.requiredWith) {
|
|
223
|
+
const companionValue = env[companion] ?? '';
|
|
224
|
+
// Only warn if the companion is also in .env but empty
|
|
225
|
+
if (companion in env && !companionValue) {
|
|
226
|
+
warnings.push(`${v.channel}: ${v.key} is set but companion ${companion} is empty.`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return warnings;
|
|
232
|
+
}
|
|
233
|
+
// ── Team ────────────────────────────────────────────────────────────
|
|
234
|
+
export const TEAM_COMMS_CHANNEL = getEnv('TEAM_COMMS_CHANNEL');
|
|
235
|
+
export const TEAM_COMMS_LOG = path.join(BASE_DIR, 'logs', 'team-comms.jsonl');
|
|
236
|
+
// ── Link Extraction ──────────────────────────────────────────────────
|
|
237
|
+
export const LINK_EXTRACT_MAX_URLS = 3;
|
|
238
|
+
export const LINK_EXTRACT_MAX_CHARS = 4000;
|
|
239
|
+
// ── Memory / Search ──────────────────────────────────────────────────
|
|
240
|
+
export const MEMORY_DB_PATH = path.join(VAULT_DIR, '.memory.db');
|
|
241
|
+
export const GRAPH_DB_DIR = path.join(BASE_DIR, '.graph.db');
|
|
242
|
+
export const SEARCH_CONTEXT_LIMIT = 3;
|
|
243
|
+
export const SEARCH_RECENCY_LIMIT = 3;
|
|
244
|
+
export const SYSTEM_PROMPT_MAX_CONTEXT_CHARS = 12000;
|
|
245
|
+
// ── Session Persistence ──────────────────────────────────────────────
|
|
246
|
+
export const SESSION_EXCHANGE_HISTORY_SIZE = 10;
|
|
247
|
+
export const SESSION_EXCHANGE_MAX_CHARS = 2000;
|
|
248
|
+
export const INJECTED_CONTEXT_MAX_CHARS = 6000;
|
|
249
|
+
// ── Search Ranking ───────────────────────────────────────────────────
|
|
250
|
+
export const TEMPORAL_DECAY_HALF_LIFE_DAYS = 30;
|
|
251
|
+
export const EPISODIC_DECAY_HALF_LIFE_DAYS = 7;
|
|
252
|
+
// ── Self-Improvement ─────────────────────────────────────────────────
|
|
253
|
+
export const SELF_IMPROVE_DIR = path.join(BASE_DIR, 'self-improve');
|
|
254
|
+
export const SOURCE_MODS_DIR = path.join(SELF_IMPROVE_DIR, 'source-mods');
|
|
255
|
+
export const PENDING_SKILLS_DIR = path.join(SELF_IMPROVE_DIR, 'pending-skills');
|
|
256
|
+
// ── Goals & Cron Progress ───────────────────────────────────────────
|
|
257
|
+
export const GOALS_DIR = path.join(BASE_DIR, 'goals');
|
|
258
|
+
export const SEEN_CHANNELS_FILE = path.join(BASE_DIR, 'seen-channels.json');
|
|
259
|
+
export const CRON_PROGRESS_DIR = path.join(BASE_DIR, 'cron', 'progress');
|
|
260
|
+
export const CRON_REFLECTIONS_DIR = path.join(BASE_DIR, 'cron', 'reflections');
|
|
261
|
+
export const DELEGATIONS_DIR = path.join(VAULT_DIR, '00-System', 'agents');
|
|
262
|
+
export const HANDOFFS_DIR = path.join(BASE_DIR, 'handoffs');
|
|
263
|
+
export const PLAN_STATE_DIR = path.join(BASE_DIR, 'plan-state');
|
|
264
|
+
export const VAULT_MIGRATIONS_STATE = path.join(BASE_DIR, '.vault-migrations.json');
|
|
265
|
+
// ── Daily Plans ─────────────────────────────────────────────────────
|
|
266
|
+
export const PLANS_DIR = path.join(BASE_DIR, 'plans');
|
|
267
|
+
// ── Advisor Decision Log ────────────────────────────────────────────
|
|
268
|
+
export const ADVISOR_LOG_PATH = path.join(BASE_DIR, 'cron', 'advisor-decisions.jsonl');
|
|
269
|
+
// ── Remote Access ──────────────────────────────────────────────────
|
|
270
|
+
export const REMOTE_ACCESS_CONFIG = path.join(BASE_DIR, 'remote-access.json');
|
|
271
|
+
// ── Source Self-Edit Staging ─────────────────────────────────────────
|
|
272
|
+
export const STAGING_DIR = path.join(BASE_DIR, 'staging');
|
|
273
|
+
// ── API ──────────────────────────────────────────────────────────────
|
|
274
|
+
// Long-lived OAuth token from `clementine login` / `claude setup-token`.
|
|
275
|
+
// Takes priority over ANTHROPIC_API_KEY in the SDK subprocess env.
|
|
276
|
+
export const CLAUDE_CODE_OAUTH_TOKEN = getSecret('CLAUDE_CODE_OAUTH_TOKEN');
|
|
277
|
+
export const ANTHROPIC_API_KEY = getSecret('ANTHROPIC_API_KEY');
|
|
278
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Event Bus.
|
|
3
|
+
*
|
|
4
|
+
* Typed pub/sub system for decoupling gateway lifecycle events from consumers.
|
|
5
|
+
* Plugins, logging, metrics, and UI can subscribe without modifying core code.
|
|
6
|
+
*
|
|
7
|
+
* Events are fire-and-forget (async handlers don't block the emitter).
|
|
8
|
+
* "before" events return a boolean — false cancels the operation.
|
|
9
|
+
*/
|
|
10
|
+
export type EventHandler<T = unknown> = (payload: T) => void | Promise<void>;
|
|
11
|
+
export type BeforeHandler<T = unknown> = (payload: T) => boolean | Promise<boolean>;
|
|
12
|
+
declare class EventBus {
|
|
13
|
+
private listeners;
|
|
14
|
+
private beforeHandlers;
|
|
15
|
+
/**
|
|
16
|
+
* Subscribe to an event. Handler is called asynchronously (fire-and-forget).
|
|
17
|
+
* Returns an unsubscribe function.
|
|
18
|
+
*/
|
|
19
|
+
on<T = unknown>(event: string, handler: EventHandler<T>): () => void;
|
|
20
|
+
/** Subscribe to an event, but only fire once. */
|
|
21
|
+
once<T = unknown>(event: string, handler: EventHandler<T>): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Register a "before" handler that can cancel an operation.
|
|
24
|
+
* If any before handler returns false, the operation is cancelled.
|
|
25
|
+
*/
|
|
26
|
+
before<T = unknown>(event: string, handler: BeforeHandler<T>): () => void;
|
|
27
|
+
/**
|
|
28
|
+
* Emit an event asynchronously. Handlers run in parallel, errors are logged but don't propagate.
|
|
29
|
+
*/
|
|
30
|
+
emit<T = unknown>(event: string, payload: T): void;
|
|
31
|
+
/**
|
|
32
|
+
* Run "before" handlers sequentially. Returns true if all pass, false if any cancels.
|
|
33
|
+
*/
|
|
34
|
+
emitBefore<T = unknown>(event: string, payload: T): Promise<boolean>;
|
|
35
|
+
/** Remove all listeners for an event, or all events if no event specified. */
|
|
36
|
+
clear(event?: string): void;
|
|
37
|
+
/** Get count of listeners for an event (useful for debugging). */
|
|
38
|
+
listenerCount(event: string): number;
|
|
39
|
+
}
|
|
40
|
+
/** Singleton event bus — shared across the entire process. */
|
|
41
|
+
export declare const events: EventBus;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=bus.d.ts.map
|