beecork 1.7.0 → 2.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/README.md +52 -111
- package/dist/index.js +1394 -581
- package/package.json +26 -54
- package/dist/capabilities/index.d.ts +0 -3
- package/dist/capabilities/index.js +0 -2
- package/dist/capabilities/manager.d.ts +0 -13
- package/dist/capabilities/manager.js +0 -115
- package/dist/capabilities/packs.d.ts +0 -2
- package/dist/capabilities/packs.js +0 -54
- package/dist/capabilities/types.d.ts +0 -21
- package/dist/capabilities/types.js +0 -1
- package/dist/channels/admin.d.ts +0 -10
- package/dist/channels/admin.js +0 -20
- package/dist/channels/command-handler.d.ts +0 -19
- package/dist/channels/command-handler.js +0 -235
- package/dist/channels/discord.d.ts +0 -17
- package/dist/channels/discord.js +0 -266
- package/dist/channels/index.d.ts +0 -7
- package/dist/channels/index.js +0 -6
- package/dist/channels/loader.d.ts +0 -7
- package/dist/channels/loader.js +0 -87
- package/dist/channels/pipeline.d.ts +0 -50
- package/dist/channels/pipeline.js +0 -92
- package/dist/channels/registry.d.ts +0 -36
- package/dist/channels/registry.js +0 -80
- package/dist/channels/send-helpers.d.ts +0 -19
- package/dist/channels/send-helpers.js +0 -21
- package/dist/channels/telegram.d.ts +0 -47
- package/dist/channels/telegram.js +0 -649
- package/dist/channels/types.d.ts +0 -41
- package/dist/channels/types.js +0 -1
- package/dist/channels/voice-state.d.ts +0 -29
- package/dist/channels/voice-state.js +0 -45
- package/dist/channels/webhook.d.ts +0 -16
- package/dist/channels/webhook.js +0 -222
- package/dist/channels/whatsapp.d.ts +0 -28
- package/dist/channels/whatsapp.js +0 -323
- package/dist/cli/capabilities.d.ts +0 -3
- package/dist/cli/capabilities.js +0 -72
- package/dist/cli/channel.d.ts +0 -3
- package/dist/cli/channel.js +0 -202
- package/dist/cli/commands.d.ts +0 -15
- package/dist/cli/commands.js +0 -279
- package/dist/cli/doctor.d.ts +0 -1
- package/dist/cli/doctor.js +0 -208
- package/dist/cli/handoff.d.ts +0 -8
- package/dist/cli/handoff.js +0 -33
- package/dist/cli/helpers.d.ts +0 -2
- package/dist/cli/helpers.js +0 -21
- package/dist/cli/mcp.d.ts +0 -3
- package/dist/cli/mcp.js +0 -47
- package/dist/cli/media.d.ts +0 -2
- package/dist/cli/media.js +0 -125
- package/dist/cli/setup.d.ts +0 -1
- package/dist/cli/setup.js +0 -239
- package/dist/cli/store.d.ts +0 -3
- package/dist/cli/store.js +0 -108
- package/dist/config.d.ts +0 -11
- package/dist/config.js +0 -115
- package/dist/daemon.d.ts +0 -1
- package/dist/daemon.js +0 -345
- package/dist/dashboard/html.d.ts +0 -1
- package/dist/dashboard/html.js +0 -849
- package/dist/dashboard/routes.d.ts +0 -17
- package/dist/dashboard/routes.js +0 -623
- package/dist/dashboard/server.d.ts +0 -1
- package/dist/dashboard/server.js +0 -104
- package/dist/db/connection.d.ts +0 -29
- package/dist/db/connection.js +0 -37
- package/dist/db/index.d.ts +0 -14
- package/dist/db/index.js +0 -127
- package/dist/db/migrations.d.ts +0 -2
- package/dist/db/migrations.js +0 -384
- package/dist/delegation/manager.d.ts +0 -18
- package/dist/delegation/manager.js +0 -89
- package/dist/index.d.ts +0 -2
- package/dist/knowledge/index.d.ts +0 -2
- package/dist/knowledge/index.js +0 -1
- package/dist/knowledge/manager.d.ts +0 -17
- package/dist/knowledge/manager.js +0 -160
- package/dist/knowledge/types.d.ts +0 -7
- package/dist/knowledge/types.js +0 -1
- package/dist/mcp/handlers.d.ts +0 -37
- package/dist/mcp/handlers.js +0 -520
- package/dist/mcp/server.d.ts +0 -2
- package/dist/mcp/server.js +0 -86
- package/dist/mcp/tool-definitions.d.ts +0 -1225
- package/dist/mcp/tool-definitions.js +0 -412
- package/dist/mcp/validate.d.ts +0 -23
- package/dist/mcp/validate.js +0 -65
- package/dist/media/factory.d.ts +0 -6
- package/dist/media/factory.js +0 -36
- package/dist/media/generators/dall-e.d.ts +0 -10
- package/dist/media/generators/dall-e.js +0 -41
- package/dist/media/generators/elevenlabs-music.d.ts +0 -9
- package/dist/media/generators/elevenlabs-music.js +0 -34
- package/dist/media/generators/elevenlabs-sfx.d.ts +0 -9
- package/dist/media/generators/elevenlabs-sfx.js +0 -33
- package/dist/media/generators/kling.d.ts +0 -9
- package/dist/media/generators/kling.js +0 -47
- package/dist/media/generators/lyria.d.ts +0 -10
- package/dist/media/generators/lyria.js +0 -41
- package/dist/media/generators/nano-banana.d.ts +0 -10
- package/dist/media/generators/nano-banana.js +0 -45
- package/dist/media/generators/poll-util.d.ts +0 -12
- package/dist/media/generators/poll-util.js +0 -22
- package/dist/media/generators/recraft.d.ts +0 -9
- package/dist/media/generators/recraft.js +0 -52
- package/dist/media/generators/runway.d.ts +0 -9
- package/dist/media/generators/runway.js +0 -49
- package/dist/media/generators/stable-diffusion.d.ts +0 -9
- package/dist/media/generators/stable-diffusion.js +0 -35
- package/dist/media/generators/veo.d.ts +0 -9
- package/dist/media/generators/veo.js +0 -32
- package/dist/media/index.d.ts +0 -6
- package/dist/media/index.js +0 -8
- package/dist/media/store.d.ts +0 -17
- package/dist/media/store.js +0 -69
- package/dist/media/types.d.ts +0 -43
- package/dist/media/types.js +0 -1
- package/dist/notifications/index.d.ts +0 -4
- package/dist/notifications/index.js +0 -21
- package/dist/notifications/ntfy.d.ts +0 -9
- package/dist/notifications/ntfy.js +0 -25
- package/dist/notifications/pushover.d.ts +0 -9
- package/dist/notifications/pushover.js +0 -26
- package/dist/notifications/types.d.ts +0 -5
- package/dist/notifications/types.js +0 -1
- package/dist/notifications/webhook-provider.d.ts +0 -9
- package/dist/notifications/webhook-provider.js +0 -24
- package/dist/observability/analytics.d.ts +0 -30
- package/dist/observability/analytics.js +0 -118
- package/dist/projects/index.d.ts +0 -4
- package/dist/projects/index.js +0 -2
- package/dist/projects/manager.d.ts +0 -13
- package/dist/projects/manager.js +0 -166
- package/dist/projects/router.d.ts +0 -17
- package/dist/projects/router.js +0 -246
- package/dist/projects/types.d.ts +0 -19
- package/dist/projects/types.js +0 -1
- package/dist/service/install.d.ts +0 -4
- package/dist/service/install.js +0 -146
- package/dist/service/templates.d.ts +0 -4
- package/dist/service/templates.js +0 -52
- package/dist/service/windows.d.ts +0 -8
- package/dist/service/windows.js +0 -59
- package/dist/session/budget-guard.d.ts +0 -20
- package/dist/session/budget-guard.js +0 -31
- package/dist/session/circuit-breaker.d.ts +0 -19
- package/dist/session/circuit-breaker.js +0 -91
- package/dist/session/context-compactor.d.ts +0 -32
- package/dist/session/context-compactor.js +0 -45
- package/dist/session/context-monitor.d.ts +0 -15
- package/dist/session/context-monitor.js +0 -44
- package/dist/session/handoff.d.ts +0 -21
- package/dist/session/handoff.js +0 -50
- package/dist/session/manager.d.ts +0 -60
- package/dist/session/manager.js +0 -379
- package/dist/session/memory-store.d.ts +0 -29
- package/dist/session/memory-store.js +0 -45
- package/dist/session/message-queue.d.ts +0 -28
- package/dist/session/message-queue.js +0 -52
- package/dist/session/pending-dispatcher.d.ts +0 -31
- package/dist/session/pending-dispatcher.js +0 -120
- package/dist/session/pending-store.d.ts +0 -60
- package/dist/session/pending-store.js +0 -118
- package/dist/session/stale-session.d.ts +0 -31
- package/dist/session/stale-session.js +0 -45
- package/dist/session/subprocess.d.ts +0 -25
- package/dist/session/subprocess.js +0 -189
- package/dist/session/tab-store.d.ts +0 -28
- package/dist/session/tab-store.js +0 -78
- package/dist/tasks/scheduler.d.ts +0 -45
- package/dist/tasks/scheduler.js +0 -329
- package/dist/tasks/store.d.ts +0 -11
- package/dist/tasks/store.js +0 -103
- package/dist/timeline/index.d.ts +0 -3
- package/dist/timeline/index.js +0 -2
- package/dist/timeline/logger.d.ts +0 -8
- package/dist/timeline/logger.js +0 -11
- package/dist/timeline/query.d.ts +0 -11
- package/dist/timeline/query.js +0 -67
- package/dist/timeline/types.d.ts +0 -12
- package/dist/timeline/types.js +0 -1
- package/dist/types.d.ts +0 -216
- package/dist/types.js +0 -3
- package/dist/util/auto-heal.d.ts +0 -43
- package/dist/util/auto-heal.js +0 -107
- package/dist/util/install-info.d.ts +0 -37
- package/dist/util/install-info.js +0 -80
- package/dist/util/logger.d.ts +0 -18
- package/dist/util/logger.js +0 -118
- package/dist/util/paths.d.ts +0 -13
- package/dist/util/paths.js +0 -55
- package/dist/util/platform.d.ts +0 -2
- package/dist/util/platform.js +0 -11
- package/dist/util/progress.d.ts +0 -34
- package/dist/util/progress.js +0 -133
- package/dist/util/rate-limiter.d.ts +0 -14
- package/dist/util/rate-limiter.js +0 -50
- package/dist/util/retry.d.ts +0 -2
- package/dist/util/retry.js +0 -18
- package/dist/util/text.d.ts +0 -32
- package/dist/util/text.js +0 -101
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -4
- package/dist/voice/index.d.ts +0 -17
- package/dist/voice/index.js +0 -42
- package/dist/voice/stt.d.ts +0 -16
- package/dist/voice/stt.js +0 -57
- package/dist/voice/tts.d.ts +0 -23
- package/dist/voice/tts.js +0 -84
- package/dist/watchers/evaluator.d.ts +0 -5
- package/dist/watchers/evaluator.js +0 -45
- package/dist/watchers/index.d.ts +0 -4
- package/dist/watchers/index.js +0 -3
- package/dist/watchers/scheduler.d.ts +0 -20
- package/dist/watchers/scheduler.js +0 -183
- package/dist/watchers/store.d.ts +0 -10
- package/dist/watchers/store.js +0 -56
- package/dist/watchers/types.d.ts +0 -15
- package/dist/watchers/types.js +0 -1
- package/scripts/postinstall.mjs +0 -50
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export class NtfyProvider {
|
|
2
|
-
topic;
|
|
3
|
-
server;
|
|
4
|
-
id = 'ntfy';
|
|
5
|
-
name = 'ntfy.sh';
|
|
6
|
-
constructor(topic, server = 'https://ntfy.sh') {
|
|
7
|
-
this.topic = topic;
|
|
8
|
-
this.server = server;
|
|
9
|
-
}
|
|
10
|
-
async send(message, urgent) {
|
|
11
|
-
const response = await fetch(`${this.server}/${this.topic}`, {
|
|
12
|
-
method: 'POST',
|
|
13
|
-
headers: {
|
|
14
|
-
Title: 'Beecork',
|
|
15
|
-
Priority: urgent ? '5' : '3',
|
|
16
|
-
Tags: urgent ? 'warning' : 'robot',
|
|
17
|
-
},
|
|
18
|
-
body: message,
|
|
19
|
-
signal: AbortSignal.timeout(10000),
|
|
20
|
-
});
|
|
21
|
-
if (!response.ok) {
|
|
22
|
-
throw new Error(`ntfy error: ${response.status}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { NotificationProvider } from './types.js';
|
|
2
|
-
export declare class PushoverProvider implements NotificationProvider {
|
|
3
|
-
private userKey;
|
|
4
|
-
private appToken;
|
|
5
|
-
readonly id = "pushover";
|
|
6
|
-
readonly name = "Pushover";
|
|
7
|
-
constructor(userKey: string, appToken: string);
|
|
8
|
-
send(message: string, urgent?: boolean): Promise<void>;
|
|
9
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export class PushoverProvider {
|
|
2
|
-
userKey;
|
|
3
|
-
appToken;
|
|
4
|
-
id = 'pushover';
|
|
5
|
-
name = 'Pushover';
|
|
6
|
-
constructor(userKey, appToken) {
|
|
7
|
-
this.userKey = userKey;
|
|
8
|
-
this.appToken = appToken;
|
|
9
|
-
}
|
|
10
|
-
async send(message, urgent) {
|
|
11
|
-
const response = await fetch('https://api.pushover.net/1/messages.json', {
|
|
12
|
-
method: 'POST',
|
|
13
|
-
headers: { 'Content-Type': 'application/json' },
|
|
14
|
-
body: JSON.stringify({
|
|
15
|
-
token: this.appToken,
|
|
16
|
-
user: this.userKey,
|
|
17
|
-
message: message.slice(0, 1024),
|
|
18
|
-
priority: urgent ? 1 : 0,
|
|
19
|
-
}),
|
|
20
|
-
signal: AbortSignal.timeout(10000),
|
|
21
|
-
});
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
throw new Error(`Pushover API error: ${response.status}`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { NotificationProvider } from './types.js';
|
|
2
|
-
export declare class WebhookNotificationProvider implements NotificationProvider {
|
|
3
|
-
private url;
|
|
4
|
-
private headers?;
|
|
5
|
-
readonly id = "webhook-notify";
|
|
6
|
-
readonly name = "Webhook";
|
|
7
|
-
constructor(url: string, headers?: Record<string, string> | undefined);
|
|
8
|
-
send(message: string, urgent?: boolean): Promise<void>;
|
|
9
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export class WebhookNotificationProvider {
|
|
2
|
-
url;
|
|
3
|
-
headers;
|
|
4
|
-
id = 'webhook-notify';
|
|
5
|
-
name = 'Webhook';
|
|
6
|
-
constructor(url, headers) {
|
|
7
|
-
this.url = url;
|
|
8
|
-
this.headers = headers;
|
|
9
|
-
}
|
|
10
|
-
async send(message, urgent) {
|
|
11
|
-
const response = await fetch(this.url, {
|
|
12
|
-
method: 'POST',
|
|
13
|
-
headers: {
|
|
14
|
-
'Content-Type': 'application/json',
|
|
15
|
-
...this.headers,
|
|
16
|
-
},
|
|
17
|
-
body: JSON.stringify({ message, urgent: !!urgent, timestamp: new Date().toISOString() }),
|
|
18
|
-
signal: AbortSignal.timeout(10000),
|
|
19
|
-
});
|
|
20
|
-
if (!response.ok) {
|
|
21
|
-
throw new Error(`Webhook notification error: ${response.status}`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type Database from 'better-sqlite3';
|
|
2
|
-
export interface CostSummary {
|
|
3
|
-
today: number;
|
|
4
|
-
last7Days: number;
|
|
5
|
-
last30Days: number;
|
|
6
|
-
perTab: Array<{
|
|
7
|
-
name: string;
|
|
8
|
-
cost: number;
|
|
9
|
-
messages: number;
|
|
10
|
-
}>;
|
|
11
|
-
}
|
|
12
|
-
export interface ActivitySummary {
|
|
13
|
-
period: string;
|
|
14
|
-
messagesReceived: number;
|
|
15
|
-
messagesFromAssistant: number;
|
|
16
|
-
tasksFired: number;
|
|
17
|
-
memoriesCreated: number;
|
|
18
|
-
totalCost: number;
|
|
19
|
-
activeTabsCount: number;
|
|
20
|
-
}
|
|
21
|
-
export declare function getCostSummary(): CostSummary;
|
|
22
|
-
export declare function getActivitySummary(hours?: number): ActivitySummary;
|
|
23
|
-
/**
|
|
24
|
-
* Returns a notification only on state transitions (ok↔breach), persisting
|
|
25
|
-
* the state in the `preferences` table so daemon restarts don't re-fire.
|
|
26
|
-
*/
|
|
27
|
-
export declare function checkAnomaliesWithDb(db: Database.Database): string | null;
|
|
28
|
-
export declare function checkAnomalies(): string | null;
|
|
29
|
-
export declare function formatCostSummary(summary: CostSummary): string;
|
|
30
|
-
export declare function formatActivitySummary(summary: ActivitySummary): string;
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { getDb } from '../db/index.js';
|
|
2
|
-
export function getCostSummary() {
|
|
3
|
-
const db = getDb();
|
|
4
|
-
const today = db
|
|
5
|
-
.prepare("SELECT COALESCE(SUM(cost_usd), 0) as total FROM messages WHERE created_at > date('now')")
|
|
6
|
-
.get().total;
|
|
7
|
-
const last7 = db
|
|
8
|
-
.prepare("SELECT COALESCE(SUM(cost_usd), 0) as total FROM messages WHERE created_at > date('now', '-7 days')")
|
|
9
|
-
.get().total;
|
|
10
|
-
const last30 = db
|
|
11
|
-
.prepare("SELECT COALESCE(SUM(cost_usd), 0) as total FROM messages WHERE created_at > date('now', '-30 days')")
|
|
12
|
-
.get().total;
|
|
13
|
-
// Per-tab summed over the last 30 days only — the unbounded version grew
|
|
14
|
-
// linearly with the messages table and made /cost noticeably slow over time.
|
|
15
|
-
const perTab = db
|
|
16
|
-
.prepare(`
|
|
17
|
-
SELECT t.name, COALESCE(SUM(m.cost_usd), 0) as cost, COUNT(m.id) as messages
|
|
18
|
-
FROM tabs t LEFT JOIN messages m ON m.tab_id = t.id
|
|
19
|
-
AND m.created_at > date('now', '-30 days')
|
|
20
|
-
GROUP BY t.id ORDER BY cost DESC
|
|
21
|
-
`)
|
|
22
|
-
.all();
|
|
23
|
-
return { today, last7Days: last7, last30Days: last30, perTab };
|
|
24
|
-
}
|
|
25
|
-
export function getActivitySummary(hours = 24) {
|
|
26
|
-
const db = getDb();
|
|
27
|
-
const sinceDate = new Date(Date.now() - hours * 3600000).toISOString();
|
|
28
|
-
const messagesReceived = db
|
|
29
|
-
.prepare('SELECT COUNT(*) as c FROM messages WHERE role = ? AND created_at > ?')
|
|
30
|
-
.get('user', sinceDate).c;
|
|
31
|
-
const messagesFromAssistant = db
|
|
32
|
-
.prepare('SELECT COUNT(*) as c FROM messages WHERE role = ? AND created_at > ?')
|
|
33
|
-
.get('assistant', sinceDate).c;
|
|
34
|
-
const tasksFired = db.prepare('SELECT COUNT(*) as c FROM tasks WHERE last_run_at > ?').get(sinceDate).c;
|
|
35
|
-
const memoriesCreated = db.prepare('SELECT COUNT(*) as c FROM memories WHERE created_at > ?').get(sinceDate).c;
|
|
36
|
-
const totalCost = db
|
|
37
|
-
.prepare('SELECT COALESCE(SUM(cost_usd), 0) as total FROM messages WHERE created_at > ?')
|
|
38
|
-
.get(sinceDate).total;
|
|
39
|
-
const activeTabsCount = db
|
|
40
|
-
.prepare('SELECT COUNT(DISTINCT tab_id) as c FROM messages WHERE created_at > ?')
|
|
41
|
-
.get(sinceDate).c;
|
|
42
|
-
return {
|
|
43
|
-
period: `Last ${hours} hours`,
|
|
44
|
-
messagesReceived,
|
|
45
|
-
messagesFromAssistant,
|
|
46
|
-
tasksFired,
|
|
47
|
-
memoriesCreated,
|
|
48
|
-
totalCost,
|
|
49
|
-
activeTabsCount,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
const ANOMALY_STATE_KEY = 'anomaly_spend_state';
|
|
53
|
-
/**
|
|
54
|
-
* Returns a notification only on state transitions (ok↔breach), persisting
|
|
55
|
-
* the state in the `preferences` table so daemon restarts don't re-fire.
|
|
56
|
-
*/
|
|
57
|
-
export function checkAnomaliesWithDb(db) {
|
|
58
|
-
// Today's spend
|
|
59
|
-
const todaySpend = db
|
|
60
|
-
.prepare("SELECT COALESCE(SUM(cost_usd), 0) as total FROM messages WHERE created_at > date('now')")
|
|
61
|
-
.get().total;
|
|
62
|
-
// 7-day rolling average (excluding today)
|
|
63
|
-
const avgSpend = db
|
|
64
|
-
.prepare(`
|
|
65
|
-
SELECT COALESCE(AVG(daily_total), 0) as avg FROM (
|
|
66
|
-
SELECT date(created_at) as day, SUM(cost_usd) as daily_total
|
|
67
|
-
FROM messages
|
|
68
|
-
WHERE created_at > date('now', '-7 days') AND created_at < date('now')
|
|
69
|
-
GROUP BY date(created_at)
|
|
70
|
-
)
|
|
71
|
-
`)
|
|
72
|
-
.get().avg;
|
|
73
|
-
const isBreach = avgSpend > 0 && todaySpend > avgSpend * 2;
|
|
74
|
-
const newState = isBreach ? 'breach' : 'ok';
|
|
75
|
-
const prevRow = db
|
|
76
|
-
.prepare('SELECT value FROM preferences WHERE key = ?')
|
|
77
|
-
.get(ANOMALY_STATE_KEY);
|
|
78
|
-
const prevState = prevRow?.value ?? 'ok';
|
|
79
|
-
if (newState === prevState)
|
|
80
|
-
return null;
|
|
81
|
-
db.prepare(`INSERT INTO preferences (key, value, updated_at) VALUES (?, ?, datetime('now'))
|
|
82
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = datetime('now')`).run(ANOMALY_STATE_KEY, newState);
|
|
83
|
-
if (isBreach) {
|
|
84
|
-
return `⚠️ Anomaly: Today's spend ($${todaySpend.toFixed(4)}) exceeds 2x your 7-day average ($${avgSpend.toFixed(4)}/day)`;
|
|
85
|
-
}
|
|
86
|
-
return `✅ Recovered: Today's spend ($${todaySpend.toFixed(4)}) is back within 2x your 7-day average ($${avgSpend.toFixed(4)}/day)`;
|
|
87
|
-
}
|
|
88
|
-
export function checkAnomalies() {
|
|
89
|
-
return checkAnomaliesWithDb(getDb());
|
|
90
|
-
}
|
|
91
|
-
export function formatCostSummary(summary) {
|
|
92
|
-
const lines = [
|
|
93
|
-
`💰 Cost Summary`,
|
|
94
|
-
` Today: $${summary.today.toFixed(4)}`,
|
|
95
|
-
` 7 days: $${summary.last7Days.toFixed(4)}`,
|
|
96
|
-
` 30 days: $${summary.last30Days.toFixed(4)}`,
|
|
97
|
-
];
|
|
98
|
-
if (summary.perTab.length > 0) {
|
|
99
|
-
lines.push('', ' Per tab:');
|
|
100
|
-
for (const tab of summary.perTab.slice(0, 10)) {
|
|
101
|
-
if (tab.cost > 0) {
|
|
102
|
-
lines.push(` ${tab.name}: $${tab.cost.toFixed(4)} (${tab.messages} msgs)`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return lines.join('\n');
|
|
107
|
-
}
|
|
108
|
-
export function formatActivitySummary(summary) {
|
|
109
|
-
return [
|
|
110
|
-
`📊 Activity (${summary.period})`,
|
|
111
|
-
` Messages in: ${summary.messagesReceived}`,
|
|
112
|
-
` Messages out: ${summary.messagesFromAssistant}`,
|
|
113
|
-
` Tasks fired: ${summary.tasksFired}`,
|
|
114
|
-
` Memories created: ${summary.memoriesCreated}`,
|
|
115
|
-
` Active tabs: ${summary.activeTabsCount}`,
|
|
116
|
-
` Cost: $${summary.totalCost.toFixed(4)}`,
|
|
117
|
-
].join('\n');
|
|
118
|
-
}
|
package/dist/projects/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export type { Project, RouteDecision, RoutingContext } from './types.js';
|
|
2
|
-
export { discoverProjects, createProject, listProjects, getProject, ensureCategory, touchProject, } from './manager.js';
|
|
3
|
-
export { routeMessage, setUserContext, resolveProjectRoute } from './router.js';
|
|
4
|
-
export type { RouteResult } from './router.js';
|
package/dist/projects/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Project } from './types.js';
|
|
2
|
-
/** Discover projects in scan paths (look for git repos, package.json, etc.) */
|
|
3
|
-
export declare function discoverProjects(scanPaths?: string[]): Project[];
|
|
4
|
-
/** Create a new project. parentDir must resolve under an allowed root. */
|
|
5
|
-
export declare function createProject(name: string, parentDir?: string): Project;
|
|
6
|
-
/** Ensure a managed category exists (lazy creation) */
|
|
7
|
-
export declare function ensureCategory(name: string): Project;
|
|
8
|
-
/** List all projects */
|
|
9
|
-
export declare function listProjects(): Project[];
|
|
10
|
-
/** Get a project by name */
|
|
11
|
-
export declare function getProject(name: string): Project | null;
|
|
12
|
-
/** Update last used timestamp */
|
|
13
|
-
export declare function touchProject(name: string): void;
|
package/dist/projects/manager.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
-
import { getDb } from '../db/index.js';
|
|
5
|
-
import { getConfig } from '../config.js';
|
|
6
|
-
import { expandHome } from '../util/paths.js';
|
|
7
|
-
import { logger } from '../util/logger.js';
|
|
8
|
-
import { invalidateProjectCache } from './router.js';
|
|
9
|
-
function rowToProject(r) {
|
|
10
|
-
return {
|
|
11
|
-
id: r.id,
|
|
12
|
-
name: r.name,
|
|
13
|
-
path: r.path,
|
|
14
|
-
type: r.type,
|
|
15
|
-
lastUsedAt: r.last_used_at,
|
|
16
|
-
createdAt: r.created_at,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/** Get the workspace root from config (module-local) */
|
|
20
|
-
function getWorkspaceRoot() {
|
|
21
|
-
const config = getConfig();
|
|
22
|
-
// Use the default tab's workingDir as workspace root
|
|
23
|
-
const root = config.tabs?.default?.workingDir || process.env.HOME || '';
|
|
24
|
-
return expandHome(root);
|
|
25
|
-
}
|
|
26
|
-
/** Get the managed workspace path (.beecork/ under workspace root) (module-local) */
|
|
27
|
-
function getManagedWorkspace() {
|
|
28
|
-
return path.join(getWorkspaceRoot(), '.beecork');
|
|
29
|
-
}
|
|
30
|
-
/** Discover projects in scan paths (look for git repos, package.json, etc.) */
|
|
31
|
-
export function discoverProjects(scanPaths) {
|
|
32
|
-
const paths = scanPaths || [getWorkspaceRoot()];
|
|
33
|
-
const projects = [];
|
|
34
|
-
const db = getDb();
|
|
35
|
-
for (let scanPath of paths) {
|
|
36
|
-
scanPath = expandHome(scanPath);
|
|
37
|
-
if (!fs.existsSync(scanPath))
|
|
38
|
-
continue;
|
|
39
|
-
try {
|
|
40
|
-
const entries = fs.readdirSync(scanPath, { withFileTypes: true });
|
|
41
|
-
for (const entry of entries) {
|
|
42
|
-
if (!entry.isDirectory())
|
|
43
|
-
continue;
|
|
44
|
-
if (entry.name.startsWith('.'))
|
|
45
|
-
continue; // Skip hidden dirs
|
|
46
|
-
if (entry.name === 'node_modules')
|
|
47
|
-
continue;
|
|
48
|
-
const dirPath = path.join(scanPath, entry.name);
|
|
49
|
-
// Check if it looks like a project (has .git, package.json, or similar)
|
|
50
|
-
const isProject = fs.existsSync(path.join(dirPath, '.git')) ||
|
|
51
|
-
fs.existsSync(path.join(dirPath, 'package.json')) ||
|
|
52
|
-
fs.existsSync(path.join(dirPath, 'Cargo.toml')) ||
|
|
53
|
-
fs.existsSync(path.join(dirPath, 'go.mod')) ||
|
|
54
|
-
fs.existsSync(path.join(dirPath, 'requirements.txt')) ||
|
|
55
|
-
fs.existsSync(path.join(dirPath, 'pyproject.toml')) ||
|
|
56
|
-
fs.existsSync(path.join(dirPath, 'CLAUDE.md'));
|
|
57
|
-
if (isProject) {
|
|
58
|
-
projects.push({
|
|
59
|
-
id: uuidv4(),
|
|
60
|
-
name: entry.name,
|
|
61
|
-
path: dirPath,
|
|
62
|
-
type: 'user-project',
|
|
63
|
-
lastUsedAt: new Date().toISOString(),
|
|
64
|
-
createdAt: new Date().toISOString(),
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch (err) {
|
|
70
|
-
logger.warn(`Failed to scan ${scanPath}:`, err);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Upsert into database
|
|
74
|
-
for (const project of projects) {
|
|
75
|
-
db.prepare(`
|
|
76
|
-
INSERT INTO projects (id, name, path, type) VALUES (?, ?, ?, ?)
|
|
77
|
-
ON CONFLICT(name) DO UPDATE SET path = excluded.path, last_used_at = datetime('now')
|
|
78
|
-
`).run(project.id, project.name, project.path, project.type);
|
|
79
|
-
}
|
|
80
|
-
invalidateProjectCache();
|
|
81
|
-
return projects;
|
|
82
|
-
}
|
|
83
|
-
/** Create a new project. parentDir must resolve under an allowed root. */
|
|
84
|
-
export function createProject(name, parentDir) {
|
|
85
|
-
const requestedParent = parentDir || getWorkspaceRoot();
|
|
86
|
-
const resolvedParent = path.resolve(expandHome(requestedParent));
|
|
87
|
-
// Allowlist: parent must resolve under workspace root or one of the configured scan paths.
|
|
88
|
-
const config = getConfig();
|
|
89
|
-
const allowedRoots = [getWorkspaceRoot(), ...(config.projectScanPaths ?? [])].map((r) => path.resolve(expandHome(r)));
|
|
90
|
-
const isAllowed = allowedRoots.some((root) => resolvedParent === root || resolvedParent.startsWith(root + path.sep));
|
|
91
|
-
if (!isAllowed) {
|
|
92
|
-
throw new Error(`Project parent directory must be under workspace root or a configured scan path. Allowed: ${allowedRoots.join(', ')}`);
|
|
93
|
-
}
|
|
94
|
-
// Sanitize name to prevent path traversal
|
|
95
|
-
const safeName = path.basename(name.replace(/\.\./g, ''));
|
|
96
|
-
if (!safeName)
|
|
97
|
-
throw new Error('Invalid project name');
|
|
98
|
-
const projectPath = path.resolve(resolvedParent, safeName);
|
|
99
|
-
// Ensure resolved path is within the parent directory
|
|
100
|
-
if (!projectPath.startsWith(resolvedParent)) {
|
|
101
|
-
throw new Error('Project path must be within the parent directory');
|
|
102
|
-
}
|
|
103
|
-
if (fs.existsSync(projectPath)) {
|
|
104
|
-
// Folder already exists — just register it
|
|
105
|
-
logger.info(`Project folder already exists: ${projectPath}`);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
fs.mkdirSync(projectPath, { recursive: true });
|
|
109
|
-
logger.info(`Created project folder: ${projectPath}`);
|
|
110
|
-
}
|
|
111
|
-
const db = getDb();
|
|
112
|
-
const id = uuidv4();
|
|
113
|
-
db.prepare(`
|
|
114
|
-
INSERT INTO projects (id, name, path, type) VALUES (?, ?, ?, ?)
|
|
115
|
-
ON CONFLICT(name) DO UPDATE SET path = excluded.path
|
|
116
|
-
`).run(id, name, projectPath, 'user-project');
|
|
117
|
-
invalidateProjectCache();
|
|
118
|
-
return {
|
|
119
|
-
id,
|
|
120
|
-
name,
|
|
121
|
-
path: projectPath,
|
|
122
|
-
type: 'user-project',
|
|
123
|
-
lastUsedAt: new Date().toISOString(),
|
|
124
|
-
createdAt: new Date().toISOString(),
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
/** Ensure a managed category exists (lazy creation) */
|
|
128
|
-
export function ensureCategory(name) {
|
|
129
|
-
const categoryPath = path.join(getManagedWorkspace(), name);
|
|
130
|
-
fs.mkdirSync(categoryPath, { recursive: true });
|
|
131
|
-
const db = getDb();
|
|
132
|
-
const existing = db
|
|
133
|
-
.prepare('SELECT * FROM projects WHERE name = ? AND type = ?')
|
|
134
|
-
.get(name, 'category');
|
|
135
|
-
if (existing)
|
|
136
|
-
return rowToProject(existing);
|
|
137
|
-
const id = uuidv4();
|
|
138
|
-
db.prepare('INSERT INTO projects (id, name, path, type) VALUES (?, ?, ?, ?)').run(id, name, categoryPath, 'category');
|
|
139
|
-
invalidateProjectCache();
|
|
140
|
-
return {
|
|
141
|
-
id,
|
|
142
|
-
name,
|
|
143
|
-
path: categoryPath,
|
|
144
|
-
type: 'category',
|
|
145
|
-
lastUsedAt: new Date().toISOString(),
|
|
146
|
-
createdAt: new Date().toISOString(),
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
/** List all projects */
|
|
150
|
-
export function listProjects() {
|
|
151
|
-
const db = getDb();
|
|
152
|
-
const rows = db
|
|
153
|
-
.prepare('SELECT * FROM projects ORDER BY type, last_used_at DESC')
|
|
154
|
-
.all();
|
|
155
|
-
return rows.map(rowToProject);
|
|
156
|
-
}
|
|
157
|
-
/** Get a project by name */
|
|
158
|
-
export function getProject(name) {
|
|
159
|
-
const db = getDb();
|
|
160
|
-
const row = db.prepare('SELECT * FROM projects WHERE name = ?').get(name);
|
|
161
|
-
return row ? rowToProject(row) : null;
|
|
162
|
-
}
|
|
163
|
-
/** Update last used timestamp */
|
|
164
|
-
export function touchProject(name) {
|
|
165
|
-
getDb().prepare("UPDATE projects SET last_used_at = datetime('now') WHERE name = ?").run(name);
|
|
166
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { RouteDecision, RoutingContext } from './types.js';
|
|
2
|
-
/** Invalidate the project cache. Call after createProject/discoverProjects/etc. */
|
|
3
|
-
export declare function invalidateProjectCache(): void;
|
|
4
|
-
/** Route a message to the right project and tab */
|
|
5
|
-
export declare function routeMessage(message: string, context?: RoutingContext): RouteDecision;
|
|
6
|
-
/** Update current context for a user */
|
|
7
|
-
export declare function setUserContext(userId: string, projectName: string, tabName: string): void;
|
|
8
|
-
export interface RouteResult {
|
|
9
|
-
effectiveTabName: string;
|
|
10
|
-
projectPath?: string;
|
|
11
|
-
confirmationMessage?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Shared project routing logic — resolves which tab/project to use for a message.
|
|
15
|
-
* Pulled out of channels/ so all routing decisions live in one place.
|
|
16
|
-
*/
|
|
17
|
-
export declare function resolveProjectRoute(rawPrompt: string, tabName: string, text: string, userId: string): Promise<RouteResult>;
|