total-recall-brain 3.13.0 → 3.13.2

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.
Files changed (152) hide show
  1. package/README.md +91 -108
  2. package/bin/antigravity.mjs +81 -52
  3. package/bin/total-recall.mjs +32 -57
  4. package/extension/background.js +1 -1
  5. package/extension/options/options.js +9 -3
  6. package/extension/sidepanel/sidepanel.js +0 -2
  7. package/frontend/index.html +4 -3
  8. package/frontend/package.json +1 -0
  9. package/frontend/src/App.tsx +109 -152
  10. package/frontend/src/api.ts +605 -23
  11. package/frontend/src/components/BrainSelector.tsx +211 -199
  12. package/frontend/src/components/DocumentEditorModal.tsx +57 -0
  13. package/frontend/src/components/DocumentTable.tsx +47 -0
  14. package/frontend/src/components/Graph3D.tsx +120 -71
  15. package/frontend/src/components/UsageChart.tsx +3 -3
  16. package/frontend/src/components/brand/BrandMark.tsx +95 -0
  17. package/frontend/src/index.css +286 -86
  18. package/frontend/src/pages/ApiKeysPage.tsx +1878 -215
  19. package/frontend/src/pages/ChatPage.tsx +103 -45
  20. package/frontend/src/pages/DesignDocsPage.tsx +5 -5
  21. package/frontend/src/pages/FilesPage.tsx +10 -6
  22. package/frontend/src/pages/GraphPage.tsx +5 -3
  23. package/frontend/src/pages/HelpPage.tsx +2 -2
  24. package/frontend/src/pages/InboxPage.tsx +82 -0
  25. package/frontend/src/pages/InstructionsPage.tsx +1 -1
  26. package/frontend/src/pages/IntegrationsPage.tsx +21 -10
  27. package/frontend/src/pages/LoginPage.tsx +95 -77
  28. package/frontend/src/pages/MemoryPage.tsx +31 -8
  29. package/frontend/src/pages/OnboardingPage.tsx +690 -0
  30. package/frontend/src/pages/OpenWikiPage.tsx +412 -323
  31. package/frontend/src/pages/SettingsPage.tsx +825 -922
  32. package/frontend/src/pages/SkillsPage.tsx +272 -147
  33. package/frontend/src/pages/UsagePage.tsx +23 -31
  34. package/frontend/src/pages/VaultPage.tsx +223 -0
  35. package/frontend/src/types.ts +13 -0
  36. package/package.json +4 -4
  37. package/scaffold/.agent/skills/total-recall/SKILL.md +43 -4
  38. package/scaffold/.agent/skills/total-recall/modules/README.md +10 -0
  39. package/scaffold/.agent/skills/total-recall/modules/agents/README.md +5 -0
  40. package/scaffold/.agent/skills/total-recall/{skills/tr-cli-agents → modules/agents}/agents.yml +8 -0
  41. package/scaffold/.agent/skills/total-recall/modules/skill-deploy/README.md +9 -0
  42. package/scaffold/.agent/skills/total-recall/openwiki/README.md +10 -0
  43. package/scaffold/.agent/skills/total-recall/openwiki/architecture.md +5 -0
  44. package/scaffold/.agent/skills/total-recall/openwiki/ide.md +10 -0
  45. package/scaffold/.agent/skills/total-recall/openwiki/memory.md +11 -0
  46. package/scaffold/.agent/skills/total-recall/openwiki/secrets.md +7 -0
  47. package/scaffold/.agent/skills/total-recall/openwiki/skills.md +7 -0
  48. package/src/cli/brain.mjs +63 -5
  49. package/src/cli/connect.mjs +11 -19
  50. package/src/cli/daemon.mjs +5 -4
  51. package/src/cli/deploy-ui.mjs +8 -3
  52. package/src/cli/deploy.mjs +84 -27
  53. package/src/cli/ingest/index.mjs +1 -1
  54. package/src/cli/init.mjs +63 -34
  55. package/src/cli/remember.mjs +3 -3
  56. package/src/cli/secret.mjs +812 -0
  57. package/src/cli/setup.mjs +34 -7
  58. package/src/cli/share.mjs +2 -2
  59. package/src/cli/skill.mjs +396 -35
  60. package/src/cli/sync.mjs +4 -4
  61. package/src/cli/task.mjs +287 -0
  62. package/src/core/clarity-rewriter.mjs +5 -5
  63. package/src/core/config.mjs +44 -2
  64. package/src/core/conflict-detector.mjs +5 -5
  65. package/src/core/crons.mjs +54 -0
  66. package/src/core/daemon-loop.mjs +87 -235
  67. package/src/core/dream.mjs +170 -10
  68. package/src/core/env-import.mjs +456 -0
  69. package/src/core/fact-seeker.mjs +14 -14
  70. package/src/core/import-rules.mjs +20 -7
  71. package/src/core/inference-engine.mjs +3 -3
  72. package/src/core/migrate.mjs +14 -8
  73. package/src/core/okf-adapter.mjs +2 -2
  74. package/src/core/operation-validator.mjs +39 -331
  75. package/src/core/optimizer.mjs +7 -0
  76. package/src/core/post-mortem.mjs +2 -2
  77. package/src/core/project-brain.mjs +349 -0
  78. package/src/core/provider-catalog.mjs +296 -0
  79. package/src/core/quick-capture.mjs +1 -1
  80. package/src/core/remote-vault-sync.mjs +194 -0
  81. package/src/core/research-queue.mjs +7 -11
  82. package/src/core/runtime.mjs +33 -9
  83. package/src/core/scheduler.mjs +59 -5
  84. package/src/core/schema.mjs +14 -0
  85. package/src/core/search.mjs +1 -1
  86. package/src/core/secrets-env-export.mjs +323 -0
  87. package/src/core/secrets-rotate.mjs +245 -0
  88. package/src/core/secrets-store.mjs +645 -0
  89. package/src/core/semantic-index.mjs +3 -3
  90. package/src/core/skills-registry.mjs +1062 -0
  91. package/src/core/source-adapters.mjs +4 -1
  92. package/src/core/ssss-host-extension.mjs +94 -0
  93. package/src/core/ssss-kernel-bridge.mjs +530 -0
  94. package/src/core/surface.mjs +14 -0
  95. package/src/core/task-envelope.mjs +298 -0
  96. package/src/core/task-executors.mjs +600 -0
  97. package/src/core/validated-write.mjs +124 -56
  98. package/src/core/vault.mjs +21 -34
  99. package/src/core/webauthn-store.mjs +272 -0
  100. package/src/server/api.mjs +26 -16
  101. package/src/server/auth.mjs +51 -0
  102. package/src/server/index.mjs +3 -3
  103. package/src/server/keys.mjs +30 -4
  104. package/src/server/rest.mjs +198 -25
  105. package/src/server/route-manifest.json +156 -0
  106. package/src/server/routes/_shared.mjs +40 -1
  107. package/src/server/routes/docs.mjs +260 -0
  108. package/src/server/routes/memory.mjs +145 -32
  109. package/src/server/routes/research.mjs +30 -0
  110. package/src/server/routes/secrets.mjs +470 -0
  111. package/src/server/routes/share.mjs +2 -2
  112. package/src/server/routes/skills.mjs +452 -54
  113. package/src/server/routes/sync.mjs +48 -0
  114. package/src/server/routes/webauthn.mjs +184 -0
  115. package/src/server/update-route-manifest.mjs +39 -0
  116. package/templates/onboarding-interview.md +32 -22
  117. package/templates/openwiki/README.md +10 -0
  118. package/templates/openwiki/architecture.md +5 -0
  119. package/templates/openwiki/ide.md +10 -0
  120. package/templates/openwiki/memory.md +11 -0
  121. package/templates/openwiki/secrets.md +7 -0
  122. package/templates/openwiki/skills.md +7 -0
  123. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/SKILL.md +0 -121
  124. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/antigravity.txt +0 -20
  125. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/claude.txt +0 -58
  126. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/codex.txt +0 -81
  127. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/gemini.txt +0 -44
  128. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/scripts/.gitkeep +0 -0
  129. package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/subagents/.gitkeep +0 -0
  130. package/scaffold/.agent/skills/total-recall/skills/tr-research/SKILL.md +0 -338
  131. package/scaffold/.agent/skills/total-recall/skills/tr-skill/SKILL.md +0 -282
  132. package/scaffold/.agent/skills/total-recall/skills/tr-skill/assets/skill-template/SKILL.md +0 -20
  133. package/scaffold/.agent/skills/total-recall/skills/tr-skill/evals/evals.json +0 -20
  134. package/scaffold/.agent/skills/total-recall/skills/tr-skill/hooks/on-skill-add.sh +0 -14
  135. package/scaffold/.agent/skills/total-recall/skills/tr-skill/hooks/on-skill-delete.sh +0 -14
  136. package/scaffold/.agent/skills/total-recall/skills/tr-skill/learnings/.gitkeep +0 -0
  137. package/scaffold/.agent/skills/total-recall/skills/tr-skill/references/.gitkeep +0 -0
  138. package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/.gitkeep +0 -0
  139. package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/create-skill.sh +0 -65
  140. package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/enforce-skill-optimization.mjs +0 -135
  141. package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/skill-watcher.mjs +0 -64
  142. package/scaffold/.agent/skills/total-recall/skills/tr-skill/subagents/audit-all-skills.md +0 -62
  143. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/SKILL.md +0 -298
  144. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/evals/evals.json +0 -17
  145. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/references/CHANGELOG.md +0 -124
  146. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/references/ssss-spec.md +0 -1325
  147. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/scripts/validate-schema.mjs +0 -232
  148. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/subagents/audit-ssss-node.md +0 -9
  149. /package/scaffold/.agent/skills/total-recall/{skills/tr-cli-agents/evals → modules/skill-deploy/scripts}/.gitkeep +0 -0
  150. /package/scaffold/.agent/skills/total-recall/{skills/tr-skill → modules/skill-deploy}/scripts/find-skills.mjs +0 -0
  151. /package/scaffold/.agent/skills/total-recall/{skills/tr-skill → modules/skill-deploy}/scripts/install-skill.mjs +0 -0
  152. /package/scaffold/.agent/skills/total-recall/{skills/tr-skill → modules/skill-deploy}/scripts/scan-skill.mjs +0 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Task envelope — durable daemon work items on the scheduler queue.
3
+ *
4
+ * Agents and users enqueue open-ended work; the daemon executes under
5
+ * capability policy via the executor registry (task-executors.mjs).
6
+ */
7
+
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import crypto from 'crypto';
11
+ import matter from 'gray-matter';
12
+ import { atomicWrite, safeStringify } from './vault.mjs';
13
+
14
+ /** Soft kinds — labels only; executor resolution uses `executor` then `category` then kind. */
15
+ export const TASK_KINDS = Object.freeze([
16
+ 'memory',
17
+ 'research',
18
+ 'maintenance',
19
+ 'system',
20
+ 'custom',
21
+ ]);
22
+
23
+ export const TASK_STATUSES = Object.freeze([
24
+ 'pending',
25
+ 'in-progress',
26
+ 'in_progress',
27
+ 'completed',
28
+ 'failed',
29
+ 'cancelled',
30
+ ]);
31
+
32
+ /** Default-deny dangerous capabilities. */
33
+ export const FORBIDDEN_CAPABILITIES = Object.freeze([
34
+ 'shell',
35
+ 'shell:all',
36
+ 'shell:any',
37
+ 'fs:root',
38
+ 'net:post',
39
+ 'net:all',
40
+ ]);
41
+
42
+ export const DEFAULT_CAPABILITIES = Object.freeze(['vault:read']);
43
+
44
+ /**
45
+ * Normalize priority: numeric 0–100, or named levels.
46
+ */
47
+ export function normalizePriority(priority) {
48
+ if (priority == null || priority === '') return 50;
49
+ if (typeof priority === 'number' && Number.isFinite(priority)) {
50
+ return Math.max(0, Math.min(100, priority));
51
+ }
52
+ const map = {
53
+ absolute: 100,
54
+ high: 80,
55
+ normal: 50,
56
+ medium: 50,
57
+ low: 20,
58
+ };
59
+ const key = String(priority).toLowerCase();
60
+ if (map[key] != null) return map[key];
61
+ const n = parseInt(String(priority), 10);
62
+ return Number.isFinite(n) ? Math.max(0, Math.min(100, n)) : 50;
63
+ }
64
+
65
+ /**
66
+ * Build a normalized task envelope object (not yet on disk).
67
+ */
68
+ export function buildTaskEnvelope({
69
+ intent,
70
+ slug,
71
+ kind = 'custom',
72
+ executor = null,
73
+ category = null,
74
+ priority = 50,
75
+ capabilities = DEFAULT_CAPABILITIES,
76
+ payload = {},
77
+ budget = {},
78
+ origin = {},
79
+ result = {},
80
+ system = false,
81
+ body = '',
82
+ target = null,
83
+ status = 'pending',
84
+ } = {}) {
85
+ if (!intent && !body && !target) {
86
+ throw new Error('Task envelope requires intent, body, or target');
87
+ }
88
+
89
+ const caps = Array.isArray(capabilities)
90
+ ? [...capabilities]
91
+ : String(capabilities || '')
92
+ .split(',')
93
+ .map((c) => c.trim())
94
+ .filter(Boolean);
95
+
96
+ const forbidden = caps.filter((c) => FORBIDDEN_CAPABILITIES.includes(c));
97
+ if (forbidden.length) {
98
+ throw new Error(
99
+ `Capability not allowed by default policy: ${forbidden.join(', ')}. ` +
100
+ 'Shell/net-post require explicit host policy (not yet granted via CLI).',
101
+ );
102
+ }
103
+
104
+ const now = new Date().toISOString();
105
+ const baseSlug =
106
+ slug ||
107
+ `task-${kind}-${crypto.createHash('sha256').update(`${intent || body || target}-${now}`).digest('hex').slice(0, 10)}`;
108
+
109
+ const resolvedCategory =
110
+ category ||
111
+ (kind === 'research'
112
+ ? 'proactive-research'
113
+ : kind === 'maintenance'
114
+ ? 'memory-maintenance'
115
+ : kind === 'system'
116
+ ? 'memory-maintenance'
117
+ : kind === 'memory'
118
+ ? 'memory-maintenance'
119
+ : 'custom');
120
+
121
+ return {
122
+ type: 'task',
123
+ schema_version: 1,
124
+ slug: baseSlug,
125
+ status,
126
+ priority: normalizePriority(priority),
127
+ kind: TASK_KINDS.includes(kind) ? kind : 'custom',
128
+ executor: executor || (kind === 'custom' ? 'custom' : null),
129
+ category: resolvedCategory,
130
+ intent: intent || body || target || '',
131
+ target: target || null,
132
+ capabilities: caps.length ? caps : [...DEFAULT_CAPABILITIES],
133
+ payload: payload && typeof payload === 'object' ? payload : {},
134
+ budget: {
135
+ max_wall_ms: budget.max_wall_ms ?? 120000,
136
+ max_tokens: budget.max_tokens ?? 0,
137
+ max_tool_calls: budget.max_tool_calls ?? 20,
138
+ },
139
+ origin: {
140
+ agent: origin.agent || origin.created_by || 'cli',
141
+ session_id: origin.session_id || null,
142
+ created_at: origin.created_at || now,
143
+ created_by: origin.created_by || origin.agent || 'cli',
144
+ },
145
+ result: {
146
+ land: result.land || 'inbox',
147
+ promote_via: result.promote_via || 'draft',
148
+ },
149
+ system: Boolean(system),
150
+ created_by: origin.created_by || origin.agent || 'cli',
151
+ reason: intent || body || '',
152
+ body: body || intent || '',
153
+ created_at: now,
154
+ updated_at: now,
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Normalize a disk/legacy task into envelope fields (in-place-ish return).
160
+ */
161
+ export function normalizeTask(raw) {
162
+ if (!raw || typeof raw !== 'object') return raw;
163
+ const task = { ...raw };
164
+ task.type = task.type || 'task';
165
+ task.status = task.status || 'pending';
166
+ if (task.status === 'in_progress') task.status = 'in-progress';
167
+ task.priority = normalizePriority(task.priority);
168
+ task.kind = task.kind || inferKind(task);
169
+ task.executor = task.executor || null;
170
+ task.capabilities = Array.isArray(task.capabilities)
171
+ ? task.capabilities
172
+ : [...DEFAULT_CAPABILITIES];
173
+ task.payload = task.payload && typeof task.payload === 'object' ? task.payload : {};
174
+ task.intent = task.intent || task.reason || task.body || task.target || task.slug || '';
175
+ task.system = Boolean(task.system);
176
+ return task;
177
+ }
178
+
179
+ function inferKind(task) {
180
+ if (task.system) return 'system';
181
+ if (task._research_id || String(task.category || '').includes('research') || String(task.slug || '').startsWith('research-')) {
182
+ return 'research';
183
+ }
184
+ if (task.category === 'memory-maintenance' || String(task.slug || '').includes('dream')) {
185
+ return 'maintenance';
186
+ }
187
+ if (task.category === 'custom' || task.executor === 'custom') return 'custom';
188
+ return task.kind || 'custom';
189
+ }
190
+
191
+ /**
192
+ * Persist envelope to queueDir as `<slug>.md`.
193
+ */
194
+ export function persistEnvelope(envelope, queueDir) {
195
+ if (!fs.existsSync(queueDir)) {
196
+ fs.mkdirSync(queueDir, { recursive: true });
197
+ }
198
+ const task = normalizeTask(envelope);
199
+ const filepath = path.join(queueDir, `${task.slug}.md`);
200
+ const { body, _filepath, ...frontmatter } = task;
201
+ for (const key of Object.keys(frontmatter)) {
202
+ if (frontmatter[key] === undefined) delete frontmatter[key];
203
+ }
204
+ atomicWrite(filepath, safeStringify(body || task.intent || '', frontmatter));
205
+ task._filepath = filepath;
206
+ return task;
207
+ }
208
+
209
+ /**
210
+ * Enqueue a new task (build + persist).
211
+ */
212
+ export function addTask(opts, queueDir) {
213
+ const envelope = buildTaskEnvelope(opts);
214
+ return persistEnvelope(envelope, queueDir);
215
+ }
216
+
217
+ /**
218
+ * List tasks from disk. statusFilter: pending|completed|failed|cancelled|all
219
+ */
220
+ export function listTasks(queueDir, { status = 'pending' } = {}) {
221
+ if (!fs.existsSync(queueDir)) return [];
222
+ const files = fs.readdirSync(queueDir).filter((f) => f.endsWith('.md'));
223
+ const tasks = [];
224
+ for (const file of files) {
225
+ try {
226
+ const filepath = path.join(queueDir, file);
227
+ const raw = fs.readFileSync(filepath, 'utf8');
228
+ const { data, content } = matter(raw);
229
+ const task = normalizeTask({
230
+ ...data,
231
+ slug: data.slug || path.basename(file, '.md'),
232
+ body: content,
233
+ _filepath: filepath,
234
+ });
235
+ if (status === 'all') {
236
+ tasks.push(task);
237
+ continue;
238
+ }
239
+ if (status === 'pending') {
240
+ if (task.status === 'pending' || task.status === 'in-progress') tasks.push(task);
241
+ continue;
242
+ }
243
+ if (task.status === status) tasks.push(task);
244
+ } catch {
245
+ // skip malformed
246
+ }
247
+ }
248
+ return tasks.sort((a, b) => (b.priority || 0) - (a.priority || 0));
249
+ }
250
+
251
+ /**
252
+ * Load one task by slug.
253
+ */
254
+ export function getTask(queueDir, slug) {
255
+ const filepath = path.join(queueDir, `${slug}.md`);
256
+ if (!fs.existsSync(filepath)) {
257
+ // scan for match
258
+ const all = listTasks(queueDir, { status: 'all' });
259
+ return all.find((t) => t.slug === slug) || null;
260
+ }
261
+ const raw = fs.readFileSync(filepath, 'utf8');
262
+ const { data, content } = matter(raw);
263
+ return normalizeTask({
264
+ ...data,
265
+ slug: data.slug || slug,
266
+ body: content,
267
+ _filepath: filepath,
268
+ });
269
+ }
270
+
271
+ /**
272
+ * Cancel a pending/in-progress task.
273
+ */
274
+ export function cancelTask(queueDir, slug) {
275
+ const task = getTask(queueDir, slug);
276
+ if (!task) return { success: false, error: `Task not found: ${slug}` };
277
+ if (task.status === 'completed' || task.status === 'cancelled') {
278
+ return { success: false, error: `Task already ${task.status}: ${slug}` };
279
+ }
280
+ const filepath = task._filepath || path.join(queueDir, `${task.slug}.md`);
281
+ const raw = fs.readFileSync(filepath, 'utf8');
282
+ const { data, content } = matter(raw);
283
+ data.status = 'cancelled';
284
+ data.updated_at = new Date().toISOString();
285
+ data.cancelled_at = data.updated_at;
286
+ for (const key of Object.keys(data)) {
287
+ if (data[key] === undefined) delete data[key];
288
+ }
289
+ atomicWrite(filepath, safeStringify(content, data));
290
+ return { success: true, task: { ...task, status: 'cancelled' } };
291
+ }
292
+
293
+ /**
294
+ * Resolve queue directory for a brain.
295
+ */
296
+ export function resolveQueueDir(brainDir) {
297
+ return path.join(brainDir, 'scheduler', 'queue');
298
+ }