@archznn/crewloop-skills 0.4.0 → 0.4.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 (132) hide show
  1. package/package.json +18 -3
  2. package/packages/cli/README.md +55 -0
  3. package/packages/cli/bin/crewloop.js +6 -0
  4. package/packages/cli/dist/agents.d.ts +7 -0
  5. package/packages/cli/dist/agents.d.ts.map +1 -0
  6. package/packages/cli/dist/agents.js +31 -0
  7. package/packages/cli/dist/agents.js.map +1 -0
  8. package/packages/cli/dist/cli.d.ts +14 -0
  9. package/packages/cli/dist/cli.d.ts.map +1 -0
  10. package/packages/cli/dist/cli.js +283 -0
  11. package/packages/cli/dist/cli.js.map +1 -0
  12. package/packages/cli/dist/installer.d.ts +19 -0
  13. package/packages/cli/dist/installer.d.ts.map +1 -0
  14. package/packages/cli/dist/installer.js +89 -0
  15. package/packages/cli/dist/installer.js.map +1 -0
  16. package/packages/cli/dist/mcp.d.ts +20 -0
  17. package/packages/cli/dist/mcp.d.ts.map +1 -0
  18. package/packages/cli/dist/mcp.js +130 -0
  19. package/packages/cli/dist/mcp.js.map +1 -0
  20. package/packages/cli/dist/resolver.d.ts +7 -0
  21. package/packages/cli/dist/resolver.d.ts.map +1 -0
  22. package/packages/cli/dist/resolver.js +57 -0
  23. package/packages/cli/dist/resolver.js.map +1 -0
  24. package/packages/cli/dist/tests/agents.test.d.ts +2 -0
  25. package/packages/cli/dist/tests/agents.test.d.ts.map +1 -0
  26. package/packages/cli/dist/tests/agents.test.js +27 -0
  27. package/packages/cli/dist/tests/agents.test.js.map +1 -0
  28. package/packages/cli/dist/tests/cli.test.d.ts +2 -0
  29. package/packages/cli/dist/tests/cli.test.d.ts.map +1 -0
  30. package/packages/cli/dist/tests/cli.test.js +103 -0
  31. package/packages/cli/dist/tests/cli.test.js.map +1 -0
  32. package/packages/cli/dist/tests/installer.test.d.ts +2 -0
  33. package/packages/cli/dist/tests/installer.test.d.ts.map +1 -0
  34. package/packages/cli/dist/tests/installer.test.js +129 -0
  35. package/packages/cli/dist/tests/installer.test.js.map +1 -0
  36. package/packages/cli/dist/tests/mcp.test.d.ts +2 -0
  37. package/packages/cli/dist/tests/mcp.test.d.ts.map +1 -0
  38. package/packages/cli/dist/tests/mcp.test.js +153 -0
  39. package/packages/cli/dist/tests/mcp.test.js.map +1 -0
  40. package/packages/cli/dist/tests/resolver.test.d.ts +2 -0
  41. package/packages/cli/dist/tests/resolver.test.d.ts.map +1 -0
  42. package/packages/cli/dist/tests/resolver.test.js +41 -0
  43. package/packages/cli/dist/tests/resolver.test.js.map +1 -0
  44. package/servers/dashboard/bin/crewloop-dashboard.js +0 -0
  45. package/servers/dashboard/dist/adapters/codex.d.ts +23 -0
  46. package/servers/dashboard/dist/adapters/codex.d.ts.map +1 -0
  47. package/servers/dashboard/dist/adapters/codex.js +28 -0
  48. package/servers/dashboard/dist/adapters/codex.js.map +1 -0
  49. package/servers/dashboard/dist/adapters/kimi.d.ts +13 -0
  50. package/servers/dashboard/dist/adapters/kimi.d.ts.map +1 -0
  51. package/servers/dashboard/dist/adapters/kimi.js +28 -0
  52. package/servers/dashboard/dist/adapters/kimi.js.map +1 -0
  53. package/servers/dashboard/dist/adapters/opencode.d.ts +9 -0
  54. package/servers/dashboard/dist/adapters/opencode.d.ts.map +1 -0
  55. package/servers/dashboard/dist/adapters/opencode.js +26 -0
  56. package/servers/dashboard/dist/adapters/opencode.js.map +1 -0
  57. package/servers/dashboard/dist/adapters/shim.d.ts +7 -0
  58. package/servers/dashboard/dist/adapters/shim.d.ts.map +1 -0
  59. package/servers/dashboard/dist/adapters/shim.js +107 -0
  60. package/servers/dashboard/dist/adapters/shim.js.map +1 -0
  61. package/servers/dashboard/dist/adapters/shim.test.d.ts +2 -0
  62. package/servers/dashboard/dist/adapters/shim.test.d.ts.map +1 -0
  63. package/servers/dashboard/dist/adapters/shim.test.js +72 -0
  64. package/servers/dashboard/dist/adapters/shim.test.js.map +1 -0
  65. package/servers/dashboard/dist/api/event.d.ts +13 -0
  66. package/servers/dashboard/dist/api/event.d.ts.map +1 -0
  67. package/servers/dashboard/dist/api/event.js +52 -0
  68. package/servers/dashboard/dist/api/event.js.map +1 -0
  69. package/servers/dashboard/dist/api/skills.d.ts +4 -0
  70. package/servers/dashboard/dist/api/skills.d.ts.map +1 -0
  71. package/servers/dashboard/dist/api/skills.js +12 -0
  72. package/servers/dashboard/dist/api/skills.js.map +1 -0
  73. package/servers/dashboard/dist/config.d.ts +11 -0
  74. package/servers/dashboard/dist/config.d.ts.map +1 -0
  75. package/servers/dashboard/dist/config.js +65 -0
  76. package/servers/dashboard/dist/config.js.map +1 -0
  77. package/servers/dashboard/dist/filters/sanitize.d.ts +14 -0
  78. package/servers/dashboard/dist/filters/sanitize.d.ts.map +1 -0
  79. package/servers/dashboard/dist/filters/sanitize.js +64 -0
  80. package/servers/dashboard/dist/filters/sanitize.js.map +1 -0
  81. package/servers/dashboard/dist/filters/sanitize.test.d.ts +2 -0
  82. package/servers/dashboard/dist/filters/sanitize.test.d.ts.map +1 -0
  83. package/servers/dashboard/dist/filters/sanitize.test.js +71 -0
  84. package/servers/dashboard/dist/filters/sanitize.test.js.map +1 -0
  85. package/servers/dashboard/dist/index.d.ts +2 -0
  86. package/servers/dashboard/dist/index.d.ts.map +1 -0
  87. package/servers/dashboard/dist/index.js +22 -0
  88. package/servers/dashboard/dist/index.js.map +1 -0
  89. package/servers/dashboard/dist/presenter.d.ts +7 -0
  90. package/servers/dashboard/dist/presenter.d.ts.map +1 -0
  91. package/servers/dashboard/dist/presenter.js +54 -0
  92. package/servers/dashboard/dist/presenter.js.map +1 -0
  93. package/servers/dashboard/dist/presenter.test.d.ts +2 -0
  94. package/servers/dashboard/dist/presenter.test.d.ts.map +1 -0
  95. package/servers/dashboard/dist/presenter.test.js +66 -0
  96. package/servers/dashboard/dist/presenter.test.js.map +1 -0
  97. package/servers/dashboard/dist/server.d.ts +13 -0
  98. package/servers/dashboard/dist/server.d.ts.map +1 -0
  99. package/servers/dashboard/dist/server.js +162 -0
  100. package/servers/dashboard/dist/server.js.map +1 -0
  101. package/servers/dashboard/dist/server.test.d.ts +2 -0
  102. package/servers/dashboard/dist/server.test.d.ts.map +1 -0
  103. package/servers/dashboard/dist/server.test.js +113 -0
  104. package/servers/dashboard/dist/server.test.js.map +1 -0
  105. package/servers/dashboard/dist/skills/infer.d.ts +8 -0
  106. package/servers/dashboard/dist/skills/infer.d.ts.map +1 -0
  107. package/servers/dashboard/dist/skills/infer.js +48 -0
  108. package/servers/dashboard/dist/skills/infer.js.map +1 -0
  109. package/servers/dashboard/dist/skills/infer.test.d.ts +2 -0
  110. package/servers/dashboard/dist/skills/infer.test.d.ts.map +1 -0
  111. package/servers/dashboard/dist/skills/infer.test.js +82 -0
  112. package/servers/dashboard/dist/skills/infer.test.js.map +1 -0
  113. package/servers/dashboard/dist/skills/mapping.d.ts +5 -0
  114. package/servers/dashboard/dist/skills/mapping.d.ts.map +1 -0
  115. package/servers/dashboard/dist/skills/mapping.js +28 -0
  116. package/servers/dashboard/dist/skills/mapping.js.map +1 -0
  117. package/servers/dashboard/dist/skills/registry.d.ts +11 -0
  118. package/servers/dashboard/dist/skills/registry.d.ts.map +1 -0
  119. package/servers/dashboard/dist/skills/registry.js +59 -0
  120. package/servers/dashboard/dist/skills/registry.js.map +1 -0
  121. package/servers/dashboard/dist/state.d.ts +18 -0
  122. package/servers/dashboard/dist/state.d.ts.map +1 -0
  123. package/servers/dashboard/dist/state.js +91 -0
  124. package/servers/dashboard/dist/state.js.map +1 -0
  125. package/servers/dashboard/dist/state.test.d.ts +2 -0
  126. package/servers/dashboard/dist/state.test.d.ts.map +1 -0
  127. package/servers/dashboard/dist/state.test.js +83 -0
  128. package/servers/dashboard/dist/state.test.js.map +1 -0
  129. package/servers/dashboard/dist/types.d.ts +86 -0
  130. package/servers/dashboard/dist/types.d.ts.map +1 -0
  131. package/servers/dashboard/dist/types.js +3 -0
  132. package/servers/dashboard/dist/types.js.map +1 -0
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createDashboardServer = createDashboardServer;
7
+ const node_http_1 = __importDefault(require("node:http"));
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const ws_1 = require("ws");
11
+ const state_1 = require("./state");
12
+ const registry_1 = require("./skills/registry");
13
+ const infer_1 = require("./skills/infer");
14
+ const event_1 = require("./api/event");
15
+ const skills_1 = require("./api/skills");
16
+ const presenter_1 = require("./presenter");
17
+ function createDashboardServer(config) {
18
+ const state = new state_1.StateStore({
19
+ maxEventsPerSession: config.maxEventsPerSession,
20
+ sessionMaxAgeMs: config.sessionMaxAgeMs,
21
+ });
22
+ const registry = new registry_1.SkillRegistry(config.packageRoot);
23
+ registry.load();
24
+ const inference = new infer_1.SkillInferenceEngine(registry.getSkills());
25
+ const clients = new Set();
26
+ let activeSessionId;
27
+ function broadcast(message) {
28
+ const data = JSON.stringify(message);
29
+ for (const client of clients) {
30
+ if (client.readyState === ws_1.WebSocket.OPEN) {
31
+ client.send(data);
32
+ }
33
+ }
34
+ }
35
+ function sendSnapshot(client) {
36
+ const message = (0, presenter_1.createSnapshotMessage)(state.getAllSessions());
37
+ if (client.readyState === ws_1.WebSocket.OPEN) {
38
+ client.send(JSON.stringify(message));
39
+ }
40
+ }
41
+ const eventHandler = (0, event_1.createEventHandler)({
42
+ state,
43
+ inference,
44
+ broadcast,
45
+ getActiveSessionId: () => activeSessionId,
46
+ setActiveSessionId: (id) => {
47
+ activeSessionId = id;
48
+ },
49
+ });
50
+ const skillsHandler = (0, skills_1.createSkillsHandler)(registry);
51
+ const httpServer = node_http_1.default.createServer((req, res) => {
52
+ res.setHeader('Content-Type', 'application/json');
53
+ if (req.method === 'POST' && req.url === '/event') {
54
+ eventHandler(req, res).catch((err) => {
55
+ console.error('Event handler error:', err);
56
+ res.statusCode = 500;
57
+ res.end(JSON.stringify({ error: 'Internal server error' }));
58
+ });
59
+ return;
60
+ }
61
+ if (req.method === 'GET' && req.url === '/api/skills') {
62
+ skillsHandler(req, res).catch((err) => {
63
+ console.error('Skills handler error:', err);
64
+ res.statusCode = 500;
65
+ res.end(JSON.stringify({ error: 'Internal server error' }));
66
+ });
67
+ return;
68
+ }
69
+ if (req.method === 'GET' && req.url === '/') {
70
+ serveStaticFile(res, 'index.html', 'text/html');
71
+ return;
72
+ }
73
+ if (req.method === 'GET') {
74
+ const filePath = req.url?.slice(1) || '';
75
+ const ext = node_path_1.default.extname(filePath);
76
+ const contentType = CONTENT_TYPES[ext] || 'application/octet-stream';
77
+ serveStaticFile(res, filePath, contentType);
78
+ return;
79
+ }
80
+ res.statusCode = 404;
81
+ res.end(JSON.stringify({ error: 'Not found' }));
82
+ });
83
+ const wss = new ws_1.WebSocketServer({ server: httpServer });
84
+ wss.on('connection', (client) => {
85
+ clients.add(client);
86
+ sendSnapshot(client);
87
+ client.on('message', (raw) => {
88
+ try {
89
+ const message = JSON.parse(raw.toString());
90
+ if (message.type === 'ping') {
91
+ client.send(JSON.stringify({ type: 'pong' }));
92
+ }
93
+ }
94
+ catch {
95
+ // Ignore malformed client messages.
96
+ }
97
+ });
98
+ client.on('close', () => {
99
+ clients.delete(client);
100
+ });
101
+ });
102
+ const pruneInterval = setInterval(() => {
103
+ state.pruneInactive();
104
+ }, config.pruneIntervalMs);
105
+ function serveStaticFile(res, filePath, contentType) {
106
+ const publicDir = node_path_1.default.resolve(__dirname, '..', 'public');
107
+ const fullPath = node_path_1.default.resolve(publicDir, filePath);
108
+ if (!fullPath.startsWith(publicDir + node_path_1.default.sep)) {
109
+ res.statusCode = 403;
110
+ res.end(JSON.stringify({ error: 'Forbidden' }));
111
+ return;
112
+ }
113
+ if (!node_fs_1.default.existsSync(fullPath)) {
114
+ res.statusCode = 404;
115
+ res.end(JSON.stringify({ error: 'Not found' }));
116
+ return;
117
+ }
118
+ node_fs_1.default.readFile(fullPath, (err, data) => {
119
+ if (err) {
120
+ res.statusCode = 500;
121
+ res.end(JSON.stringify({ error: 'Failed to read file' }));
122
+ return;
123
+ }
124
+ res.setHeader('Content-Type', contentType);
125
+ res.statusCode = 200;
126
+ res.end(data);
127
+ });
128
+ }
129
+ return {
130
+ httpServer,
131
+ wss,
132
+ state,
133
+ start: () => new Promise((resolve, reject) => {
134
+ httpServer.listen(config.port, config.host, () => {
135
+ console.log(`CrewLoop dashboard running at http://${config.host}:${config.port}`);
136
+ resolve();
137
+ });
138
+ httpServer.on('error', reject);
139
+ }),
140
+ stop: () => new Promise((resolve) => {
141
+ clearInterval(pruneInterval);
142
+ for (const client of clients) {
143
+ client.terminate();
144
+ }
145
+ wss.close(() => {
146
+ httpServer.close(() => {
147
+ resolve();
148
+ });
149
+ });
150
+ }),
151
+ };
152
+ }
153
+ const CONTENT_TYPES = {
154
+ '.html': 'text/html',
155
+ '.css': 'text/css',
156
+ '.js': 'application/javascript',
157
+ '.json': 'application/json',
158
+ '.svg': 'image/svg+xml',
159
+ '.png': 'image/png',
160
+ '.ico': 'image/x-icon',
161
+ };
162
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../src/server.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const node_http_1 = __importDefault(require("node:http"));
9
+ const ws_1 = __importDefault(require("ws"));
10
+ const server_1 = require("./server");
11
+ function httpGetStatus(port, path) {
12
+ return new Promise((resolve, reject) => {
13
+ const req = node_http_1.default.get({ hostname: '127.0.0.1', port, path }, (res) => {
14
+ resolve(res.statusCode || 0);
15
+ });
16
+ req.on('error', reject);
17
+ req.end();
18
+ });
19
+ }
20
+ function getFreePort() {
21
+ return new Promise((resolve) => {
22
+ const server = node_http_1.default.createServer();
23
+ server.listen(0, '127.0.0.1', () => {
24
+ const address = server.address();
25
+ const port = typeof address === 'object' && address ? address.port : 0;
26
+ server.close(() => resolve(port));
27
+ });
28
+ });
29
+ }
30
+ function makeConfig(port, packageRoot) {
31
+ return {
32
+ port,
33
+ host: '127.0.0.1',
34
+ packageRoot,
35
+ maxEventsPerSession: 100,
36
+ sessionMaxAgeMs: 60000,
37
+ pruneIntervalMs: 60000,
38
+ };
39
+ }
40
+ (0, node_test_1.describe)('DashboardServer', () => {
41
+ let server;
42
+ let port;
43
+ (0, node_test_1.before)(async () => {
44
+ port = await getFreePort();
45
+ server = (0, server_1.createDashboardServer)(makeConfig(port, process.cwd()));
46
+ await server.start();
47
+ });
48
+ (0, node_test_1.after)(async () => {
49
+ await server.stop();
50
+ });
51
+ (0, node_test_1.it)('serves index.html', async () => {
52
+ const res = await fetch(`http://127.0.0.1:${port}/`);
53
+ strict_1.default.equal(res.status, 200);
54
+ const text = await res.text();
55
+ strict_1.default.ok(text.includes('<html'));
56
+ });
57
+ (0, node_test_1.it)('accepts POST /event and broadcasts via WebSocket', async () => {
58
+ const ws = new ws_1.default(`ws://127.0.0.1:${port}`);
59
+ const snapshot = await new Promise((resolve, reject) => {
60
+ const timer = setTimeout(() => reject(new Error('WebSocket timeout')), 2000);
61
+ ws.once('message', (data) => {
62
+ clearTimeout(timer);
63
+ resolve(JSON.parse(data.toString()));
64
+ });
65
+ });
66
+ strict_1.default.equal(snapshot.type, 'snapshot');
67
+ const updatePromise = new Promise((resolve) => {
68
+ ws.on('message', (data) => {
69
+ const message = JSON.parse(data.toString());
70
+ if (message.type === 'update') {
71
+ resolve(message);
72
+ }
73
+ });
74
+ });
75
+ const res = await fetch(`http://127.0.0.1:${port}/event`, {
76
+ method: 'POST',
77
+ headers: { 'Content-Type': 'application/json' },
78
+ body: JSON.stringify({
79
+ id: 'ev-1',
80
+ timestamp: Date.now(),
81
+ source: 'kimi',
82
+ session_id: 'sess-1',
83
+ event_type: 'tool_start',
84
+ tool: 'Read',
85
+ }),
86
+ });
87
+ strict_1.default.equal(res.status, 200);
88
+ const update = await updatePromise;
89
+ strict_1.default.equal(update.session.id, 'sess-1');
90
+ strict_1.default.equal(update.isActive, true);
91
+ ws.close();
92
+ });
93
+ (0, node_test_1.it)('rejects events with dangerous fields', async () => {
94
+ const res = await fetch(`http://127.0.0.1:${port}/event`, {
95
+ method: 'POST',
96
+ headers: { 'Content-Type': 'application/json' },
97
+ body: JSON.stringify({
98
+ id: 'ev-bad',
99
+ timestamp: Date.now(),
100
+ source: 'kimi',
101
+ session_id: 'sess-bad',
102
+ event_type: 'tool_start',
103
+ command: 'rm -rf /',
104
+ }),
105
+ });
106
+ strict_1.default.equal(res.status, 400);
107
+ });
108
+ (0, node_test_1.it)('blocks static file path traversal', async () => {
109
+ const status = await httpGetStatus(port, '/../../package.json');
110
+ strict_1.default.equal(status, 403);
111
+ });
112
+ });
113
+ //# sourceMappingURL=server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.test.js","sourceRoot":"","sources":["../src/server.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { DashboardEvent, Session, SkillInferenceResult, SkillMeta } from '../types';
2
+ export declare class SkillInferenceEngine {
3
+ private skillNames;
4
+ constructor(skills: SkillMeta[]);
5
+ infer(event: DashboardEvent, session: Session): SkillInferenceResult;
6
+ private normalizeSkillName;
7
+ }
8
+ //# sourceMappingURL=infer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.d.ts","sourceRoot":"","sources":["../../src/skills/infer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGzF,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,UAAU,CAAc;gBAEpB,MAAM,EAAE,SAAS,EAAE;IAI/B,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,oBAAoB;IAiCpE,OAAO,CAAC,kBAAkB;CAS3B"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SkillInferenceEngine = void 0;
4
+ const mapping_1 = require("./mapping");
5
+ class SkillInferenceEngine {
6
+ skillNames;
7
+ constructor(skills) {
8
+ this.skillNames = new Set(skills.map((skill) => skill.name));
9
+ }
10
+ infer(event, session) {
11
+ if (event.event_type === 'skill_change' && event.skill) {
12
+ return { skill: event.skill, confidence: 'explicit' };
13
+ }
14
+ if (event.tool === 'Skill' && event.detail) {
15
+ const skill = this.normalizeSkillName(event.detail);
16
+ if (skill) {
17
+ return { skill, confidence: 'explicit' };
18
+ }
19
+ }
20
+ if (event.tool === 'Bash' && event.detail) {
21
+ const gitSkill = (0, mapping_1.inferFromGitCommand)(event.detail);
22
+ if (gitSkill) {
23
+ return { skill: gitSkill, confidence: 'heuristic' };
24
+ }
25
+ }
26
+ if (event.tool) {
27
+ const mapped = (0, mapping_1.inferFromTool)(event.tool);
28
+ if (mapped && this.skillNames.has(mapped)) {
29
+ return { skill: mapped, confidence: 'heuristic' };
30
+ }
31
+ }
32
+ if (session.active_skill && this.skillNames.has(session.active_skill)) {
33
+ return { skill: session.active_skill, confidence: 'heuristic' };
34
+ }
35
+ return { skill: undefined, confidence: 'unknown' };
36
+ }
37
+ normalizeSkillName(raw) {
38
+ const normalized = raw.toLowerCase().trim();
39
+ for (const name of this.skillNames) {
40
+ if (name.toLowerCase() === normalized) {
41
+ return name;
42
+ }
43
+ }
44
+ return undefined;
45
+ }
46
+ }
47
+ exports.SkillInferenceEngine = SkillInferenceEngine;
48
+ //# sourceMappingURL=infer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.js","sourceRoot":"","sources":["../../src/skills/infer.ts"],"names":[],"mappings":";;;AACA,uCAA+D;AAE/D,MAAa,oBAAoB;IACvB,UAAU,CAAc;IAEhC,YAAY,MAAmB;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,KAAqB,EAAE,OAAgB;QAC3C,IAAI,KAAK,CAAC,UAAU,KAAK,cAAc,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACvD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;QACxD,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,IAAA,6BAAmB,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;YACtD,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,IAAA,uBAAa,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;YACpD,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACtE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;QAClE,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IACrD,CAAC;IAEO,kBAAkB,CAAC,GAAW;QACpC,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,UAAU,EAAE,CAAC;gBACtC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAjDD,oDAiDC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=infer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.test.d.ts","sourceRoot":"","sources":["../../src/skills/infer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const infer_1 = require("./infer");
9
+ function makeSession(overrides = {}) {
10
+ return {
11
+ id: 'sess-1',
12
+ source: 'kimi',
13
+ events: [],
14
+ tool_counts: {},
15
+ started_at: Date.now(),
16
+ last_event_at: Date.now(),
17
+ ...overrides,
18
+ };
19
+ }
20
+ function makeEvent(overrides = {}) {
21
+ return {
22
+ id: 'ev-1',
23
+ timestamp: Date.now(),
24
+ source: 'kimi',
25
+ session_id: 'sess-1',
26
+ event_type: 'tool_start',
27
+ ...overrides,
28
+ };
29
+ }
30
+ const skills = [
31
+ { name: 'orchestrator', description: '', icon: 'target' },
32
+ { name: 'architect', description: '', icon: 'blueprint' },
33
+ { name: 'engineer', description: '', icon: 'wrench' },
34
+ { name: 'shipper', description: '', icon: 'rocket-launch' },
35
+ { name: 'researcher', description: '', icon: 'microscope' },
36
+ ];
37
+ (0, node_test_1.describe)('SkillInferenceEngine', () => {
38
+ (0, node_test_1.it)('infers explicit skill from skill_change event', () => {
39
+ const engine = new infer_1.SkillInferenceEngine(skills);
40
+ const event = makeEvent({ event_type: 'skill_change', skill: 'architect' });
41
+ const result = engine.infer(event, makeSession());
42
+ strict_1.default.equal(result.skill, 'architect');
43
+ strict_1.default.equal(result.confidence, 'explicit');
44
+ });
45
+ (0, node_test_1.it)('infers explicit skill from Skill tool detail', () => {
46
+ const engine = new infer_1.SkillInferenceEngine(skills);
47
+ const event = makeEvent({ tool: 'Skill', detail: 'engineer' });
48
+ const result = engine.infer(event, makeSession());
49
+ strict_1.default.equal(result.skill, 'engineer');
50
+ strict_1.default.equal(result.confidence, 'explicit');
51
+ });
52
+ (0, node_test_1.it)('infers researcher from Read tool', () => {
53
+ const engine = new infer_1.SkillInferenceEngine(skills);
54
+ const event = makeEvent({ tool: 'Read', detail: 'README.md' });
55
+ const result = engine.infer(event, makeSession());
56
+ strict_1.default.equal(result.skill, 'researcher');
57
+ strict_1.default.equal(result.confidence, 'heuristic');
58
+ });
59
+ (0, node_test_1.it)('infers shipper from git commit command', () => {
60
+ const engine = new infer_1.SkillInferenceEngine(skills);
61
+ const event = makeEvent({ tool: 'Bash', detail: 'git commit -m "feat: x"' });
62
+ const result = engine.infer(event, makeSession());
63
+ strict_1.default.equal(result.skill, 'shipper');
64
+ strict_1.default.equal(result.confidence, 'heuristic');
65
+ });
66
+ (0, node_test_1.it)('falls back to session active skill', () => {
67
+ const engine = new infer_1.SkillInferenceEngine(skills);
68
+ const session = makeSession({ active_skill: 'architect' });
69
+ const event = makeEvent({ tool: 'UnknownTool' });
70
+ const result = engine.infer(event, session);
71
+ strict_1.default.equal(result.skill, 'architect');
72
+ strict_1.default.equal(result.confidence, 'heuristic');
73
+ });
74
+ (0, node_test_1.it)('returns unknown when nothing matches', () => {
75
+ const engine = new infer_1.SkillInferenceEngine(skills);
76
+ const event = makeEvent({ tool: 'UnknownTool' });
77
+ const result = engine.infer(event, makeSession());
78
+ strict_1.default.equal(result.skill, undefined);
79
+ strict_1.default.equal(result.confidence, 'unknown');
80
+ });
81
+ });
82
+ //# sourceMappingURL=infer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.test.js","sourceRoot":"","sources":["../../src/skills/infer.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,gEAAwC;AACxC,mCAA+C;AAG/C,SAAS,WAAW,CAAC,YAA8B,EAAE;IACnD,OAAO;QACL,EAAE,EAAE,QAAQ;QACZ,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,EAAE;QACV,WAAW,EAAE,EAAE;QACf,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;QACtB,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE;QACzB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,YAAqC,EAAE;IACxD,OAAO;QACL,EAAE,EAAE,MAAM;QACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,QAAQ;QACpB,UAAU,EAAE,YAAY;QACxB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG;IACb,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACzD,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;IACzD,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACrD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;IAC3D,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;CAC5D,CAAC;AAEF,IAAA,oBAAQ,EAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAA,cAAE,EAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,MAAM,GAAG,IAAI,4BAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAClD,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACxC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,MAAM,GAAG,IAAI,4BAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAClD,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACvC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,MAAM,GAAG,IAAI,4BAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAClD,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QACzC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,IAAI,4BAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAClD,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACtC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,IAAI,4BAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,WAAW,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5C,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACxC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,IAAI,4BAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAClD,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACtC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ToolToSkillMap } from '../types';
2
+ export declare const DEFAULT_TOOL_TO_SKILL_MAP: ToolToSkillMap;
3
+ export declare function inferFromTool(toolName: string): string | undefined;
4
+ export declare function inferFromGitCommand(command: string): string | undefined;
5
+ //# sourceMappingURL=mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/skills/mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,eAAO,MAAM,yBAAyB,EAAE,cAYvC,CAAC;AAEF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAElE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKvE"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_TOOL_TO_SKILL_MAP = void 0;
4
+ exports.inferFromTool = inferFromTool;
5
+ exports.inferFromGitCommand = inferFromGitCommand;
6
+ exports.DEFAULT_TOOL_TO_SKILL_MAP = {
7
+ Task: 'orchestrator',
8
+ Agent: 'orchestrator',
9
+ Read: 'researcher',
10
+ Grep: 'researcher',
11
+ Glob: 'researcher',
12
+ WebSearch: 'researcher',
13
+ FetchURL: 'researcher',
14
+ Edit: 'engineer',
15
+ Write: 'engineer',
16
+ Bash: 'engineer',
17
+ Skill: undefined,
18
+ };
19
+ function inferFromTool(toolName) {
20
+ return exports.DEFAULT_TOOL_TO_SKILL_MAP[toolName];
21
+ }
22
+ function inferFromGitCommand(command) {
23
+ if (/\b(git\s+(commit|push|branch|merge|tag|checkout))\b/.test(command)) {
24
+ return 'shipper';
25
+ }
26
+ return undefined;
27
+ }
28
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/skills/mapping.ts"],"names":[],"mappings":";;;AAgBA,sCAEC;AAED,kDAKC;AAvBY,QAAA,yBAAyB,GAAmB;IACvD,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,cAAc;IACrB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,YAAY;IACtB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,SAAS;CACjB,CAAC;AAEF,SAAgB,aAAa,CAAC,QAAgB;IAC5C,OAAO,iCAAyB,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAe;IACjD,IAAI,qDAAqD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { SkillMeta } from '../types';
2
+ export declare class SkillRegistry {
3
+ private skills;
4
+ private packageRoot;
5
+ constructor(packageRoot: string);
6
+ load(): SkillMeta[];
7
+ getSkills(): SkillMeta[];
8
+ getIcon(skillName: string): string;
9
+ hasSkill(skillName: string): boolean;
10
+ }
11
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/skills/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAmB1C,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAI/B,IAAI,IAAI,SAAS,EAAE;IAgBnB,SAAS,IAAI,SAAS,EAAE;IAOxB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAIlC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;CAGrC"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SkillRegistry = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const SKILL_ICONS = {
10
+ orchestrator: 'target',
11
+ architect: 'blueprint',
12
+ designer: 'palette',
13
+ engineer: 'wrench',
14
+ reviewer: 'magnifying-glass',
15
+ shipper: 'rocket-launch',
16
+ 'docs-writer': 'article',
17
+ tester: 'flask',
18
+ 'product-manager': 'chart-bar',
19
+ maintainer: 'toolbox',
20
+ researcher: 'microscope',
21
+ 'security-guard': 'shield',
22
+ 'accessibility-auditor': 'person',
23
+ 'obsidian-second-brain': 'brain',
24
+ };
25
+ class SkillRegistry {
26
+ skills = [];
27
+ packageRoot;
28
+ constructor(packageRoot) {
29
+ this.packageRoot = packageRoot;
30
+ }
31
+ load() {
32
+ const skillsDir = node_path_1.default.join(this.packageRoot, 'skills');
33
+ if (node_fs_1.default.existsSync(skillsDir)) {
34
+ this.skills = node_fs_1.default
35
+ .readdirSync(skillsDir, { withFileTypes: true })
36
+ .filter((entry) => entry.isDirectory())
37
+ .map((entry) => ({
38
+ name: entry.name,
39
+ description: '',
40
+ icon: SKILL_ICONS[entry.name] || 'circle',
41
+ }));
42
+ }
43
+ return this.skills;
44
+ }
45
+ getSkills() {
46
+ if (this.skills.length === 0) {
47
+ this.load();
48
+ }
49
+ return this.skills;
50
+ }
51
+ getIcon(skillName) {
52
+ return SKILL_ICONS[skillName] || 'circle';
53
+ }
54
+ hasSkill(skillName) {
55
+ return this.getSkills().some((skill) => skill.name === skillName);
56
+ }
57
+ }
58
+ exports.SkillRegistry = SkillRegistry;
59
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/skills/registry.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAyB;AACzB,0DAA6B;AAG7B,MAAM,WAAW,GAA2B;IAC1C,YAAY,EAAE,QAAQ;IACtB,SAAS,EAAE,WAAW;IACtB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,kBAAkB;IAC5B,OAAO,EAAE,eAAe;IACxB,aAAa,EAAE,SAAS;IACxB,MAAM,EAAE,OAAO;IACf,iBAAiB,EAAE,WAAW;IAC9B,UAAU,EAAE,SAAS;IACrB,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,QAAQ;IAC1B,uBAAuB,EAAE,QAAQ;IACjC,uBAAuB,EAAE,OAAO;CACjC,CAAC;AAEF,MAAa,aAAa;IAChB,MAAM,GAAgB,EAAE,CAAC;IACzB,WAAW,CAAS;IAE5B,YAAY,WAAmB;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,IAAI;QACF,MAAM,SAAS,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACxD,IAAI,iBAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,GAAG,iBAAE;iBACb,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAC/C,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;iBACtC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACf,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,EAAE;gBACf,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ;aAC1C,CAAC,CAAC,CAAC;QACR,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,SAAS;QACP,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,OAAO,CAAC,SAAiB;QACvB,OAAO,WAAW,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC;IAC5C,CAAC;IAED,QAAQ,CAAC,SAAiB;QACxB,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IACpE,CAAC;CACF;AAtCD,sCAsCC"}
@@ -0,0 +1,18 @@
1
+ import type { DashboardEvent, Session, DashboardState } from './types';
2
+ export interface StateStoreOptions {
3
+ maxEventsPerSession: number;
4
+ sessionMaxAgeMs: number;
5
+ }
6
+ export declare class StateStore {
7
+ private sessions;
8
+ private options;
9
+ constructor(options: StateStoreOptions);
10
+ applyEvent(event: DashboardEvent): Session;
11
+ setActiveSkill(sessionId: string, skill: string | undefined, confidence: 'explicit' | 'heuristic' | 'unknown'): Session | undefined;
12
+ getSession(id: string): Session | undefined;
13
+ getAllSessions(): Session[];
14
+ getState(): DashboardState;
15
+ pruneInactive(now?: number): number;
16
+ private createSession;
17
+ }
18
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAA4B,MAAM,SAAS,CAAC;AAEjG,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,EAAE,iBAAiB;IAItC,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO;IA8B1C,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,UAAU,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,GAC/C,OAAO,GAAG,SAAS;IAUtB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI3C,cAAc,IAAI,OAAO,EAAE;IAM3B,QAAQ,IAAI,cAAc;IAM1B,aAAa,CAAC,GAAG,GAAE,MAAmB,GAAG,MAAM;IAW/C,OAAO,CAAC,aAAa;CAatB"}