total-recall-brain 3.25.6 → 3.28.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.
Files changed (81) hide show
  1. package/bin/total-recall.mjs +31 -1
  2. package/docs/ARCHITECTURE.md +76 -9
  3. package/frontend/dist/assets/index-U7o-qU99.js +5742 -0
  4. package/frontend/dist/index.html +1 -1
  5. package/frontend/src/App.tsx +39 -1
  6. package/frontend/src/api/index.ts +1 -0
  7. package/frontend/src/api/mesh.ts +32 -0
  8. package/frontend/src/api/plugins.ts +167 -0
  9. package/frontend/src/components/MobilePairing.spec.tsx +89 -0
  10. package/frontend/src/components/MobilePairing.tsx +72 -1
  11. package/frontend/src/components/TailnetEnroll.spec.tsx +29 -1
  12. package/frontend/src/components/TailnetEnroll.tsx +85 -3
  13. package/frontend/src/pages/ChatPage.tsx +44 -17
  14. package/frontend/src/pages/IntegrationsPage.tsx +7 -0
  15. package/frontend/src/pages/PluginsPage.spec.tsx +17 -0
  16. package/frontend/src/pages/PluginsPage.tsx +1331 -0
  17. package/package.json +1 -1
  18. package/scaffold/.agent/plugins/.gitkeep +0 -0
  19. package/scaffold/.agent/plugins/code-quality/README.md +16 -0
  20. package/scaffold/.agent/plugins/code-quality/cli.mjs +15 -0
  21. package/scaffold/.agent/plugins/code-quality/plugin.json +34 -0
  22. package/scaffold/.agent/plugins/git-sentinel/README.md +16 -0
  23. package/scaffold/.agent/plugins/git-sentinel/cli.mjs +86 -0
  24. package/scaffold/.agent/plugins/git-sentinel/plugin.json +34 -0
  25. package/scaffold/.agent/plugins/meta-harness/README.md +16 -0
  26. package/scaffold/.agent/plugins/meta-harness/cli.mjs +34 -0
  27. package/scaffold/.agent/plugins/meta-harness/plugin.json +34 -0
  28. package/scaffold/.agent/plugins/system-monitor/README.md +16 -0
  29. package/scaffold/.agent/plugins/system-monitor/cli.mjs +79 -0
  30. package/scaffold/.agent/plugins/system-monitor/generator.mjs +20 -0
  31. package/scaffold/.agent/plugins/system-monitor/plugin.json +38 -0
  32. package/scaffold/.agent/skills/meta-harness/SKILL.md +113 -0
  33. package/scaffold/.agent/skills/total-recall/references/cli-reference.md +23 -0
  34. package/src/cli/agent.mjs +173 -0
  35. package/src/cli/connect.mjs +89 -4
  36. package/src/cli/deploy-ui.mjs +6 -0
  37. package/src/cli/harness.mjs +135 -0
  38. package/src/cli/ingest-openwiki.mjs +71 -2
  39. package/src/cli/init.mjs +1 -0
  40. package/src/cli/lint.mjs +47 -3
  41. package/src/cli/mesh.mjs +286 -0
  42. package/src/cli/plugin/create.mjs +186 -0
  43. package/src/cli/plugin/index.mjs +139 -0
  44. package/src/cli/plugin/install.mjs +141 -0
  45. package/src/cli/plugin/list.mjs +83 -0
  46. package/src/cli/plugin/remove.mjs +51 -0
  47. package/src/cli/plugin/search.mjs +37 -0
  48. package/src/cli/skill-projection.mjs +14 -0
  49. package/src/cli/wizard.html +9 -0
  50. package/src/core/agent-manager.mjs +290 -0
  51. package/src/core/bound-hosts.mjs +64 -0
  52. package/src/core/cache-prune.mjs +341 -0
  53. package/src/core/context-cache.mjs +130 -0
  54. package/src/core/daemon-loop.mjs +47 -1
  55. package/src/core/evolving-context.mjs +171 -0
  56. package/src/core/mesh-activity.mjs +140 -0
  57. package/src/core/mesh-late-bind.mjs +105 -0
  58. package/src/core/mesh.mjs +174 -1
  59. package/src/core/meta-harness.mjs +251 -0
  60. package/src/core/pairing.mjs +49 -10
  61. package/src/core/plugin-context.mjs +206 -0
  62. package/src/core/plugin-loader.mjs +210 -0
  63. package/src/core/registration-watch.mjs +193 -0
  64. package/src/core/runtime.mjs +65 -13
  65. package/src/core/secrets-store.mjs +8 -0
  66. package/src/core/surface.mjs +32 -10
  67. package/src/server/api.mjs +18 -2
  68. package/src/server/auth.mjs +11 -1
  69. package/src/server/index.mjs +43 -2
  70. package/src/server/rest.mjs +4 -0
  71. package/src/server/route-manifest.json +12 -0
  72. package/src/server/routes/auth.mjs +31 -0
  73. package/src/server/routes/integrations.mjs +5 -1
  74. package/src/server/routes/mesh-presence.mjs +143 -0
  75. package/src/server/routes/mesh.mjs +55 -0
  76. package/src/server/routes/models.mjs +42 -30
  77. package/src/server/routes/plugins.mjs +517 -0
  78. package/src/server/routes/secrets.mjs +1 -0
  79. package/src/server/routes/system.mjs +5 -0
  80. package/src/server/tools.mjs +266 -0
  81. package/frontend/dist/assets/index-DSxCyPAx.js +0 -5742
@@ -62,14 +62,26 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
62
62
  const [nodeSearchQuery, setNodeSearchQuery] = useState('')
63
63
  const nodeSelectorRef = useRef<HTMLDivElement>(null)
64
64
 
65
+ const DEFAULT_GEMINI_MODELS = [
66
+ { id: 'gemini-3.8-flash-high', displayName: 'Gemini 3.8 Flash (High)' },
67
+ { id: 'gemini-3.8-flash-medium', displayName: 'Gemini 3.8 Flash (Medium)' },
68
+ { id: 'gemini-3.8-flash-low', displayName: 'Gemini 3.8 Flash (Low)' },
69
+ { id: 'gemini-3.7-flash-high', displayName: 'Gemini 3.7 Flash (High)' },
70
+ { id: 'gemini-3.7-flash-medium', displayName: 'Gemini 3.7 Flash (Medium)' },
71
+ { id: 'gemini-3.6-flash-high', displayName: 'Gemini 3.6 Flash (High)' },
72
+ { id: 'gemini-3.1-pro-high', displayName: 'Gemini 3.1 Pro (High)' },
73
+ { id: 'gemini-3.5-flash', displayName: 'Gemini 3.5 Flash' },
74
+ { id: 'gemini-3.5-pro', displayName: 'Gemini 3.5 Pro' },
75
+ ]
76
+
65
77
  // Model Selector state
66
78
  const [availableModels, setAvailableModels] = useState<string[]>([])
67
79
  const [selectedModel, setSelectedModel] = useState<string>(() => {
68
80
  const saved = localStorage.getItem('selectedModel');
69
81
  return (saved && saved !== 'gemini') ? saved : 'antigravity';
70
82
  })
71
- const [selectedSubModel, setSelectedSubModel] = useState<string>(() => localStorage.getItem('selectedSubModel') || '')
72
- const [geminiModels, setGeminiModels] = useState<{ id: string; displayName: string }[]>([])
83
+ const [selectedSubModel, setSelectedSubModel] = useState<string>(() => localStorage.getItem('selectedSubModel') || 'gemini-3.8-flash-high')
84
+ const [geminiModels, setGeminiModels] = useState<{ id: string; displayName: string }[]>(DEFAULT_GEMINI_MODELS)
73
85
  const [showModelDropdown, setShowModelDropdown] = useState(false)
74
86
  const dropdownRef = useRef<HTMLDivElement>(null)
75
87
 
@@ -144,19 +156,28 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
144
156
 
145
157
  fetchGeminiModels()
146
158
  .then(models => {
147
- setGeminiModels(models)
148
- if (models && models.length > 0) {
149
- const savedSub = localStorage.getItem('selectedSubModel');
150
- const exists = models.some(m => m.id === savedSub);
151
- if (savedSub && exists) {
152
- setSelectedSubModel(savedSub);
153
- } else {
154
- setSelectedSubModel(models[0].id);
155
- localStorage.setItem('selectedSubModel', models[0].id);
156
- }
159
+ const list = models && models.length > 0 ? models : DEFAULT_GEMINI_MODELS;
160
+ setGeminiModels(list);
161
+ const savedSub = localStorage.getItem('selectedSubModel');
162
+ const exists = list.some(m => m.id === savedSub);
163
+ if (savedSub && exists) {
164
+ setSelectedSubModel(savedSub);
165
+ } else {
166
+ setSelectedSubModel(list[0].id);
167
+ localStorage.setItem('selectedSubModel', list[0].id);
168
+ }
169
+ })
170
+ .catch(() => {
171
+ setGeminiModels(DEFAULT_GEMINI_MODELS);
172
+ const savedSub = localStorage.getItem('selectedSubModel');
173
+ const exists = DEFAULT_GEMINI_MODELS.some(m => m.id === savedSub);
174
+ if (savedSub && exists) {
175
+ setSelectedSubModel(savedSub);
176
+ } else {
177
+ setSelectedSubModel(DEFAULT_GEMINI_MODELS[0].id);
178
+ localStorage.setItem('selectedSubModel', DEFAULT_GEMINI_MODELS[0].id);
157
179
  }
158
180
  })
159
- .catch(console.error)
160
181
  // eslint-disable-next-line react-hooks/exhaustive-deps -- onBrainChange is stable from parent
161
182
  }, [])
162
183
 
@@ -380,7 +401,7 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
380
401
  return;
381
402
  }
382
403
 
383
- const modelWithSubModel = ['gemini', 'antigravity'].includes(selectedModel) && selectedSubModel
404
+ const modelWithSubModel = ['gemini', 'antigravity', 'agy'].includes(selectedModel) && selectedSubModel
384
405
  ? `${selectedModel}:${selectedSubModel}`
385
406
  : selectedModel
386
407
 
@@ -409,7 +430,7 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
409
430
  setLoading(true)
410
431
  abortControllerRef.current = new AbortController()
411
432
  try {
412
- const modelWithSubModel = ['gemini', 'antigravity'].includes(selectedModel) && selectedSubModel
433
+ const modelWithSubModel = ['gemini', 'antigravity', 'agy'].includes(selectedModel) && selectedSubModel
413
434
  ? `${selectedModel}:${selectedSubModel}`
414
435
  : selectedModel
415
436
 
@@ -599,7 +620,12 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
599
620
  }}
600
621
  title="Select CLI agent / provider"
601
622
  >
602
- <span style={{ textTransform: 'capitalize' }}>{selectedModel || 'Select Model'}</span>
623
+ <span style={{ textTransform: 'capitalize' }}>
624
+ {selectedModel || 'Select Model'}
625
+ {['gemini', 'antigravity', 'agy'].includes(selectedModel) && selectedSubModel
626
+ ? ` · ${geminiModels.find(m => m.id === selectedSubModel)?.displayName || selectedSubModel}`
627
+ : ''}
628
+ </span>
603
629
  <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
604
630
  <polyline points="6 9 12 15 18 9"></polyline>
605
631
  </svg>
@@ -629,6 +655,7 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
629
655
  <span className="model-selector-item-name" style={{ textTransform: 'capitalize' }}>{modelName}</span>
630
656
  <span className="model-selector-item-desc">
631
657
  {modelName === 'antigravity' && 'Google Antigravity'}
658
+ {modelName === 'agy' && 'Google Antigravity'}
632
659
  {modelName === 'grok' && 'xAI Grok Build CLI'}
633
660
  {modelName === 'gemini' && 'Google Gemini CLI'}
634
661
  {modelName === 'claude' && 'Anthropic Claude CLI'}
@@ -641,7 +668,7 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
641
668
  </div>
642
669
  )}
643
670
  </div>
644
- {['gemini', 'antigravity'].includes(selectedModel) && geminiModels.length > 0 && (
671
+ {['gemini', 'antigravity', 'agy'].includes(selectedModel) && geminiModels.length > 0 && (
645
672
  <div className="chat-header-submodel-selector" style={{ display: 'flex', alignItems: 'center', gap: 8, marginLeft: 16 }}>
646
673
  <span className="selector-label" style={{ fontSize: '12px', color: 'var(--text-tertiary)', fontWeight: 500 }}>Base:</span>
647
674
  <select
@@ -66,6 +66,13 @@ const PRESETS: Preset[] = [
66
66
  command: 'npx total-recall connect hermes',
67
67
  snippet: () => `Pushes truncated memory surface projections to autonomous Hermes.`
68
68
  },
69
+ {
70
+ id: 'dsh',
71
+ name: 'DeepSeek Harness (dsh)',
72
+ surface: 'AGENTS.md / ~/.dsh/memory/MEMORY.md',
73
+ command: 'npx total-recall connect dsh',
74
+ snippet: () => `Integrates SSSS memory and skills into DeepSeek Harness agent runtimes.`
75
+ },
69
76
  {
70
77
  id: 'openclaw',
71
78
  name: 'OpenClaw',
@@ -0,0 +1,17 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import PluginsPage from './PluginsPage';
4
+
5
+ // Mock fetch globally
6
+ const mockFetch = vi.fn().mockResolvedValue({
7
+ ok: true,
8
+ json: async () => ({ installed: [], catalog: [] })
9
+ });
10
+ globalThis.fetch = mockFetch as unknown as typeof fetch;
11
+
12
+ describe('PluginsPage', () => {
13
+ it('renders plugins page', () => {
14
+ render(<PluginsPage />);
15
+ expect(screen.getByText(/Plugin/i)).toBeInTheDocument();
16
+ });
17
+ });