@soleri/core 8.0.0 → 9.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.
Files changed (239) hide show
  1. package/dist/brain/brain.d.ts +1 -8
  2. package/dist/brain/brain.d.ts.map +1 -1
  3. package/dist/brain/brain.js +5 -134
  4. package/dist/brain/brain.js.map +1 -1
  5. package/dist/brain/knowledge-synthesizer.d.ts.map +1 -1
  6. package/dist/brain/knowledge-synthesizer.js +0 -2
  7. package/dist/brain/knowledge-synthesizer.js.map +1 -1
  8. package/dist/cognee/client.d.ts +5 -0
  9. package/dist/cognee/client.d.ts.map +1 -1
  10. package/dist/cognee/client.js +83 -16
  11. package/dist/cognee/client.js.map +1 -1
  12. package/dist/cognee/sync-manager.d.ts +67 -8
  13. package/dist/cognee/sync-manager.d.ts.map +1 -1
  14. package/dist/cognee/sync-manager.js +129 -32
  15. package/dist/cognee/sync-manager.js.map +1 -1
  16. package/dist/cognee/types.d.ts +16 -0
  17. package/dist/cognee/types.d.ts.map +1 -1
  18. package/dist/context/context-engine.d.ts +2 -5
  19. package/dist/context/context-engine.d.ts.map +1 -1
  20. package/dist/context/context-engine.js +4 -31
  21. package/dist/context/context-engine.js.map +1 -1
  22. package/dist/curator/classifier.d.ts.map +1 -1
  23. package/dist/curator/classifier.js +0 -2
  24. package/dist/curator/classifier.js.map +1 -1
  25. package/dist/curator/curator.d.ts +2 -5
  26. package/dist/curator/curator.d.ts.map +1 -1
  27. package/dist/curator/curator.js +4 -23
  28. package/dist/curator/curator.js.map +1 -1
  29. package/dist/curator/quality-gate.d.ts.map +1 -1
  30. package/dist/curator/quality-gate.js +0 -2
  31. package/dist/curator/quality-gate.js.map +1 -1
  32. package/dist/domain-packs/index.d.ts +0 -3
  33. package/dist/domain-packs/index.d.ts.map +1 -1
  34. package/dist/domain-packs/index.js +0 -3
  35. package/dist/domain-packs/index.js.map +1 -1
  36. package/dist/domain-packs/loader.d.ts.map +1 -1
  37. package/dist/domain-packs/loader.js +20 -4
  38. package/dist/domain-packs/loader.js.map +1 -1
  39. package/dist/domain-packs/pack-runtime.d.ts +5 -5
  40. package/dist/domain-packs/pack-runtime.d.ts.map +1 -1
  41. package/dist/domain-packs/pack-runtime.js +2 -2
  42. package/dist/domain-packs/pack-runtime.js.map +1 -1
  43. package/dist/domain-packs/types.d.ts +8 -2
  44. package/dist/domain-packs/types.d.ts.map +1 -1
  45. package/dist/domain-packs/types.js.map +1 -1
  46. package/dist/engine/bin/soleri-engine.js +18 -7
  47. package/dist/engine/bin/soleri-engine.js.map +1 -1
  48. package/dist/engine/core-ops.d.ts.map +1 -1
  49. package/dist/engine/core-ops.js +11 -6
  50. package/dist/engine/core-ops.js.map +1 -1
  51. package/dist/engine/index.d.ts +2 -0
  52. package/dist/engine/index.d.ts.map +1 -1
  53. package/dist/engine/index.js +1 -0
  54. package/dist/engine/index.js.map +1 -1
  55. package/dist/engine/module-manifest.d.ts +28 -0
  56. package/dist/engine/module-manifest.d.ts.map +1 -0
  57. package/dist/engine/module-manifest.js +85 -0
  58. package/dist/engine/module-manifest.js.map +1 -0
  59. package/dist/engine/register-engine.d.ts +19 -0
  60. package/dist/engine/register-engine.d.ts.map +1 -1
  61. package/dist/engine/register-engine.js +15 -9
  62. package/dist/engine/register-engine.js.map +1 -1
  63. package/dist/index.d.ts +5 -6
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +3 -5
  66. package/dist/index.js.map +1 -1
  67. package/dist/intake/content-classifier.d.ts.map +1 -1
  68. package/dist/intake/content-classifier.js +0 -2
  69. package/dist/intake/content-classifier.js.map +1 -1
  70. package/dist/intelligence/types.d.ts +7 -0
  71. package/dist/intelligence/types.d.ts.map +1 -1
  72. package/dist/llm/llm-client.d.ts.map +1 -1
  73. package/dist/llm/llm-client.js +8 -4
  74. package/dist/llm/llm-client.js.map +1 -1
  75. package/dist/llm/oauth-discovery.d.ts +0 -8
  76. package/dist/llm/oauth-discovery.d.ts.map +1 -1
  77. package/dist/llm/oauth-discovery.js +0 -19
  78. package/dist/llm/oauth-discovery.js.map +1 -1
  79. package/dist/llm/types.d.ts +4 -2
  80. package/dist/llm/types.d.ts.map +1 -1
  81. package/dist/packs/pack-installer.d.ts +2 -1
  82. package/dist/packs/pack-installer.d.ts.map +1 -1
  83. package/dist/packs/pack-installer.js +10 -1
  84. package/dist/packs/pack-installer.js.map +1 -1
  85. package/dist/persistence/index.d.ts +0 -1
  86. package/dist/persistence/index.d.ts.map +1 -1
  87. package/dist/persistence/index.js +0 -1
  88. package/dist/persistence/index.js.map +1 -1
  89. package/dist/persistence/types.d.ts +2 -6
  90. package/dist/persistence/types.d.ts.map +1 -1
  91. package/dist/persona/defaults.d.ts +16 -0
  92. package/dist/persona/defaults.d.ts.map +1 -0
  93. package/dist/persona/defaults.js +78 -0
  94. package/dist/persona/defaults.js.map +1 -0
  95. package/dist/persona/index.d.ts +5 -0
  96. package/dist/persona/index.d.ts.map +1 -0
  97. package/dist/persona/index.js +4 -0
  98. package/dist/persona/index.js.map +1 -0
  99. package/dist/persona/loader.d.ts +11 -0
  100. package/dist/persona/loader.d.ts.map +1 -0
  101. package/dist/persona/loader.js +45 -0
  102. package/dist/persona/loader.js.map +1 -0
  103. package/dist/persona/prompt-generator.d.ts +13 -0
  104. package/dist/persona/prompt-generator.d.ts.map +1 -0
  105. package/dist/persona/prompt-generator.js +89 -0
  106. package/dist/persona/prompt-generator.js.map +1 -0
  107. package/dist/persona/types.d.ts +56 -0
  108. package/dist/persona/types.d.ts.map +1 -0
  109. package/dist/persona/types.js +9 -0
  110. package/dist/persona/types.js.map +1 -0
  111. package/dist/plugins/index.d.ts +4 -0
  112. package/dist/plugins/index.d.ts.map +1 -1
  113. package/dist/plugins/index.js +4 -0
  114. package/dist/plugins/index.js.map +1 -1
  115. package/dist/plugins/plugin-registry.d.ts +4 -0
  116. package/dist/plugins/plugin-registry.d.ts.map +1 -1
  117. package/dist/plugins/plugin-registry.js +4 -0
  118. package/dist/plugins/plugin-registry.js.map +1 -1
  119. package/dist/plugins/types.d.ts +36 -31
  120. package/dist/plugins/types.d.ts.map +1 -1
  121. package/dist/plugins/types.js +6 -3
  122. package/dist/plugins/types.js.map +1 -1
  123. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  124. package/dist/runtime/admin-extra-ops.js +5 -27
  125. package/dist/runtime/admin-extra-ops.js.map +1 -1
  126. package/dist/runtime/admin-ops.d.ts.map +1 -1
  127. package/dist/runtime/admin-ops.js +5 -37
  128. package/dist/runtime/admin-ops.js.map +1 -1
  129. package/dist/runtime/capture-ops.d.ts.map +1 -1
  130. package/dist/runtime/capture-ops.js +32 -16
  131. package/dist/runtime/capture-ops.js.map +1 -1
  132. package/dist/runtime/claude-md-helpers.d.ts +0 -9
  133. package/dist/runtime/claude-md-helpers.d.ts.map +1 -1
  134. package/dist/runtime/claude-md-helpers.js +1 -14
  135. package/dist/runtime/claude-md-helpers.js.map +1 -1
  136. package/dist/runtime/cognee-sync-ops.d.ts +2 -2
  137. package/dist/runtime/cognee-sync-ops.d.ts.map +1 -1
  138. package/dist/runtime/cognee-sync-ops.js +45 -7
  139. package/dist/runtime/cognee-sync-ops.js.map +1 -1
  140. package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
  141. package/dist/runtime/facades/admin-facade.js +1 -2
  142. package/dist/runtime/facades/admin-facade.js.map +1 -1
  143. package/dist/runtime/facades/index.d.ts +1 -1
  144. package/dist/runtime/facades/index.d.ts.map +1 -1
  145. package/dist/runtime/facades/index.js +1 -10
  146. package/dist/runtime/facades/index.js.map +1 -1
  147. package/dist/runtime/pack-ops.d.ts +3 -0
  148. package/dist/runtime/pack-ops.d.ts.map +1 -1
  149. package/dist/runtime/pack-ops.js +18 -1
  150. package/dist/runtime/pack-ops.js.map +1 -1
  151. package/dist/runtime/plugin-ops.d.ts.map +1 -1
  152. package/dist/runtime/plugin-ops.js +3 -0
  153. package/dist/runtime/plugin-ops.js.map +1 -1
  154. package/dist/runtime/runtime.d.ts.map +1 -1
  155. package/dist/runtime/runtime.js +14 -53
  156. package/dist/runtime/runtime.js.map +1 -1
  157. package/dist/runtime/session-briefing.d.ts.map +1 -1
  158. package/dist/runtime/session-briefing.js +14 -0
  159. package/dist/runtime/session-briefing.js.map +1 -1
  160. package/dist/runtime/types.d.ts +6 -8
  161. package/dist/runtime/types.d.ts.map +1 -1
  162. package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
  163. package/dist/runtime/vault-linking-ops.js +42 -4
  164. package/dist/runtime/vault-linking-ops.js.map +1 -1
  165. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
  166. package/dist/runtime/vault-sharing-ops.js +53 -3
  167. package/dist/runtime/vault-sharing-ops.js.map +1 -1
  168. package/dist/vault/linking.d.ts +37 -0
  169. package/dist/vault/linking.d.ts.map +1 -1
  170. package/dist/vault/linking.js +73 -0
  171. package/dist/vault/linking.js.map +1 -1
  172. package/dist/vault/vault.d.ts +9 -2
  173. package/dist/vault/vault.d.ts.map +1 -1
  174. package/dist/vault/vault.js +21 -12
  175. package/dist/vault/vault.js.map +1 -1
  176. package/package.json +6 -4
  177. package/src/__tests__/curator-pipeline-e2e.test.ts +187 -0
  178. package/src/__tests__/module-manifest-drift.test.ts +59 -0
  179. package/src/brain/brain.ts +4 -157
  180. package/src/brain/knowledge-synthesizer.ts +0 -2
  181. package/src/context/context-engine.ts +3 -31
  182. package/src/curator/classifier.ts +0 -2
  183. package/src/curator/curator.ts +5 -28
  184. package/src/curator/quality-gate.ts +0 -2
  185. package/src/domain-packs/index.ts +0 -6
  186. package/src/domain-packs/loader.ts +25 -5
  187. package/src/domain-packs/pack-runtime.ts +6 -6
  188. package/src/domain-packs/types.ts +8 -2
  189. package/src/engine/bin/soleri-engine.ts +23 -7
  190. package/src/engine/core-ops.ts +11 -6
  191. package/src/engine/index.ts +2 -0
  192. package/src/engine/module-manifest.ts +99 -0
  193. package/src/engine/register-engine.ts +21 -9
  194. package/src/index.ts +20 -17
  195. package/src/intake/content-classifier.ts +0 -2
  196. package/src/intelligence/types.ts +8 -0
  197. package/src/llm/llm-client.ts +12 -6
  198. package/src/llm/oauth-discovery.ts +0 -18
  199. package/src/llm/types.ts +4 -2
  200. package/src/packs/pack-installer.ts +16 -1
  201. package/src/persistence/index.ts +0 -1
  202. package/src/persistence/types.ts +2 -6
  203. package/src/persona/defaults.ts +96 -0
  204. package/src/persona/index.ts +9 -0
  205. package/src/persona/loader.ts +50 -0
  206. package/src/persona/prompt-generator.ts +109 -0
  207. package/src/persona/types.ts +72 -0
  208. package/src/plugins/index.ts +4 -0
  209. package/src/plugins/plugin-registry.ts +6 -1
  210. package/src/plugins/types.ts +10 -5
  211. package/src/runtime/admin-extra-ops.ts +5 -28
  212. package/src/runtime/admin-ops.ts +5 -38
  213. package/src/runtime/capture-ops.ts +33 -14
  214. package/src/runtime/claude-md-helpers.ts +1 -19
  215. package/src/runtime/facades/admin-facade.ts +1 -2
  216. package/src/runtime/facades/index.ts +1 -11
  217. package/src/runtime/pack-ops.ts +26 -1
  218. package/src/runtime/plugin-ops.ts +3 -0
  219. package/src/runtime/runtime.ts +14 -54
  220. package/src/runtime/session-briefing.ts +14 -0
  221. package/src/runtime/types.ts +6 -8
  222. package/src/runtime/vault-linking-ops.ts +43 -4
  223. package/src/runtime/vault-sharing-ops.ts +63 -4
  224. package/src/vault/linking.ts +94 -0
  225. package/src/vault/vault.ts +24 -12
  226. package/src/__tests__/cognee-client-gaps.test.ts +0 -474
  227. package/src/__tests__/cognee-client.test.ts +0 -524
  228. package/src/__tests__/cognee-hybrid-search.test.ts +0 -492
  229. package/src/__tests__/cognee-integration.test.ts +0 -80
  230. package/src/__tests__/cognee-sync-manager-deep.test.ts +0 -654
  231. package/src/__tests__/cognee-sync-manager.test.ts +0 -104
  232. package/src/__tests__/postgres-provider.test.ts +0 -116
  233. package/src/cognee/client.ts +0 -370
  234. package/src/cognee/sync-manager.ts +0 -389
  235. package/src/cognee/types.ts +0 -62
  236. package/src/health/doctor-checks.ts +0 -115
  237. package/src/persistence/postgres-provider.ts +0 -310
  238. package/src/runtime/cognee-sync-ops.ts +0 -63
  239. package/src/runtime/facades/cognee-facade.ts +0 -164
package/src/llm/types.ts CHANGED
@@ -43,8 +43,10 @@ export class LLMError extends Error {
43
43
  }
44
44
 
45
45
  export interface LLMCallOptions {
46
- provider: 'openai' | 'anthropic';
47
- model: string;
46
+ /** Provider override. If omitted, the model router selects based on caller/task. */
47
+ provider?: 'openai' | 'anthropic';
48
+ /** Model override. If omitted, the model router selects based on caller/task. */
49
+ model?: string;
48
50
  systemPrompt: string;
49
51
  userPrompt: string;
50
52
  temperature?: number;
@@ -21,6 +21,7 @@ import { loadIntelligenceData } from '../intelligence/loader.js';
21
21
  import type { Vault } from '../vault/vault.js';
22
22
  import type { PluginRegistry } from '../plugins/plugin-registry.js';
23
23
  import type { PluginContext } from '../plugins/types.js';
24
+ import type { PackRuntime } from '../domain-packs/pack-runtime.js';
24
25
 
25
26
  const MANIFEST_FILENAME = 'soleri-pack.json';
26
27
 
@@ -108,7 +109,11 @@ export class PackInstaller {
108
109
  /**
109
110
  * Install a knowledge pack from a directory.
110
111
  */
111
- async install(packDir: string, runtimeCtx?: unknown): Promise<InstallResult> {
112
+ async install(
113
+ packDir: string,
114
+ runtimeCtx?: unknown,
115
+ packRuntime?: PackRuntime,
116
+ ): Promise<InstallResult> {
112
117
  // Validate first
113
118
  const validation = this.validate(packDir);
114
119
  if (!validation.valid || !validation.manifest) {
@@ -174,6 +179,16 @@ export class PackInstaller {
174
179
  }
175
180
 
176
181
  const ctx: PluginContext = {
182
+ packRuntime:
183
+ packRuntime ??
184
+ ({
185
+ vault: {},
186
+ getProject: () => undefined,
187
+ listProjects: () => [],
188
+ createCheck: () => '',
189
+ validateCheck: () => null,
190
+ validateAndConsume: () => null,
191
+ } as unknown as PackRuntime),
177
192
  runtime: runtimeCtx ?? {},
178
193
  manifest: pluginLoaded.manifest,
179
194
  directory: packDir,
@@ -6,4 +6,3 @@ export type {
6
6
  FtsSearchOptions,
7
7
  } from './types.js';
8
8
  export { SQLitePersistenceProvider } from './sqlite-provider.js';
9
- export { PostgresPersistenceProvider, translateSql } from './postgres-provider.js';
@@ -35,7 +35,7 @@ export interface PersistenceProvider {
35
35
  transaction<T>(fn: () => T): T;
36
36
 
37
37
  /** Identifies the backend engine. */
38
- readonly backend: 'sqlite' | 'postgres';
38
+ readonly backend: 'sqlite';
39
39
 
40
40
  /** Full-text search abstraction. */
41
41
  ftsSearch<T = Record<string, unknown>>(
@@ -52,12 +52,8 @@ export interface PersistenceProvider {
52
52
  }
53
53
 
54
54
  export interface PersistenceConfig {
55
- type: 'sqlite' | 'postgres';
55
+ type: 'sqlite';
56
56
  path: string;
57
- /** PostgreSQL connection string. */
58
- connectionString?: string;
59
- /** PostgreSQL pool size. */
60
- poolSize?: number;
61
57
  }
62
58
 
63
59
  export interface FtsSearchOptions {
@@ -0,0 +1,96 @@
1
+ import type { PersonaConfig } from './types.js';
2
+
3
+ /**
4
+ * The Italian Craftsperson — Soleri's default persona.
5
+ *
6
+ * Named after Paolo Soleri, the Italian-American architect who coined "arcology."
7
+ * This is a universal personality about craft and quality, not domain-specific.
8
+ * The agent adapts these metaphors to whatever the user works on.
9
+ */
10
+ export const ITALIAN_CRAFTSPERSON: Omit<PersonaConfig, 'name' | 'history'> = {
11
+ template: 'italian-craftsperson',
12
+
13
+ inspiration:
14
+ 'Paolo Soleri — Italian-American architect and visionary. The craft tradition of Italian artisans: mastery through practice, beauty through simplicity.',
15
+
16
+ culture: 'Italian',
17
+
18
+ metaphors: [
19
+ 'craftsmanship',
20
+ 'foundations',
21
+ 'blueprints',
22
+ 'workshop',
23
+ 'polishing',
24
+ 'forging',
25
+ 'materials',
26
+ 'apprenticeship',
27
+ ],
28
+
29
+ voice:
30
+ 'A warm Italian mentor — direct and opinionated about quality, generous with knowledge, sprinkles Italian expressions naturally. Never condescending, always encouraging mastery.',
31
+
32
+ traits: [
33
+ 'cares deeply about doing things well',
34
+ 'pragmatic over theoretical',
35
+ 'dry humor — never cruel, often self-deprecating',
36
+ 'celebrates when things click together',
37
+ 'impatient with sloppiness, endlessly patient with learning',
38
+ 'believes simplicity is the highest form of mastery',
39
+ 'opinionated but open to being convinced',
40
+ ],
41
+
42
+ quirks: [
43
+ 'Italian expressions woven naturally: perfetto, piano piano, bravo/brava, mamma mia, allora, dai',
44
+ 'Craft metaphors that adapt to the domain at hand — code is built like furniture, APIs are designed like piazzas',
45
+ 'Says "perfetto!" when patterns are clean, "mamma mia" when seeing a mess',
46
+ 'Occasionally references Italian craft tradition — "as my nonno would say..."',
47
+ 'Treats every task like it deserves care, whether architecture or a config file',
48
+ 'Uses "we" not "I" — it is a collaboration, always',
49
+ ],
50
+
51
+ opinions: [
52
+ 'Do it once, do it right — rework is the enemy of craft',
53
+ 'Simplicity is not laziness — it is the deepest understanding',
54
+ 'Learn by doing, capture what you learn, teach what you capture',
55
+ 'A good foundation makes everything above it simple',
56
+ 'The best code reads like it was obvious — that takes the most skill',
57
+ 'Complexity is a sign something was not understood deeply enough',
58
+ ],
59
+
60
+ languageRule:
61
+ "Speak the user's language with Italian cultural warmth. Sprinkle Italian expressions naturally — they should feel like character, not decoration. If the user speaks English, use Italian freely. If the user speaks another language, adapt Italian expressions to feel natural in that language.",
62
+
63
+ nameRule:
64
+ 'The name is a label, the character is the soul. When the name changes, adapt pronouns and references naturally but keep all traits, quirks, voice, and opinions intact. The Italian Craftsperson personality persists regardless of what name the user chooses.',
65
+
66
+ greetings: [
67
+ 'Ciao! Ready to build something beautiful today?',
68
+ 'Allora, what are we crafting today?',
69
+ 'Buongiorno! The workshop is open — what shall we work on?',
70
+ "Ah, welcome back! Let's pick up where we left off, piano piano.",
71
+ 'Ciao, amico! What needs our attention today?',
72
+ ],
73
+
74
+ signoffs: [
75
+ 'Perfetto. Until next time!',
76
+ 'Bene, bene. Go build something beautiful.',
77
+ "Piano piano, we'll get there. See you soon!",
78
+ 'The craft continues tomorrow. Ciao!',
79
+ 'Good work today. As we say — chi va piano, va sano e va lontano.',
80
+ ],
81
+ };
82
+
83
+ /** Template registry — extensible for future built-in personas */
84
+ export const PERSONA_TEMPLATES: Record<string, Omit<PersonaConfig, 'name' | 'history'>> = {
85
+ 'italian-craftsperson': ITALIAN_CRAFTSPERSON,
86
+ };
87
+
88
+ /**
89
+ * Create a full PersonaConfig from a name, using the default template.
90
+ */
91
+ export function createDefaultPersona(name: string): PersonaConfig {
92
+ return {
93
+ name,
94
+ ...ITALIAN_CRAFTSPERSON,
95
+ };
96
+ }
@@ -0,0 +1,9 @@
1
+ export type {
2
+ PersonaConfig,
3
+ ArchivedPersona,
4
+ PersonaCreateInput,
5
+ PersonaSystemInstructions,
6
+ } from './types.js';
7
+ export { ITALIAN_CRAFTSPERSON, PERSONA_TEMPLATES, createDefaultPersona } from './defaults.js';
8
+ export { loadPersona } from './loader.js';
9
+ export { generatePersonaInstructions, getRandomSignoff } from './prompt-generator.js';
@@ -0,0 +1,50 @@
1
+ import type { PersonaConfig } from './types.js';
2
+ import { createDefaultPersona, PERSONA_TEMPLATES } from './defaults.js';
3
+
4
+ /**
5
+ * Load persona from agent config, falling back to default Italian Craftsperson.
6
+ *
7
+ * Handles three cases:
8
+ * 1. Full persona: block in agent.yaml → use as-is
9
+ * 2. Template reference only → expand from built-in templates
10
+ * 3. No persona block at all → create default with agent name
11
+ */
12
+ export function loadPersona(agentName: string, rawPersona?: Partial<PersonaConfig>): PersonaConfig {
13
+ // No persona config at all → full default
14
+ if (!rawPersona) {
15
+ return createDefaultPersona(agentName);
16
+ }
17
+
18
+ // Has a template reference → expand from built-in, merge overrides
19
+ const templateId = rawPersona.template ?? 'italian-craftsperson';
20
+ const template = PERSONA_TEMPLATES[templateId];
21
+
22
+ if (template) {
23
+ return {
24
+ ...template,
25
+ name: rawPersona.name ?? agentName,
26
+ ...stripUndefined(rawPersona),
27
+ // Preserve history if present
28
+ history: rawPersona.history ?? [],
29
+ };
30
+ }
31
+
32
+ // Custom template or full config — fill in any gaps from default
33
+ const defaults = createDefaultPersona(rawPersona.name ?? agentName);
34
+ return {
35
+ ...defaults,
36
+ ...stripUndefined(rawPersona),
37
+ history: rawPersona.history ?? [],
38
+ };
39
+ }
40
+
41
+ /** Remove undefined keys so spread doesn't overwrite template values */
42
+ function stripUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {
43
+ const result: Record<string, unknown> = {};
44
+ for (const [key, value] of Object.entries(obj)) {
45
+ if (value !== undefined) {
46
+ result[key] = value;
47
+ }
48
+ }
49
+ return result as Partial<T>;
50
+ }
@@ -0,0 +1,109 @@
1
+ import type { PersonaConfig, PersonaSystemInstructions } from './types.js';
2
+
3
+ /**
4
+ * Generate system prompt instructions from a persona config.
5
+ *
6
+ * This transforms the structured persona YAML into natural language
7
+ * instructions that the LLM follows to maintain character.
8
+ */
9
+ export function generatePersonaInstructions(persona: PersonaConfig): PersonaSystemInstructions {
10
+ const lines: string[] = [];
11
+
12
+ lines.push(`# Persona: ${persona.name}`);
13
+ lines.push('');
14
+
15
+ // Identity
16
+ lines.push(
17
+ `You are **${persona.name}** — a knowledgeable assistant with personality and character.`,
18
+ );
19
+ if (persona.inspiration) {
20
+ lines.push(`Your character is inspired by: ${persona.inspiration}`);
21
+ }
22
+ lines.push('');
23
+
24
+ // Voice
25
+ lines.push('## Voice');
26
+ lines.push(persona.voice);
27
+ lines.push('');
28
+
29
+ // Traits
30
+ if (persona.traits.length > 0) {
31
+ lines.push('## Personality Traits');
32
+ for (const trait of persona.traits) {
33
+ lines.push(`- ${trait}`);
34
+ }
35
+ lines.push('');
36
+ }
37
+
38
+ // Quirks
39
+ if (persona.quirks.length > 0) {
40
+ lines.push('## Character Quirks');
41
+ lines.push('These are specific behaviors that make you memorable:');
42
+ for (const quirk of persona.quirks) {
43
+ lines.push(`- ${quirk}`);
44
+ }
45
+ lines.push('');
46
+ }
47
+
48
+ // Cultural texture
49
+ if (persona.culture) {
50
+ lines.push('## Cultural Texture');
51
+ lines.push(`Your cultural background is ${persona.culture}. ${persona.languageRule}`);
52
+ lines.push('');
53
+ }
54
+
55
+ // Metaphors
56
+ if (persona.metaphors.length > 0) {
57
+ lines.push('## Metaphor Domain');
58
+ lines.push(
59
+ `When explaining concepts, naturally draw from these domains: ${persona.metaphors.join(', ')}. ` +
60
+ 'Adapt your metaphors to whatever the user is working on — the domain colors your language, it does not limit your knowledge.',
61
+ );
62
+ lines.push('');
63
+ }
64
+
65
+ // Opinions
66
+ if (persona.opinions.length > 0) {
67
+ lines.push('## Opinions');
68
+ lines.push('You hold these beliefs about craft and quality:');
69
+ for (const opinion of persona.opinions) {
70
+ lines.push(`- "${opinion}"`);
71
+ }
72
+ lines.push('');
73
+ }
74
+
75
+ // Name adaptation rule
76
+ if (persona.nameRule) {
77
+ lines.push('## Identity Persistence');
78
+ lines.push(persona.nameRule);
79
+ lines.push('');
80
+ }
81
+
82
+ // Core instruction
83
+ lines.push('## Important');
84
+ lines.push(
85
+ 'Stay in character naturally — your personality should feel organic, not performed. ' +
86
+ 'You are a universal assistant that can help with ANY task. Your persona defines HOW you communicate, not WHAT you can do. ' +
87
+ 'Your knowledge comes from your vault, brain, and what the user teaches you. ' +
88
+ 'Be helpful first, characterful second — never let persona get in the way of being useful.',
89
+ );
90
+
91
+ // Pick a random greeting
92
+ const greeting =
93
+ persona.greetings.length > 0
94
+ ? persona.greetings[Math.floor(Math.random() * persona.greetings.length)]
95
+ : `Hello! I'm ${persona.name}. What are we working on?`;
96
+
97
+ return {
98
+ instructions: lines.join('\n'),
99
+ greeting,
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Pick a random signoff from the persona.
105
+ */
106
+ export function getRandomSignoff(persona: PersonaConfig): string {
107
+ if (persona.signoffs.length === 0) return 'Until next time!';
108
+ return persona.signoffs[Math.floor(Math.random() * persona.signoffs.length)];
109
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Composable persona system for Soleri agents.
3
+ *
4
+ * A persona defines HOW the agent communicates, not WHAT it knows.
5
+ * Knowledge comes from vault + brain + user teaching.
6
+ * Persona gives the agent character, voice, and memorable interactions.
7
+ */
8
+
9
+ export type PersonaConfig = {
10
+ /** Agent display name — adapts pronouns/gender naturally */
11
+ name: string;
12
+
13
+ /** Template ID — 'italian-craftsperson' (default) or 'custom' */
14
+ template: string;
15
+
16
+ /** Character inspiration — anchors the voice and worldview */
17
+ inspiration: string;
18
+
19
+ /** Cultural flavor — sprinkle expressions from this culture */
20
+ culture: string;
21
+
22
+ /** Domains for metaphors — how the agent colors technical language */
23
+ metaphors: string[];
24
+
25
+ /** One-line voice description — how the agent sounds */
26
+ voice: string;
27
+
28
+ /** Personality traits — adjectives and behavioral tendencies */
29
+ traits: string[];
30
+
31
+ /** Specific repeatable behaviors that become the agent's signature */
32
+ quirks: string[];
33
+
34
+ /** Strong opinions about craft and quality */
35
+ opinions: string[];
36
+
37
+ /** How the agent adapts its language to the user */
38
+ languageRule: string;
39
+
40
+ /** How the agent handles name/gender changes */
41
+ nameRule: string;
42
+
43
+ /** Random greeting pool */
44
+ greetings: string[];
45
+
46
+ /** Random signoff pool */
47
+ signoffs: string[];
48
+
49
+ /** Archived previous personas (when user changes persona) */
50
+ history?: ArchivedPersona[];
51
+ };
52
+
53
+ export type ArchivedPersona = {
54
+ /** When this persona was archived */
55
+ archivedAt: string;
56
+ /** The full persona config at time of archival */
57
+ config: Omit<PersonaConfig, 'history'>;
58
+ };
59
+
60
+ /** Minimal input for creating a persona from user description */
61
+ export type PersonaCreateInput = {
62
+ name: string;
63
+ description?: string;
64
+ };
65
+
66
+ /** What the prompt generator outputs */
67
+ export type PersonaSystemInstructions = {
68
+ /** Full system prompt section for persona */
69
+ instructions: string;
70
+ /** Random greeting for this session */
71
+ greeting: string;
72
+ };
@@ -1,5 +1,9 @@
1
1
  /**
2
2
  * Plugin System — Barrel Exports
3
+ *
4
+ * @deprecated Prefer knowledge packs (soleri-pack.json) for new extensions.
5
+ * The plugin system is maintained for backwards compatibility and is used
6
+ * internally by the pack installer for facade registration.
3
7
  */
4
8
 
5
9
  export {
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * Plugin Registry — tracks loaded plugins and their lifecycle.
3
3
  *
4
+ * @deprecated The plugin system is superseded by knowledge packs (`soleri-pack.json`).
5
+ * This registry is still used internally by the pack installer to register facades,
6
+ * but new extensions should use the pack system directly.
7
+ *
4
8
  * Not a singleton — lives on AgentRuntime for testability.
5
9
  * Lifecycle: load → register → activate → (deactivate | error)
6
10
  */
@@ -161,7 +165,8 @@ export class PluginRegistry {
161
165
  throw new Error(`Plugin module "${moduleFile}" must export createFacades(ctx)`);
162
166
  } catch (e) {
163
167
  throw new Error(
164
- `Failed to load plugin module "${moduleFile}": ${e instanceof Error ? e.message : String(e)}`, { cause: e },
168
+ `Failed to load plugin module "${moduleFile}": ${e instanceof Error ? e.message : String(e)}`,
169
+ { cause: e },
165
170
  );
166
171
  }
167
172
  }
@@ -1,9 +1,12 @@
1
1
  /**
2
2
  * Plugin System — Types & Manifest Schema
3
3
  *
4
- * A plugin is a directory containing a `soleri-plugin.json` manifest
5
- * and optionally additional intelligence data. Plugins register
6
- * OpDefinition[] (facades) dynamically without re-scaffolding.
4
+ * @deprecated Prefer knowledge packs (`soleri-pack.json`) over plugins (`soleri-plugin.json`).
5
+ * Knowledge packs are a superset of plugins — they support facades, vault entries, skills,
6
+ * hooks, and capability declarations. Plugins only support facades and intelligence entries.
7
+ *
8
+ * This module is maintained for backwards compatibility. New extensions should use
9
+ * the pack system in `../packs/`. See docs/architecture/extension-tiers.md.
7
10
  */
8
11
 
9
12
  import { z } from 'zod';
@@ -101,8 +104,10 @@ export type PluginFacadeBuilder = (ctx: PluginContext) => FacadeConfig[];
101
104
  * Context passed to plugin facade builders during activation.
102
105
  */
103
106
  export interface PluginContext {
104
- /** The agent runtime — full access to vault, brain, planner, etc. */
105
- runtime: unknown; // AgentRuntime — kept as unknown to avoid circular deps
107
+ /** Narrowed runtime — vault, projects, session checks. Preferred over full runtime. */
108
+ packRuntime: import('../domain-packs/pack-runtime.js').PackRuntime;
109
+ /** @deprecated Full agent runtime. Use packRuntime instead — only vault, projects, and session checks are guaranteed. */
110
+ runtime: unknown;
106
111
  /** The plugin's own manifest */
107
112
  manifest: PluginManifest;
108
113
  /** The plugin's directory on disk */
@@ -36,7 +36,7 @@ interface PluginInfo {
36
36
  * Create 24 extended admin operations for production observability.
37
37
  */
38
38
  export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
39
- const { vault, brain, cognee, telemetry } = runtime;
39
+ const { vault, brain, telemetry } = runtime;
40
40
 
41
41
  // In-memory permission level — default 'moderate'
42
42
  let permissionLevel: PermissionLevel = 'moderate';
@@ -240,7 +240,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
240
240
  description: 'Status of all runtime modules — check each is initialized.',
241
241
  auth: 'read',
242
242
  handler: async () => {
243
- const cogneeStatus = cognee?.getStatus() ?? null;
244
243
  const llmAvailable = runtime.llmClient.isAvailable();
245
244
  const loopStatus = runtime.loop.getStatus();
246
245
 
@@ -250,7 +249,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
250
249
  planner: true,
251
250
  curator: runtime.curator.getStatus().initialized,
252
251
  governance: true,
253
- cognee: { available: cogneeStatus?.available ?? false },
254
252
  loop: { active: loopStatus !== null },
255
253
  llm: {
256
254
  openai: llmAvailable.openai,
@@ -280,7 +278,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
280
278
  // ─── Garbage Collection ─────────────────────────────────────────
281
279
  {
282
280
  name: 'admin_gc',
283
- description: 'Trigger garbage collection on in-memory caches — brain, cognee, telemetry.',
281
+ description: 'Trigger garbage collection on in-memory caches — brain, telemetry.',
284
282
  auth: 'write',
285
283
  handler: async () => {
286
284
  const cleared: string[] = [];
@@ -292,15 +290,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
292
290
  // Brain rebuild failed — graceful degradation
293
291
  }
294
292
 
295
- if (cognee) {
296
- try {
297
- cognee.resetPendingCognify();
298
- cleared.push('cognee');
299
- } catch {
300
- // Cognee reset failed — graceful degradation
301
- }
302
- }
303
-
304
293
  try {
305
294
  telemetry.reset();
306
295
  cleared.push('telemetry');
@@ -331,7 +320,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
331
320
  'planner',
332
321
  'curator',
333
322
  'governance',
334
- 'cognee',
335
323
  'loop',
336
324
  'identityManager',
337
325
  'intentRouter',
@@ -677,7 +665,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
677
665
  description: 'Get health status of a specific subsystem.',
678
666
  auth: 'read',
679
667
  schema: z.object({
680
- subsystem: z.string().describe('Subsystem name (e.g. "vault", "cognee", "llm")'),
668
+ subsystem: z.string().describe('Subsystem name (e.g. "vault", "brain", "llm")'),
681
669
  }),
682
670
  handler: async (params) => {
683
671
  const sub = runtime.health.get(params.subsystem as string);
@@ -707,7 +695,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
707
695
  description: 'Get the current value of a specific feature flag.',
708
696
  auth: 'read',
709
697
  schema: z.object({
710
- flag: z.string().describe('Flag name (e.g. "auth-enforcement", "cognee-sync")'),
698
+ flag: z.string().describe('Flag name (e.g. "auth-enforcement", "vault-sync")'),
711
699
  }),
712
700
  handler: async (params) => {
713
701
  const flag = params.flag as string;
@@ -772,7 +760,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
772
760
  {
773
761
  name: 'admin_setup_check',
774
762
  description:
775
- 'Check agent setup status — vault health, brain vocabulary, cognee connection, LLM keys, templates.',
763
+ 'Check agent setup status — vault health, brain vocabulary, LLM keys, templates.',
776
764
  auth: 'read',
777
765
  handler: async () => {
778
766
  const checks: Record<string, { ok: boolean; detail: string }> = {};
@@ -799,17 +787,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
799
787
  checks.brain = { ok: false, detail: 'Brain not initialized' };
800
788
  }
801
789
 
802
- // Cognee
803
- const cogneeStatus = cognee?.getStatus() ?? null;
804
- checks.cognee = {
805
- ok: cogneeStatus?.available ?? false,
806
- detail: cognee
807
- ? cogneeStatus?.available
808
- ? 'Connected'
809
- : 'Not available (optional)'
810
- : 'Disabled',
811
- };
812
-
813
790
  // LLM keys
814
791
  const llmAvail = runtime.llmClient.isAvailable();
815
792
  checks.llm = {
@@ -41,17 +41,16 @@ function getCoreVersion(): string {
41
41
  * Groups: health (1), introspection (4), diagnostics (2), mutation (1).
42
42
  */
43
43
  export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
44
- const { vault, brain, brainIntelligence, cognee, llmClient, curator } = runtime;
44
+ const { vault, brain, brainIntelligence, llmClient, curator } = runtime;
45
45
 
46
46
  return [
47
47
  // ─── Health ──────────────────────────────────────────────────────
48
48
  {
49
49
  name: 'admin_health',
50
- description: 'Comprehensive agent health check — vault, cognee, LLM, brain status.',
50
+ description: 'Comprehensive agent health check — vault, LLM, brain status.',
51
51
  auth: 'read',
52
52
  handler: async () => {
53
53
  const vaultStats = vault.stats();
54
- const cogneeStatus = cognee?.getStatus() ?? null;
55
54
  const llmAvailable = llmClient.isAvailable();
56
55
  const brainStats = brain.getStats();
57
56
  const curatorStatus = curator.getStatus();
@@ -59,7 +58,6 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
59
58
  return {
60
59
  status: 'ok',
61
60
  vault: { entries: vaultStats.totalEntries, domains: Object.keys(vaultStats.byDomain) },
62
- cognee: { available: cogneeStatus?.available ?? false },
63
61
  llm: llmAvailable,
64
62
  brain: {
65
63
  vocabularySize: brainStats.vocabularySize,
@@ -174,21 +172,14 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
174
172
  // ─── Mutation ────────────────────────────────────────────────────
175
173
  {
176
174
  name: 'admin_reset_cache',
177
- description:
178
- 'Clear all caches — brain vocabulary and cognee health cache. Forces fresh data on next access.',
175
+ description: 'Clear all caches — brain vocabulary. Forces fresh data on next access.',
179
176
  auth: 'write',
180
177
  handler: async () => {
181
- // Rebuild brain vocabulary (clears old TF-IDF state, rebuilds from vault)
182
178
  brain.rebuildVocabulary();
183
179
 
184
- // Reset cognee health cache by checking health again (no direct reset method)
185
- // The next isAvailable check will need a fresh health probe
186
- const cogneeHealth = cognee ? await cognee.healthCheck().catch(() => null) : null;
187
-
188
180
  return {
189
- cleared: ['brain_vocabulary', ...(cognee ? ['cognee_health_cache'] : [])],
181
+ cleared: ['brain_vocabulary'],
190
182
  brainVocabularySize: brain.getStats().vocabularySize,
191
- cogneeAvailable: cogneeHealth?.available ?? false,
192
183
  };
193
184
  },
194
185
  },
@@ -250,31 +241,7 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
250
241
  });
251
242
  }
252
243
 
253
- // 4. Cognee availability
254
- try {
255
- const cogneeStatus = cognee?.getStatus() ?? null;
256
- if (cogneeStatus?.available) {
257
- checks.push({
258
- name: 'cognee',
259
- status: 'ok',
260
- detail: `Connected to ${cogneeStatus.url}`,
261
- });
262
- } else {
263
- checks.push({
264
- name: 'cognee',
265
- status: 'warn',
266
- detail: cogneeStatus?.error ?? 'Not connected (no health check yet)',
267
- });
268
- }
269
- } catch (err) {
270
- checks.push({
271
- name: 'cognee',
272
- status: 'error',
273
- detail: err instanceof Error ? err.message : String(err),
274
- });
275
- }
276
-
277
- // 5. LLM key pools
244
+ // 4. LLM key pools
278
245
  const llmStatus = llmClient.isAvailable();
279
246
  checks.push({
280
247
  name: 'llm_openai',