@usejarvis/brain 0.1.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/LICENSE +153 -0
- package/README.md +278 -0
- package/bin/jarvis.ts +413 -0
- package/package.json +74 -0
- package/scripts/ensure-bun.cjs +8 -0
- package/src/actions/README.md +421 -0
- package/src/actions/app-control/desktop-controller.test.ts +26 -0
- package/src/actions/app-control/desktop-controller.ts +438 -0
- package/src/actions/app-control/interface.ts +64 -0
- package/src/actions/app-control/linux.ts +273 -0
- package/src/actions/app-control/macos.ts +54 -0
- package/src/actions/app-control/sidecar-launcher.test.ts +23 -0
- package/src/actions/app-control/sidecar-launcher.ts +286 -0
- package/src/actions/app-control/windows.ts +44 -0
- package/src/actions/browser/cdp.ts +138 -0
- package/src/actions/browser/chrome-launcher.ts +252 -0
- package/src/actions/browser/session.ts +437 -0
- package/src/actions/browser/stealth.ts +49 -0
- package/src/actions/index.ts +20 -0
- package/src/actions/terminal/executor.ts +157 -0
- package/src/actions/terminal/wsl-bridge.ts +126 -0
- package/src/actions/test.ts +93 -0
- package/src/actions/tools/agents.ts +321 -0
- package/src/actions/tools/builtin.ts +846 -0
- package/src/actions/tools/commitments.ts +192 -0
- package/src/actions/tools/content.ts +217 -0
- package/src/actions/tools/delegate.ts +147 -0
- package/src/actions/tools/desktop.test.ts +55 -0
- package/src/actions/tools/desktop.ts +305 -0
- package/src/actions/tools/goals.ts +376 -0
- package/src/actions/tools/local-tools-guard.ts +20 -0
- package/src/actions/tools/registry.ts +171 -0
- package/src/actions/tools/research.ts +111 -0
- package/src/actions/tools/sidecar-list.ts +57 -0
- package/src/actions/tools/sidecar-route.ts +105 -0
- package/src/actions/tools/workflows.ts +216 -0
- package/src/agents/agent.ts +132 -0
- package/src/agents/delegation.ts +107 -0
- package/src/agents/hierarchy.ts +113 -0
- package/src/agents/index.ts +19 -0
- package/src/agents/messaging.ts +125 -0
- package/src/agents/orchestrator.ts +576 -0
- package/src/agents/role-discovery.ts +61 -0
- package/src/agents/sub-agent-runner.ts +307 -0
- package/src/agents/task-manager.ts +151 -0
- package/src/authority/approval-delivery.ts +59 -0
- package/src/authority/approval.ts +196 -0
- package/src/authority/audit.ts +158 -0
- package/src/authority/authority.test.ts +519 -0
- package/src/authority/deferred-executor.ts +103 -0
- package/src/authority/emergency.ts +66 -0
- package/src/authority/engine.ts +297 -0
- package/src/authority/index.ts +12 -0
- package/src/authority/learning.ts +111 -0
- package/src/authority/tool-action-map.ts +74 -0
- package/src/awareness/analytics.ts +466 -0
- package/src/awareness/awareness.test.ts +332 -0
- package/src/awareness/capture-engine.ts +305 -0
- package/src/awareness/context-graph.ts +130 -0
- package/src/awareness/context-tracker.ts +349 -0
- package/src/awareness/index.ts +25 -0
- package/src/awareness/intelligence.ts +321 -0
- package/src/awareness/ocr-engine.ts +88 -0
- package/src/awareness/service.ts +528 -0
- package/src/awareness/struggle-detector.ts +342 -0
- package/src/awareness/suggestion-engine.ts +476 -0
- package/src/awareness/types.ts +201 -0
- package/src/cli/autostart.ts +241 -0
- package/src/cli/deps.ts +449 -0
- package/src/cli/doctor.ts +230 -0
- package/src/cli/helpers.ts +401 -0
- package/src/cli/onboard.ts +580 -0
- package/src/comms/README.md +329 -0
- package/src/comms/auth-error.html +48 -0
- package/src/comms/channels/discord.ts +228 -0
- package/src/comms/channels/signal.ts +56 -0
- package/src/comms/channels/telegram.ts +316 -0
- package/src/comms/channels/whatsapp.ts +60 -0
- package/src/comms/channels.test.ts +173 -0
- package/src/comms/desktop-notify.ts +114 -0
- package/src/comms/example.ts +129 -0
- package/src/comms/index.ts +129 -0
- package/src/comms/streaming.ts +142 -0
- package/src/comms/voice.test.ts +152 -0
- package/src/comms/voice.ts +291 -0
- package/src/comms/websocket.test.ts +409 -0
- package/src/comms/websocket.ts +473 -0
- package/src/config/README.md +387 -0
- package/src/config/index.ts +6 -0
- package/src/config/loader.test.ts +137 -0
- package/src/config/loader.ts +142 -0
- package/src/config/types.ts +260 -0
- package/src/daemon/README.md +232 -0
- package/src/daemon/agent-service-interface.ts +9 -0
- package/src/daemon/agent-service.ts +600 -0
- package/src/daemon/api-routes.ts +2119 -0
- package/src/daemon/background-agent-service.ts +396 -0
- package/src/daemon/background-agent.test.ts +78 -0
- package/src/daemon/channel-service.ts +201 -0
- package/src/daemon/commitment-executor.ts +297 -0
- package/src/daemon/event-classifier.ts +239 -0
- package/src/daemon/event-coalescer.ts +123 -0
- package/src/daemon/event-reactor.ts +214 -0
- package/src/daemon/health.ts +220 -0
- package/src/daemon/index.ts +1004 -0
- package/src/daemon/llm-settings.ts +316 -0
- package/src/daemon/observer-service.ts +150 -0
- package/src/daemon/pid.ts +98 -0
- package/src/daemon/research-queue.ts +155 -0
- package/src/daemon/services.ts +175 -0
- package/src/daemon/ws-service.ts +788 -0
- package/src/goals/accountability.ts +240 -0
- package/src/goals/awareness-bridge.ts +185 -0
- package/src/goals/estimator.ts +185 -0
- package/src/goals/events.ts +28 -0
- package/src/goals/goals.test.ts +400 -0
- package/src/goals/integration.test.ts +329 -0
- package/src/goals/nl-builder.test.ts +220 -0
- package/src/goals/nl-builder.ts +256 -0
- package/src/goals/rhythm.test.ts +177 -0
- package/src/goals/rhythm.ts +275 -0
- package/src/goals/service.test.ts +135 -0
- package/src/goals/service.ts +348 -0
- package/src/goals/types.ts +106 -0
- package/src/goals/workflow-bridge.ts +96 -0
- package/src/integrations/google-api.ts +134 -0
- package/src/integrations/google-auth.ts +175 -0
- package/src/llm/README.md +291 -0
- package/src/llm/anthropic.ts +386 -0
- package/src/llm/gemini.ts +371 -0
- package/src/llm/index.ts +19 -0
- package/src/llm/manager.ts +153 -0
- package/src/llm/ollama.ts +307 -0
- package/src/llm/openai.ts +350 -0
- package/src/llm/provider.test.ts +231 -0
- package/src/llm/provider.ts +60 -0
- package/src/llm/test.ts +87 -0
- package/src/observers/README.md +278 -0
- package/src/observers/calendar.ts +113 -0
- package/src/observers/clipboard.ts +136 -0
- package/src/observers/email.ts +109 -0
- package/src/observers/example.ts +58 -0
- package/src/observers/file-watcher.ts +124 -0
- package/src/observers/index.ts +159 -0
- package/src/observers/notifications.ts +197 -0
- package/src/observers/observers.test.ts +203 -0
- package/src/observers/processes.ts +225 -0
- package/src/personality/README.md +61 -0
- package/src/personality/adapter.ts +196 -0
- package/src/personality/index.ts +20 -0
- package/src/personality/learner.ts +209 -0
- package/src/personality/model.ts +132 -0
- package/src/personality/personality.test.ts +236 -0
- package/src/roles/README.md +252 -0
- package/src/roles/authority.ts +119 -0
- package/src/roles/example-usage.ts +198 -0
- package/src/roles/index.ts +42 -0
- package/src/roles/loader.ts +143 -0
- package/src/roles/prompt-builder.ts +194 -0
- package/src/roles/test-multi.ts +102 -0
- package/src/roles/test-role.yaml +77 -0
- package/src/roles/test-utils.ts +93 -0
- package/src/roles/test.ts +106 -0
- package/src/roles/tool-guide.ts +190 -0
- package/src/roles/types.ts +36 -0
- package/src/roles/utils.ts +200 -0
- package/src/scripts/google-setup.ts +168 -0
- package/src/sidecar/connection.ts +179 -0
- package/src/sidecar/index.ts +6 -0
- package/src/sidecar/manager.ts +542 -0
- package/src/sidecar/protocol.ts +85 -0
- package/src/sidecar/rpc.ts +161 -0
- package/src/sidecar/scheduler.ts +136 -0
- package/src/sidecar/types.ts +112 -0
- package/src/sidecar/validator.ts +144 -0
- package/src/vault/README.md +110 -0
- package/src/vault/awareness.ts +341 -0
- package/src/vault/commitments.ts +299 -0
- package/src/vault/content-pipeline.ts +260 -0
- package/src/vault/conversations.ts +173 -0
- package/src/vault/entities.ts +180 -0
- package/src/vault/extractor.test.ts +356 -0
- package/src/vault/extractor.ts +345 -0
- package/src/vault/facts.ts +190 -0
- package/src/vault/goals.ts +477 -0
- package/src/vault/index.ts +87 -0
- package/src/vault/keychain.ts +99 -0
- package/src/vault/observations.ts +115 -0
- package/src/vault/relationships.ts +178 -0
- package/src/vault/retrieval.test.ts +126 -0
- package/src/vault/retrieval.ts +227 -0
- package/src/vault/schema.ts +658 -0
- package/src/vault/settings.ts +38 -0
- package/src/vault/vectors.ts +92 -0
- package/src/vault/workflows.ts +403 -0
- package/src/workflows/auto-suggest.ts +290 -0
- package/src/workflows/engine.ts +366 -0
- package/src/workflows/events.ts +24 -0
- package/src/workflows/executor.ts +207 -0
- package/src/workflows/nl-builder.ts +198 -0
- package/src/workflows/nodes/actions/agent-task.ts +73 -0
- package/src/workflows/nodes/actions/calendar-action.ts +85 -0
- package/src/workflows/nodes/actions/code-execution.ts +73 -0
- package/src/workflows/nodes/actions/discord.ts +77 -0
- package/src/workflows/nodes/actions/file-write.ts +73 -0
- package/src/workflows/nodes/actions/gmail.ts +69 -0
- package/src/workflows/nodes/actions/http-request.ts +117 -0
- package/src/workflows/nodes/actions/notification.ts +85 -0
- package/src/workflows/nodes/actions/run-tool.ts +55 -0
- package/src/workflows/nodes/actions/send-message.ts +82 -0
- package/src/workflows/nodes/actions/shell-command.ts +76 -0
- package/src/workflows/nodes/actions/telegram.ts +60 -0
- package/src/workflows/nodes/builtin.ts +119 -0
- package/src/workflows/nodes/error/error-handler.ts +37 -0
- package/src/workflows/nodes/error/fallback.ts +47 -0
- package/src/workflows/nodes/error/retry.ts +82 -0
- package/src/workflows/nodes/logic/delay.ts +42 -0
- package/src/workflows/nodes/logic/if-else.ts +41 -0
- package/src/workflows/nodes/logic/loop.ts +90 -0
- package/src/workflows/nodes/logic/merge.ts +38 -0
- package/src/workflows/nodes/logic/race.ts +40 -0
- package/src/workflows/nodes/logic/switch.ts +59 -0
- package/src/workflows/nodes/logic/template-render.ts +53 -0
- package/src/workflows/nodes/logic/variable-get.ts +37 -0
- package/src/workflows/nodes/logic/variable-set.ts +59 -0
- package/src/workflows/nodes/registry.ts +99 -0
- package/src/workflows/nodes/transform/aggregate.ts +99 -0
- package/src/workflows/nodes/transform/csv-parse.ts +70 -0
- package/src/workflows/nodes/transform/json-parse.ts +63 -0
- package/src/workflows/nodes/transform/map-filter.ts +84 -0
- package/src/workflows/nodes/transform/regex-match.ts +89 -0
- package/src/workflows/nodes/triggers/calendar.ts +33 -0
- package/src/workflows/nodes/triggers/clipboard.ts +32 -0
- package/src/workflows/nodes/triggers/cron.ts +40 -0
- package/src/workflows/nodes/triggers/email.ts +40 -0
- package/src/workflows/nodes/triggers/file-change.ts +45 -0
- package/src/workflows/nodes/triggers/git.ts +46 -0
- package/src/workflows/nodes/triggers/manual.ts +23 -0
- package/src/workflows/nodes/triggers/poll.ts +81 -0
- package/src/workflows/nodes/triggers/process.ts +44 -0
- package/src/workflows/nodes/triggers/screen-event.ts +37 -0
- package/src/workflows/nodes/triggers/webhook.ts +39 -0
- package/src/workflows/safe-eval.ts +139 -0
- package/src/workflows/template.ts +118 -0
- package/src/workflows/triggers/cron.ts +311 -0
- package/src/workflows/triggers/manager.ts +285 -0
- package/src/workflows/triggers/observer-bridge.ts +172 -0
- package/src/workflows/triggers/poller.ts +201 -0
- package/src/workflows/triggers/screen-condition.ts +218 -0
- package/src/workflows/triggers/triggers.test.ts +740 -0
- package/src/workflows/triggers/webhook.ts +191 -0
- package/src/workflows/types.ts +133 -0
- package/src/workflows/variables.ts +72 -0
- package/src/workflows/workflows.test.ts +383 -0
- package/src/workflows/yaml.ts +104 -0
- package/ui/dist/index-j75njzc1.css +1199 -0
- package/ui/dist/index-p2zh407q.js +80603 -0
- package/ui/dist/index.html +13 -0
- package/ui/public/openwakeword/models/embedding_model.onnx +0 -0
- package/ui/public/openwakeword/models/hey_jarvis_v0.1.onnx +0 -0
- package/ui/public/openwakeword/models/melspectrogram.onnx +0 -0
- package/ui/public/openwakeword/models/silero_vad.onnx +0 -0
- package/ui/public/ort/ort-wasm-simd-threaded.jsep.mjs +106 -0
- package/ui/public/ort/ort-wasm-simd-threaded.jsep.wasm +0 -0
- package/ui/public/ort/ort-wasm-simd-threaded.mjs +59 -0
- package/ui/public/ort/ort-wasm-simd-threaded.wasm +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vault Retrieval — Memory Query Engine
|
|
3
|
+
*
|
|
4
|
+
* Takes a user message, extracts search terms, queries the knowledge graph
|
|
5
|
+
* for matching entities/facts/relationships, and returns formatted context
|
|
6
|
+
* that gets injected into the system prompt.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { getDb } from './schema.ts';
|
|
10
|
+
import { searchEntitiesByName, type Entity } from './entities.ts';
|
|
11
|
+
import { findFacts, type Fact } from './facts.ts';
|
|
12
|
+
import { getEntityRelationships } from './relationships.ts';
|
|
13
|
+
|
|
14
|
+
// Common stopwords to filter from search queries
|
|
15
|
+
const STOPWORDS = new Set([
|
|
16
|
+
'i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', 'your',
|
|
17
|
+
'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', 'her',
|
|
18
|
+
'hers', 'herself', 'it', 'its', 'itself', 'they', 'them', 'their', 'theirs',
|
|
19
|
+
'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those',
|
|
20
|
+
'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had',
|
|
21
|
+
'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if',
|
|
22
|
+
'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with',
|
|
23
|
+
'about', 'against', 'between', 'through', 'during', 'before', 'after', 'above',
|
|
24
|
+
'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under',
|
|
25
|
+
'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why',
|
|
26
|
+
'how', 'all', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such',
|
|
27
|
+
'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very',
|
|
28
|
+
'can', 'will', 'just', 'don', 'should', 'now', 'could', 'would', 'shall',
|
|
29
|
+
'may', 'might', 'must', 'tell', 'know', 'think', 'say', 'said', 'get', 'go',
|
|
30
|
+
'make', 'like', 'also', 'well', 'back', 'way', 'want', 'look', 'first', 'even',
|
|
31
|
+
'give', 'yeah', 'yes', 'please', 'thanks', 'thank', 'hi', 'hello', 'hey',
|
|
32
|
+
'okay', 'ok', 'sure', 'right', 'much', 'many', 'need', 'let', 'remember',
|
|
33
|
+
'recall', 'told', 'mentioned', 'talked', 'work', 'works', 'working',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
export type EntityProfile = {
|
|
37
|
+
entity: Entity;
|
|
38
|
+
facts: Fact[];
|
|
39
|
+
relationships: Array<{ type: string; target: string; direction: 'from' | 'to' }>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extract meaningful search terms from a user message.
|
|
44
|
+
* Filters stopwords and short words, deduplicates.
|
|
45
|
+
*/
|
|
46
|
+
export function extractSearchTerms(message: string): string[] {
|
|
47
|
+
const words = message
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.split(/[^a-zA-Z0-9']+/)
|
|
50
|
+
.map(w => w.replace(/^'+|'+$/g, '')) // trim quotes
|
|
51
|
+
.filter(w => w.length > 1 && !STOPWORDS.has(w));
|
|
52
|
+
|
|
53
|
+
return [...new Set(words)];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Search the vault for entities matching the given terms.
|
|
58
|
+
* Searches entity names and fact objects/predicates.
|
|
59
|
+
*/
|
|
60
|
+
export function retrieveForMessage(message: string): EntityProfile[] {
|
|
61
|
+
const terms = extractSearchTerms(message);
|
|
62
|
+
if (terms.length === 0) return [];
|
|
63
|
+
|
|
64
|
+
const entityMap = new Map<string, Entity>();
|
|
65
|
+
|
|
66
|
+
// 1. Search entity names
|
|
67
|
+
for (const term of terms) {
|
|
68
|
+
const matches = searchEntitiesByName(term);
|
|
69
|
+
for (const entity of matches) {
|
|
70
|
+
entityMap.set(entity.id, entity);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 2. Search fact objects and predicates for matching terms
|
|
75
|
+
try {
|
|
76
|
+
const db = getDb();
|
|
77
|
+
for (const term of terms) {
|
|
78
|
+
const stmt = db.prepare(`
|
|
79
|
+
SELECT DISTINCT e.id, e.type, e.name, e.properties, e.created_at, e.updated_at, e.source
|
|
80
|
+
FROM entities e
|
|
81
|
+
JOIN facts f ON e.id = f.subject_id
|
|
82
|
+
WHERE f.object LIKE ? OR f.predicate LIKE ?
|
|
83
|
+
LIMIT 10
|
|
84
|
+
`);
|
|
85
|
+
const rows = stmt.all(`%${term}%`, `%${term}%`) as any[];
|
|
86
|
+
for (const row of rows) {
|
|
87
|
+
if (!entityMap.has(row.id)) {
|
|
88
|
+
entityMap.set(row.id, {
|
|
89
|
+
...row,
|
|
90
|
+
properties: row.properties ? JSON.parse(row.properties) : null,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
// DB not available — return what we have from entity search
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 3. Build full profiles for matched entities (cap at 10)
|
|
100
|
+
const entities = [...entityMap.values()].slice(0, 10);
|
|
101
|
+
const profiles: EntityProfile[] = [];
|
|
102
|
+
|
|
103
|
+
for (const entity of entities) {
|
|
104
|
+
const facts = findFacts({ subject_id: entity.id });
|
|
105
|
+
|
|
106
|
+
let relationships: EntityProfile['relationships'] = [];
|
|
107
|
+
try {
|
|
108
|
+
const rels = getEntityRelationships(entity.id);
|
|
109
|
+
relationships = rels.map(r => ({
|
|
110
|
+
type: r.type,
|
|
111
|
+
target: r.from_id === entity.id ? r.to_entity.name : r.from_entity.name,
|
|
112
|
+
direction: (r.from_id === entity.id ? 'from' : 'to') as 'from' | 'to',
|
|
113
|
+
}));
|
|
114
|
+
} catch {
|
|
115
|
+
// Relationship query failed — skip
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
profiles.push({ entity, facts, relationships });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return profiles;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Format entity profiles into readable text for the system prompt.
|
|
126
|
+
*/
|
|
127
|
+
export function formatKnowledgeContext(profiles: EntityProfile[]): string {
|
|
128
|
+
if (profiles.length === 0) return '';
|
|
129
|
+
|
|
130
|
+
const sections: string[] = [];
|
|
131
|
+
|
|
132
|
+
for (const { entity, facts, relationships } of profiles) {
|
|
133
|
+
const lines: string[] = [];
|
|
134
|
+
|
|
135
|
+
lines.push(`**${entity.name}** (${entity.type})`);
|
|
136
|
+
|
|
137
|
+
for (const fact of facts) {
|
|
138
|
+
lines.push(` - ${fact.predicate}: ${fact.object}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for (const rel of relationships) {
|
|
142
|
+
if (rel.direction === 'from') {
|
|
143
|
+
lines.push(` - ${rel.type} -> ${rel.target}`);
|
|
144
|
+
} else {
|
|
145
|
+
lines.push(` - ${rel.target} -> ${rel.type} -> ${entity.name}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
sections.push(lines.join('\n'));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return sections.join('\n\n');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Main entry point: get formatted knowledge context for a user message.
|
|
157
|
+
* Returns empty string if no relevant knowledge found.
|
|
158
|
+
*/
|
|
159
|
+
export function getKnowledgeForMessage(message: string): string {
|
|
160
|
+
try {
|
|
161
|
+
const profiles = retrieveForMessage(message);
|
|
162
|
+
return formatKnowledgeContext(profiles);
|
|
163
|
+
} catch (err) {
|
|
164
|
+
console.error('[Retrieval] Error querying vault:', err);
|
|
165
|
+
return '';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get a summary of active goals for system prompt injection.
|
|
171
|
+
* Returns formatted text showing goal hierarchy with scores, or empty string.
|
|
172
|
+
*/
|
|
173
|
+
export function getActiveGoalsSummary(): string {
|
|
174
|
+
try {
|
|
175
|
+
const { findGoals } = require('./goals.ts');
|
|
176
|
+
const activeGoals = findGoals({ status: 'active' }) as Array<{
|
|
177
|
+
id: string;
|
|
178
|
+
parent_id: string | null;
|
|
179
|
+
level: string;
|
|
180
|
+
title: string;
|
|
181
|
+
score: number;
|
|
182
|
+
health: string;
|
|
183
|
+
deadline: number | null;
|
|
184
|
+
}>;
|
|
185
|
+
|
|
186
|
+
if (activeGoals.length === 0) return '';
|
|
187
|
+
|
|
188
|
+
const levelOrder: Record<string, number> = {
|
|
189
|
+
objective: 0,
|
|
190
|
+
key_result: 1,
|
|
191
|
+
milestone: 2,
|
|
192
|
+
task: 3,
|
|
193
|
+
daily_action: 4,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Sort by level then title
|
|
197
|
+
activeGoals.sort((a, b) => {
|
|
198
|
+
const la = levelOrder[a.level] ?? 5;
|
|
199
|
+
const lb = levelOrder[b.level] ?? 5;
|
|
200
|
+
if (la !== lb) return la - lb;
|
|
201
|
+
return a.title.localeCompare(b.title);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Cap at 15 most important goals (objectives + key results + top milestones)
|
|
205
|
+
const topGoals = activeGoals.slice(0, 15);
|
|
206
|
+
|
|
207
|
+
const lines: string[] = [];
|
|
208
|
+
for (const goal of topGoals) {
|
|
209
|
+
const indent = ' '.repeat(levelOrder[goal.level] ?? 0);
|
|
210
|
+
const healthIcon = goal.health === 'on_track' ? '+' :
|
|
211
|
+
goal.health === 'at_risk' ? '~' :
|
|
212
|
+
goal.health === 'behind' ? '-' : '!';
|
|
213
|
+
const deadlineStr = goal.deadline
|
|
214
|
+
? ` (due: ${new Date(goal.deadline).toLocaleDateString()})`
|
|
215
|
+
: '';
|
|
216
|
+
lines.push(`${indent}[${healthIcon}] ${goal.title} — ${goal.score.toFixed(1)}/1.0${deadlineStr}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (activeGoals.length > 15) {
|
|
220
|
+
lines.push(` ... and ${activeGoals.length - 15} more active goals`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return lines.join('\n');
|
|
224
|
+
} catch {
|
|
225
|
+
return '';
|
|
226
|
+
}
|
|
227
|
+
}
|