@mohanscodex/spectra-agent 0.4.9 → 0.5.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=skill-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/skill-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,156 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, rmSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { tmpdir } from 'os';
5
+ describe('Evolving skill store', () => {
6
+ let tmpDir;
7
+ let originalHome;
8
+ beforeEach(() => {
9
+ tmpDir = mkdtempSync(join(tmpdir(), 'spectra-evolve-'));
10
+ originalHome = process.env.SPECTRA_HOME;
11
+ process.env.SPECTRA_HOME = tmpDir;
12
+ });
13
+ afterEach(() => {
14
+ if (originalHome !== undefined) {
15
+ process.env.SPECTRA_HOME = originalHome;
16
+ }
17
+ else {
18
+ delete process.env.SPECTRA_HOME;
19
+ }
20
+ rmSync(tmpDir, { recursive: true, force: true });
21
+ });
22
+ it('saves and loads an evolving skill', async () => {
23
+ const { saveEvolvingSkill, loadEvolvingSkill } = await import('../skill-store.js');
24
+ const meta = {
25
+ id: 'test-skill',
26
+ name: 'Test Skill',
27
+ description: 'A test skill',
28
+ whenToUse: 'when testing',
29
+ tags: ['test'],
30
+ useCount: 0,
31
+ version: 1,
32
+ createdAt: new Date().toISOString(),
33
+ updatedAt: new Date().toISOString(),
34
+ origin: 'learned',
35
+ };
36
+ await saveEvolvingSkill(meta, '---\nname: Test Skill\n---\n\n# Test');
37
+ const loaded = await loadEvolvingSkill('test-skill');
38
+ expect(loaded).not.toBeNull();
39
+ expect(loaded.meta.name).toBe('Test Skill');
40
+ expect(loaded.meta.useCount).toBe(0);
41
+ expect(loaded.content).toContain('# Test');
42
+ });
43
+ it('increments useCount', async () => {
44
+ const { saveEvolvingSkill, loadEvolvingSkill, incrementUseCount } = await import('../skill-store.js');
45
+ const meta = {
46
+ id: 'count-test',
47
+ name: 'Count Test',
48
+ description: 'Test',
49
+ whenToUse: '',
50
+ tags: [],
51
+ useCount: 0,
52
+ version: 1,
53
+ createdAt: new Date().toISOString(),
54
+ updatedAt: new Date().toISOString(),
55
+ origin: 'learned',
56
+ };
57
+ await saveEvolvingSkill(meta, '# Test');
58
+ await incrementUseCount('count-test');
59
+ await incrementUseCount('count-test');
60
+ const loaded = await loadEvolvingSkill('count-test');
61
+ expect(loaded.meta.useCount).toBe(2);
62
+ });
63
+ it('loads all evolving skills', async () => {
64
+ const { saveEvolvingSkill, loadAllEvolvingSkills } = await import('../skill-store.js');
65
+ for (let i = 0; i < 3; i++) {
66
+ await saveEvolvingSkill({
67
+ id: `skill-${i}`,
68
+ name: `Skill ${i}`,
69
+ description: `Skill number ${i}`,
70
+ whenToUse: '',
71
+ tags: [],
72
+ useCount: 0,
73
+ version: 1,
74
+ createdAt: new Date().toISOString(),
75
+ updatedAt: new Date().toISOString(),
76
+ origin: 'learned',
77
+ }, `# Skill ${i}`);
78
+ }
79
+ const all = await loadAllEvolvingSkills();
80
+ expect(all.length).toBe(3);
81
+ });
82
+ it('evolves a skill (version bump)', async () => {
83
+ const { saveEvolvingSkill, loadEvolvingSkill, evolveSkill } = await import('../skill-store.js');
84
+ const meta = {
85
+ id: 'evolve-test',
86
+ name: 'Evolve Test',
87
+ description: 'Original',
88
+ whenToUse: '',
89
+ tags: [],
90
+ useCount: 5,
91
+ version: 1,
92
+ createdAt: new Date().toISOString(),
93
+ updatedAt: new Date().toISOString(),
94
+ origin: 'learned',
95
+ };
96
+ await saveEvolvingSkill(meta, '# Original');
97
+ await evolveSkill('evolve-test', { description: 'Updated' }, '# Updated');
98
+ const loaded = await loadEvolvingSkill('evolve-test');
99
+ expect(loaded.meta.version).toBe(2);
100
+ expect(loaded.meta.description).toBe('Updated');
101
+ expect(loaded.meta.origin).toBe('evolved');
102
+ expect(loaded.meta.useCount).toBe(5); // preserved
103
+ });
104
+ it('returns null for non-existent skill', async () => {
105
+ const { loadEvolvingSkill } = await import('../skill-store.js');
106
+ const loaded = await loadEvolvingSkill('does-not-exist');
107
+ expect(loaded).toBeNull();
108
+ });
109
+ });
110
+ describe('Skill synthesis eligibility', () => {
111
+ it('rejects sessions with too few tool calls', async () => {
112
+ const { isSessionEligibleForSynthesis } = await import('../skill-synth.js');
113
+ const trace = {
114
+ messages: [
115
+ { role: 'user', content: 'Hello', timestamp: Date.now() },
116
+ { role: 'assistant', content: [{ type: 'text', text: 'Hi' }], timestamp: Date.now() },
117
+ ],
118
+ toolCalls: [{ name: 'read', args: {}, success: true }],
119
+ duration: 1000,
120
+ };
121
+ expect(isSessionEligibleForSynthesis(trace)).toBe(false);
122
+ });
123
+ it('rejects sessions with too few messages', async () => {
124
+ const { isSessionEligibleForSynthesis } = await import('../skill-synth.js');
125
+ const trace = {
126
+ messages: [
127
+ { role: 'user', content: 'Hello', timestamp: Date.now() },
128
+ ],
129
+ toolCalls: [
130
+ { name: 'read', args: {}, success: true },
131
+ { name: 'write', args: {}, success: true },
132
+ { name: 'bash', args: {}, success: true },
133
+ ],
134
+ duration: 1000,
135
+ };
136
+ expect(isSessionEligibleForSynthesis(trace)).toBe(false);
137
+ });
138
+ it('accepts sessions with enough tool calls and messages', async () => {
139
+ const { isSessionEligibleForSynthesis } = await import('../skill-synth.js');
140
+ const trace = {
141
+ messages: Array.from({ length: 8 }, (_, i) => ({
142
+ role: i % 2 === 0 ? 'user' : 'assistant',
143
+ content: i % 2 === 0 ? `Message ${i}` : [{ type: 'text', text: `Response ${i}` }],
144
+ timestamp: Date.now(),
145
+ })),
146
+ toolCalls: [
147
+ { name: 'read', args: {}, success: true },
148
+ { name: 'write', args: {}, success: true },
149
+ { name: 'bash', args: {}, success: true },
150
+ ],
151
+ duration: 5000,
152
+ };
153
+ expect(isSessionEligibleForSynthesis(trace)).toBe(true);
154
+ });
155
+ });
156
+ //# sourceMappingURL=skill-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-store.test.js","sourceRoot":"","sources":["../../src/__tests__/skill-store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=skill.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/skill.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { tmpdir } from 'os';
5
+ describe('Skill frontmatter parsing', () => {
6
+ let tmpDir;
7
+ beforeEach(() => {
8
+ tmpDir = mkdtempSync(join(tmpdir(), 'spectra-skill-'));
9
+ });
10
+ afterEach(() => {
11
+ rmSync(tmpDir, { recursive: true, force: true });
12
+ });
13
+ it('parses LF line endings', async () => {
14
+ const skillDir = join(tmpDir, 'test-skill');
15
+ mkdirSync(skillDir, { recursive: true });
16
+ writeFileSync(join(skillDir, 'SKILL.md'), '---\nname: Test Skill\ndescription: A test skill\n---\n\n# Body');
17
+ const { discoverSkills } = await import('../skill.js');
18
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
19
+ expect(skills.has('Test Skill')).toBe(true);
20
+ expect(skills.get('Test Skill').description).toBe('A test skill');
21
+ });
22
+ it('parses CRLF line endings', async () => {
23
+ const skillDir = join(tmpDir, 'crlf-skill');
24
+ mkdirSync(skillDir, { recursive: true });
25
+ writeFileSync(join(skillDir, 'SKILL.md'), '---\r\nname: CRLF Skill\r\ndescription: Has CRLF\r\n---\r\n\r\n# Body');
26
+ const { discoverSkills } = await import('../skill.js');
27
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
28
+ expect(skills.has('CRLF Skill')).toBe(true);
29
+ expect(skills.get('CRLF Skill').description).toBe('Has CRLF');
30
+ });
31
+ it('handles mixed line endings in same file', async () => {
32
+ const skillDir = join(tmpDir, 'mixed-skill');
33
+ mkdirSync(skillDir, { recursive: true });
34
+ writeFileSync(join(skillDir, 'SKILL.md'), '---\r\nname: Mixed Skill\r\ndescription: Mixed endings\n---\n\n# Body');
35
+ const { discoverSkills } = await import('../skill.js');
36
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
37
+ expect(skills.has('Mixed Skill')).toBe(true);
38
+ });
39
+ it('returns empty name for files without frontmatter', async () => {
40
+ const skillDir = join(tmpDir, 'no-frontmatter');
41
+ mkdirSync(skillDir, { recursive: true });
42
+ writeFileSync(join(skillDir, 'SKILL.md'), '# Just a heading\n\nNo frontmatter here.');
43
+ const { discoverSkills } = await import('../skill.js');
44
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
45
+ // The no-frontmatter skill should not be found (empty name filtered out)
46
+ const allNames = Array.from(skills.keys());
47
+ expect(allNames).not.toContain('');
48
+ });
49
+ });
50
+ describe('Skill discovery — nested directories', () => {
51
+ let tmpDir;
52
+ beforeEach(() => {
53
+ tmpDir = mkdtempSync(join(tmpdir(), 'spectra-nested-'));
54
+ });
55
+ afterEach(() => {
56
+ rmSync(tmpDir, { recursive: true, force: true });
57
+ });
58
+ it('discovers skills in category subdirectories', async () => {
59
+ const catDir = join(tmpDir, 'debugging');
60
+ const skillDir = join(catDir, 'my-debug-skill');
61
+ mkdirSync(skillDir, { recursive: true });
62
+ writeFileSync(join(skillDir, 'SKILL.md'), '---\nname: Debug Skill\ndescription: Debug stuff\n---\n\n# Debug');
63
+ const { discoverSkills } = await import('../skill.js');
64
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
65
+ expect(skills.has('Debug Skill')).toBe(true);
66
+ });
67
+ it('discovers both top-level and nested skills', async () => {
68
+ // Top-level skill
69
+ const topDir = join(tmpDir, 'top-skill');
70
+ mkdirSync(topDir, { recursive: true });
71
+ writeFileSync(join(topDir, 'SKILL.md'), '---\nname: Top Skill\ndescription: Top level\n---\n\n# Top');
72
+ // Nested skill
73
+ const catDir = join(tmpDir, 'category');
74
+ const nestedDir = join(catDir, 'nested-skill');
75
+ mkdirSync(nestedDir, { recursive: true });
76
+ writeFileSync(join(nestedDir, 'SKILL.md'), '---\nname: Nested Skill\ndescription: Nested level\n---\n\n# Nested');
77
+ const { discoverSkills } = await import('../skill.js');
78
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
79
+ expect(skills.has('Top Skill')).toBe(true);
80
+ expect(skills.has('Nested Skill')).toBe(true);
81
+ });
82
+ it('skips directories without SKILL.md', async () => {
83
+ const emptyDir = join(tmpDir, 'empty-category');
84
+ mkdirSync(emptyDir, { recursive: true });
85
+ writeFileSync(join(emptyDir, 'readme.txt'), 'No skills here');
86
+ const { discoverSkills } = await import('../skill.js');
87
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
88
+ // Should not find any skills from the empty category
89
+ const allNames = Array.from(skills.keys());
90
+ expect(allNames.some((n) => n.includes('empty-category') || n.includes('readme'))).toBe(false);
91
+ });
92
+ });
93
+ describe('Skill tag extraction', () => {
94
+ let tmpDir;
95
+ beforeEach(() => {
96
+ tmpDir = mkdtempSync(join(tmpdir(), 'spectra-tags-'));
97
+ });
98
+ afterEach(() => {
99
+ rmSync(tmpDir, { recursive: true, force: true });
100
+ });
101
+ it('extracts category from directory path', async () => {
102
+ // Category extraction requires a "skills" segment in the path
103
+ const skillsDir = join(tmpDir, 'skills');
104
+ const catDir = join(skillsDir, 'deployment');
105
+ const skillDir = join(catDir, 'vercel-deploy');
106
+ mkdirSync(skillDir, { recursive: true });
107
+ writeFileSync(join(skillDir, 'SKILL.md'), '---\nname: Vercel Deploy\ndescription: Deploy to Vercel\n---\n\n# Deploy');
108
+ const { discoverSkills } = await import('../skill.js');
109
+ const skills = await discoverSkills({ customPaths: [skillsDir] });
110
+ const skill = skills.get('Vercel Deploy');
111
+ expect(skill).toBeDefined();
112
+ expect(skill.tags).toContain('deployment');
113
+ expect(skill.tags).toContain('vercel');
114
+ expect(skill.tags).toContain('deploy');
115
+ });
116
+ it('extracts name segments as tags', async () => {
117
+ const skillDir = join(tmpDir, 'test-driven-development');
118
+ mkdirSync(skillDir, { recursive: true });
119
+ writeFileSync(join(skillDir, 'SKILL.md'), '---\nname: Test Driven Development\ndescription: TDD workflow\n---\n\n# TDD');
120
+ const { discoverSkills } = await import('../skill.js');
121
+ const skills = await discoverSkills({ customPaths: [tmpDir] });
122
+ const skill = skills.get('Test Driven Development');
123
+ expect(skill).toBeDefined();
124
+ expect(skill.tags).toContain('test');
125
+ expect(skill.tags).toContain('driven');
126
+ expect(skill.tags).toContain('development');
127
+ });
128
+ });
129
+ //# sourceMappingURL=skill.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.test.js","sourceRoot":"","sources":["../../src/__tests__/skill.test.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  export { Agent } from './agent.js';
2
2
  export { defineTool } from './define-tool.js';
3
+ export type { Skill, SkillMetadata, SkillDiscoveryOptions, MatchResult, SkillIndex, } from './skill.js';
4
+ export { discoverSkills, getSkillDescription, buildAvailableSkillsBlock, formatSkillCatalogEntry, loadSkillContent, substituteVariables, buildIndex, matchSkills, getSkillIndex, invalidateSkillIndex, } from './skill.js';
5
+ export { createSkillTool, createFindSkillsTool } from './tool/skill.js';
6
+ export { loadEvolvingSkill, loadAllEvolvingSkills, saveEvolvingSkill, incrementUseCount, findSimilarSkill, evolveSkill, forkSkill, } from './skill-store.js';
7
+ export type { EvolvingSkillMeta } from './skill-store.js';
8
+ export { synthesizeSkill, isSessionEligibleForSynthesis } from './skill-synth.js';
9
+ export type { SessionTrace } from './skill-synth.js';
3
10
  export type { AgentTool, ToolResult, ToolUpdateCallback, ToolExecutionMode, BeforeToolCallContext, AfterToolCallContext, BeforeToolCallResult, AfterToolCallResult, AgentEvent, AgentEventListener, AgentState, AgentConfig, RetryContext, RetryDecision, } from './types.js';
4
11
  export type { AssistantMessageEvent } from '@mohanscodex/spectra-ai';
5
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACX,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACX,KAAK,EACL,aAAa,EACb,qBAAqB,EACrB,WAAW,EACX,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,yBAAyB,EACzB,uBAAuB,EACvB,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,aAAa,EACb,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACN,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,SAAS,GACT,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EACX,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,7 @@
1
1
  export { Agent } from './agent.js';
2
2
  export { defineTool } from './define-tool.js';
3
+ export { discoverSkills, getSkillDescription, buildAvailableSkillsBlock, formatSkillCatalogEntry, loadSkillContent, substituteVariables, buildIndex, matchSkills, getSkillIndex, invalidateSkillIndex, } from './skill.js';
4
+ export { createSkillTool, createFindSkillsTool } from './tool/skill.js';
5
+ export { loadEvolvingSkill, loadAllEvolvingSkills, saveEvolvingSkill, incrementUseCount, findSimilarSkill, evolveSkill, forkSkill, } from './skill-store.js';
6
+ export { synthesizeSkill, isSessionEligibleForSynthesis } from './skill-synth.js';
3
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQ9C,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,yBAAyB,EACzB,uBAAuB,EACvB,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,aAAa,EACb,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACN,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,SAAS,GACT,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { Skill } from './skill.js';
2
+ export interface EvolvingSkillMeta {
3
+ id: string;
4
+ name: string;
5
+ description: string;
6
+ whenToUse: string;
7
+ tags: string[];
8
+ useCount: number;
9
+ version: number;
10
+ parentId?: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ origin: 'learned' | 'evolved';
14
+ }
15
+ export declare function ensureSkillsDir(): Promise<void>;
16
+ export declare function saveEvolvingSkill(skill: EvolvingSkillMeta, content: string): Promise<void>;
17
+ export declare function loadEvolvingSkill(id: string): Promise<{
18
+ meta: EvolvingSkillMeta;
19
+ content: string;
20
+ } | null>;
21
+ export declare function loadAllEvolvingSkills(): Promise<Skill[]>;
22
+ export declare function incrementUseCount(id: string): Promise<void>;
23
+ export declare function findSimilarSkill(name: string, description: string, whenToUse: string, existingSkills: Skill[]): Promise<Skill | null>;
24
+ export declare function evolveSkill(existingId: string, updates: Partial<EvolvingSkillMeta>, content: string): Promise<void>;
25
+ export declare function forkSkill(parentId: string, newId: string, newName: string, content: string): Promise<void>;
26
+ //# sourceMappingURL=skill-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-store.d.ts","sourceRoot":"","sources":["../src/skill-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B;AA0BD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAKrD;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhG;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAehH;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CA0B9D;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjE;AAED,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,KAAK,EAAE,GACrB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAQvB;AAED,wBAAsB,WAAW,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,EACnC,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,SAAS,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAiBf"}
@@ -0,0 +1,132 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ function getSpectraDir() {
6
+ return process.env.SPECTRA_HOME || path.join(homedir(), '.spectra');
7
+ }
8
+ function getSkillsDir() {
9
+ return path.join(getSpectraDir(), 'skills');
10
+ }
11
+ function getSkillDir(id) {
12
+ return path.join(getSkillsDir(), id);
13
+ }
14
+ function getMetadataPath(id) {
15
+ return path.join(getSkillDir(id), 'metadata.json');
16
+ }
17
+ function getSkillMdPath(id) {
18
+ return path.join(getSkillDir(id), 'SKILL.md');
19
+ }
20
+ function isValidSkillId(id) {
21
+ return /^[a-z0-9][a-z0-9-]{1,79}$/.test(id);
22
+ }
23
+ export async function ensureSkillsDir() {
24
+ const dir = getSkillsDir();
25
+ if (!existsSync(dir)) {
26
+ await fs.mkdir(dir, { recursive: true });
27
+ }
28
+ }
29
+ export async function saveEvolvingSkill(skill, content) {
30
+ await ensureSkillsDir();
31
+ const dir = getSkillDir(skill.id);
32
+ if (!existsSync(dir)) {
33
+ await fs.mkdir(dir, { recursive: true });
34
+ }
35
+ await fs.writeFile(getMetadataPath(skill.id), JSON.stringify(skill, null, 2), 'utf-8');
36
+ await fs.writeFile(getSkillMdPath(skill.id), content, 'utf-8');
37
+ }
38
+ export async function loadEvolvingSkill(id) {
39
+ if (!isValidSkillId(id))
40
+ return null;
41
+ const metaPath = getMetadataPath(id);
42
+ if (existsSync(metaPath)) {
43
+ try {
44
+ const raw = await fs.readFile(metaPath, 'utf-8');
45
+ const meta = JSON.parse(raw);
46
+ const content = await fs.readFile(getSkillMdPath(id), 'utf-8');
47
+ return { meta, content };
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ export async function loadAllEvolvingSkills() {
56
+ const dir = getSkillsDir();
57
+ if (!existsSync(dir))
58
+ return [];
59
+ const skills = [];
60
+ try {
61
+ const entries = await fs.readdir(dir, { withFileTypes: true });
62
+ for (const entry of entries) {
63
+ if (!entry.isDirectory())
64
+ continue;
65
+ const loaded = await loadEvolvingSkill(entry.name);
66
+ if (loaded) {
67
+ skills.push({
68
+ name: loaded.meta.name,
69
+ description: loaded.meta.description,
70
+ whenToUse: loaded.meta.whenToUse,
71
+ location: getSkillDir(entry.name),
72
+ content: loaded.content,
73
+ files: [],
74
+ tags: loaded.meta.tags,
75
+ });
76
+ }
77
+ }
78
+ }
79
+ catch {
80
+ // Skip unreadable directories
81
+ }
82
+ return skills;
83
+ }
84
+ export async function incrementUseCount(id) {
85
+ const loaded = await loadEvolvingSkill(id);
86
+ if (!loaded)
87
+ return;
88
+ loaded.meta.useCount++;
89
+ loaded.meta.updatedAt = new Date().toISOString();
90
+ await saveEvolvingSkill(loaded.meta, loaded.content);
91
+ }
92
+ export async function findSimilarSkill(name, description, whenToUse, existingSkills) {
93
+ if (existingSkills.length === 0)
94
+ return null;
95
+ const { buildIndex, matchSkills } = await import('./skill.js');
96
+ const index = buildIndex(existingSkills);
97
+ const queryText = [name, description, whenToUse].join(' ');
98
+ const matches = matchSkills(queryText, index, { topK: 1, threshold: 0.3 });
99
+ return matches.length > 0 ? matches[0].skill : null;
100
+ }
101
+ export async function evolveSkill(existingId, updates, content) {
102
+ const loaded = await loadEvolvingSkill(existingId);
103
+ if (!loaded)
104
+ return;
105
+ const updated = {
106
+ ...loaded.meta,
107
+ ...updates,
108
+ version: loaded.meta.version + 1,
109
+ updatedAt: new Date().toISOString(),
110
+ origin: 'evolved',
111
+ };
112
+ await saveEvolvingSkill(updated, content);
113
+ }
114
+ export async function forkSkill(parentId, newId, newName, content) {
115
+ if (!isValidSkillId(newId))
116
+ return;
117
+ const meta = {
118
+ id: newId,
119
+ name: newName,
120
+ description: '',
121
+ whenToUse: '',
122
+ tags: [],
123
+ useCount: 0,
124
+ version: 1,
125
+ parentId,
126
+ createdAt: new Date().toISOString(),
127
+ updatedAt: new Date().toISOString(),
128
+ origin: 'learned',
129
+ };
130
+ await saveEvolvingSkill(meta, content);
131
+ }
132
+ //# sourceMappingURL=skill-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-store.js","sourceRoot":"","sources":["../src/skill-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { Message } from '@mohanscodex/spectra-ai';
2
+ import type { Skill } from './skill.js';
3
+ export interface SessionTrace {
4
+ messages: Message[];
5
+ toolCalls: {
6
+ name: string;
7
+ args: unknown;
8
+ success: boolean;
9
+ }[];
10
+ duration: number;
11
+ }
12
+ export declare function isSessionEligibleForSynthesis(trace: SessionTrace): boolean;
13
+ export declare function generateSkillContent(trace: SessionTrace): {
14
+ id: string;
15
+ name: string;
16
+ description: string;
17
+ whenToUse: string;
18
+ content: string;
19
+ };
20
+ export declare function synthesizeSkill(trace: SessionTrace, existingSkills: Skill[]): Promise<{
21
+ id: string;
22
+ action: 'created' | 'evolved' | 'skipped';
23
+ } | null>;
24
+ //# sourceMappingURL=skill-synth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-synth.d.ts","sourceRoot":"","sources":["../src/skill-synth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAIxC,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC/D,QAAQ,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAE1E;AA6ED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB,CAqCA;AAED,wBAAsB,eAAe,CACpC,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,KAAK,EAAE,GACrB,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,CAAC,CA0B3E"}