@archznn/crewloop-skills 0.3.0 → 0.4.1
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.
- package/package.json +16 -3
- package/packages/cli/README.md +55 -0
- package/packages/cli/bin/crewloop.js +6 -0
- package/packages/cli/dist/agents.d.ts +7 -0
- package/packages/cli/dist/agents.d.ts.map +1 -0
- package/packages/cli/dist/agents.js +31 -0
- package/packages/cli/dist/agents.js.map +1 -0
- package/packages/cli/dist/cli.d.ts +14 -0
- package/packages/cli/dist/cli.d.ts.map +1 -0
- package/packages/cli/dist/cli.js +255 -0
- package/packages/cli/dist/cli.js.map +1 -0
- package/packages/cli/dist/installer.d.ts +19 -0
- package/packages/cli/dist/installer.d.ts.map +1 -0
- package/packages/cli/dist/installer.js +89 -0
- package/packages/cli/dist/installer.js.map +1 -0
- package/packages/cli/dist/mcp.d.ts +20 -0
- package/packages/cli/dist/mcp.d.ts.map +1 -0
- package/packages/cli/dist/mcp.js +130 -0
- package/packages/cli/dist/mcp.js.map +1 -0
- package/packages/cli/dist/resolver.d.ts +7 -0
- package/packages/cli/dist/resolver.d.ts.map +1 -0
- package/packages/cli/dist/resolver.js +57 -0
- package/packages/cli/dist/resolver.js.map +1 -0
- package/packages/cli/dist/tests/agents.test.d.ts +2 -0
- package/packages/cli/dist/tests/agents.test.d.ts.map +1 -0
- package/packages/cli/dist/tests/agents.test.js +27 -0
- package/packages/cli/dist/tests/agents.test.js.map +1 -0
- package/packages/cli/dist/tests/cli.test.d.ts +2 -0
- package/packages/cli/dist/tests/cli.test.d.ts.map +1 -0
- package/packages/cli/dist/tests/cli.test.js +103 -0
- package/packages/cli/dist/tests/cli.test.js.map +1 -0
- package/packages/cli/dist/tests/installer.test.d.ts +2 -0
- package/packages/cli/dist/tests/installer.test.d.ts.map +1 -0
- package/packages/cli/dist/tests/installer.test.js +129 -0
- package/packages/cli/dist/tests/installer.test.js.map +1 -0
- package/packages/cli/dist/tests/mcp.test.d.ts +2 -0
- package/packages/cli/dist/tests/mcp.test.d.ts.map +1 -0
- package/packages/cli/dist/tests/mcp.test.js +153 -0
- package/packages/cli/dist/tests/mcp.test.js.map +1 -0
- package/packages/cli/dist/tests/resolver.test.d.ts +2 -0
- package/packages/cli/dist/tests/resolver.test.d.ts.map +1 -0
- package/packages/cli/dist/tests/resolver.test.js +41 -0
- package/packages/cli/dist/tests/resolver.test.js.map +1 -0
- package/servers/dashboard/README.md +87 -0
- package/servers/dashboard/bin/crewloop-dashboard.js +5 -0
- package/servers/dashboard/config-examples/codex-hooks.json +14 -0
- package/servers/dashboard/config-examples/kimi-code-config.toml +6 -0
- package/servers/dashboard/config-examples/opencode-plugin/crewloop-dashboard.js +64 -0
- package/servers/dashboard/dist/adapters/codex.d.ts +23 -0
- package/servers/dashboard/dist/adapters/codex.d.ts.map +1 -0
- package/servers/dashboard/dist/adapters/codex.js +28 -0
- package/servers/dashboard/dist/adapters/codex.js.map +1 -0
- package/servers/dashboard/dist/adapters/kimi.d.ts +13 -0
- package/servers/dashboard/dist/adapters/kimi.d.ts.map +1 -0
- package/servers/dashboard/dist/adapters/kimi.js +28 -0
- package/servers/dashboard/dist/adapters/kimi.js.map +1 -0
- package/servers/dashboard/dist/adapters/opencode.d.ts +9 -0
- package/servers/dashboard/dist/adapters/opencode.d.ts.map +1 -0
- package/servers/dashboard/dist/adapters/opencode.js +26 -0
- package/servers/dashboard/dist/adapters/opencode.js.map +1 -0
- package/servers/dashboard/dist/adapters/shim.d.ts +7 -0
- package/servers/dashboard/dist/adapters/shim.d.ts.map +1 -0
- package/servers/dashboard/dist/adapters/shim.js +107 -0
- package/servers/dashboard/dist/adapters/shim.js.map +1 -0
- package/servers/dashboard/dist/adapters/shim.test.d.ts +2 -0
- package/servers/dashboard/dist/adapters/shim.test.d.ts.map +1 -0
- package/servers/dashboard/dist/adapters/shim.test.js +72 -0
- package/servers/dashboard/dist/adapters/shim.test.js.map +1 -0
- package/servers/dashboard/dist/api/event.d.ts +13 -0
- package/servers/dashboard/dist/api/event.d.ts.map +1 -0
- package/servers/dashboard/dist/api/event.js +52 -0
- package/servers/dashboard/dist/api/event.js.map +1 -0
- package/servers/dashboard/dist/api/skills.d.ts +4 -0
- package/servers/dashboard/dist/api/skills.d.ts.map +1 -0
- package/servers/dashboard/dist/api/skills.js +12 -0
- package/servers/dashboard/dist/api/skills.js.map +1 -0
- package/servers/dashboard/dist/config.d.ts +11 -0
- package/servers/dashboard/dist/config.d.ts.map +1 -0
- package/servers/dashboard/dist/config.js +65 -0
- package/servers/dashboard/dist/config.js.map +1 -0
- package/servers/dashboard/dist/filters/sanitize.d.ts +14 -0
- package/servers/dashboard/dist/filters/sanitize.d.ts.map +1 -0
- package/servers/dashboard/dist/filters/sanitize.js +64 -0
- package/servers/dashboard/dist/filters/sanitize.js.map +1 -0
- package/servers/dashboard/dist/filters/sanitize.test.d.ts +2 -0
- package/servers/dashboard/dist/filters/sanitize.test.d.ts.map +1 -0
- package/servers/dashboard/dist/filters/sanitize.test.js +71 -0
- package/servers/dashboard/dist/filters/sanitize.test.js.map +1 -0
- package/servers/dashboard/dist/index.d.ts +2 -0
- package/servers/dashboard/dist/index.d.ts.map +1 -0
- package/servers/dashboard/dist/index.js +22 -0
- package/servers/dashboard/dist/index.js.map +1 -0
- package/servers/dashboard/dist/presenter.d.ts +7 -0
- package/servers/dashboard/dist/presenter.d.ts.map +1 -0
- package/servers/dashboard/dist/presenter.js +54 -0
- package/servers/dashboard/dist/presenter.js.map +1 -0
- package/servers/dashboard/dist/presenter.test.d.ts +2 -0
- package/servers/dashboard/dist/presenter.test.d.ts.map +1 -0
- package/servers/dashboard/dist/presenter.test.js +66 -0
- package/servers/dashboard/dist/presenter.test.js.map +1 -0
- package/servers/dashboard/dist/server.d.ts +13 -0
- package/servers/dashboard/dist/server.d.ts.map +1 -0
- package/servers/dashboard/dist/server.js +162 -0
- package/servers/dashboard/dist/server.js.map +1 -0
- package/servers/dashboard/dist/server.test.d.ts +2 -0
- package/servers/dashboard/dist/server.test.d.ts.map +1 -0
- package/servers/dashboard/dist/server.test.js +113 -0
- package/servers/dashboard/dist/server.test.js.map +1 -0
- package/servers/dashboard/dist/skills/infer.d.ts +8 -0
- package/servers/dashboard/dist/skills/infer.d.ts.map +1 -0
- package/servers/dashboard/dist/skills/infer.js +48 -0
- package/servers/dashboard/dist/skills/infer.js.map +1 -0
- package/servers/dashboard/dist/skills/infer.test.d.ts +2 -0
- package/servers/dashboard/dist/skills/infer.test.d.ts.map +1 -0
- package/servers/dashboard/dist/skills/infer.test.js +82 -0
- package/servers/dashboard/dist/skills/infer.test.js.map +1 -0
- package/servers/dashboard/dist/skills/mapping.d.ts +5 -0
- package/servers/dashboard/dist/skills/mapping.d.ts.map +1 -0
- package/servers/dashboard/dist/skills/mapping.js +28 -0
- package/servers/dashboard/dist/skills/mapping.js.map +1 -0
- package/servers/dashboard/dist/skills/registry.d.ts +11 -0
- package/servers/dashboard/dist/skills/registry.d.ts.map +1 -0
- package/servers/dashboard/dist/skills/registry.js +59 -0
- package/servers/dashboard/dist/skills/registry.js.map +1 -0
- package/servers/dashboard/dist/state.d.ts +18 -0
- package/servers/dashboard/dist/state.d.ts.map +1 -0
- package/servers/dashboard/dist/state.js +91 -0
- package/servers/dashboard/dist/state.js.map +1 -0
- package/servers/dashboard/dist/state.test.d.ts +2 -0
- package/servers/dashboard/dist/state.test.d.ts.map +1 -0
- package/servers/dashboard/dist/state.test.js +83 -0
- package/servers/dashboard/dist/state.test.js.map +1 -0
- package/servers/dashboard/dist/types.d.ts +86 -0
- package/servers/dashboard/dist/types.d.ts.map +1 -0
- package/servers/dashboard/dist/types.js +3 -0
- package/servers/dashboard/dist/types.js.map +1 -0
- package/servers/dashboard/package.json +46 -0
- package/servers/dashboard/public/app.js +447 -0
- package/servers/dashboard/public/index.html +96 -0
- package/servers/dashboard/public/styles.css +664 -0
- package/servers/dashboard/src/adapters/codex.ts +50 -0
- package/servers/dashboard/src/adapters/kimi.ts +40 -0
- package/servers/dashboard/src/adapters/opencode.ts +36 -0
- package/servers/dashboard/src/adapters/shim.test.ts +74 -0
- package/servers/dashboard/src/adapters/shim.ts +120 -0
- package/servers/dashboard/src/api/event.ts +70 -0
- package/servers/dashboard/src/api/skills.ts +11 -0
- package/servers/dashboard/src/config.ts +66 -0
- package/servers/dashboard/src/filters/sanitize.test.ts +94 -0
- package/servers/dashboard/src/filters/sanitize.ts +78 -0
- package/servers/dashboard/src/index.ts +24 -0
- package/servers/dashboard/src/presenter.test.ts +69 -0
- package/servers/dashboard/src/presenter.ts +56 -0
- package/servers/dashboard/src/server.test.ts +123 -0
- package/servers/dashboard/src/server.ts +191 -0
- package/servers/dashboard/src/skills/infer.test.ts +86 -0
- package/servers/dashboard/src/skills/infer.ts +53 -0
- package/servers/dashboard/src/skills/mapping.ts +26 -0
- package/servers/dashboard/src/skills/registry.ts +60 -0
- package/servers/dashboard/src/state.test.ts +88 -0
- package/servers/dashboard/src/state.ts +115 -0
- package/servers/dashboard/src/types.ts +110 -0
- package/servers/dashboard/tsconfig.json +19 -0
- package/skills/orchestrator/SKILL.md +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.presentEvent = presentEvent;
|
|
4
|
+
exports.presentSession = presentSession;
|
|
5
|
+
exports.presentState = presentState;
|
|
6
|
+
exports.createSnapshotMessage = createSnapshotMessage;
|
|
7
|
+
exports.createUpdateMessage = createUpdateMessage;
|
|
8
|
+
function presentEvent(event) {
|
|
9
|
+
return {
|
|
10
|
+
id: event.id,
|
|
11
|
+
timestamp: event.timestamp,
|
|
12
|
+
event_type: event.event_type,
|
|
13
|
+
tool: event.tool,
|
|
14
|
+
detail: event.detail,
|
|
15
|
+
status: event.status,
|
|
16
|
+
duration_ms: event.duration_ms,
|
|
17
|
+
skill: event.skill,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function presentSession(session) {
|
|
21
|
+
return {
|
|
22
|
+
id: session.id,
|
|
23
|
+
source: session.source,
|
|
24
|
+
skill: session.active_skill,
|
|
25
|
+
activeSkill: session.active_skill
|
|
26
|
+
? {
|
|
27
|
+
name: session.active_skill,
|
|
28
|
+
confidence: session.active_confidence || 'unknown',
|
|
29
|
+
}
|
|
30
|
+
: undefined,
|
|
31
|
+
status: session.status,
|
|
32
|
+
events: session.events.map(presentEvent),
|
|
33
|
+
startTime: session.started_at,
|
|
34
|
+
lastActivity: session.last_event_at,
|
|
35
|
+
toolCounts: session.tool_counts,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function presentState(state) {
|
|
39
|
+
return Object.values(state.sessions).map(presentSession);
|
|
40
|
+
}
|
|
41
|
+
function createSnapshotMessage(sessions) {
|
|
42
|
+
return {
|
|
43
|
+
type: 'snapshot',
|
|
44
|
+
sessions: sessions.map(presentSession),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function createUpdateMessage(session, activeSessionId) {
|
|
48
|
+
return {
|
|
49
|
+
type: 'update',
|
|
50
|
+
session: presentSession(session),
|
|
51
|
+
isActive: activeSessionId === session.id,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=presenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presenter.js","sourceRoot":"","sources":["../src/presenter.ts"],"names":[],"mappings":";;AAEA,oCAWC;AAED,wCAkBC;AAED,oCAEC;AAED,sDAKC;AAED,kDASC;AArDD,SAAgB,YAAY,CAAC,KAAgC;IAC3D,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc,CAAC,OAAgB;IAC7C,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,YAAY;QAC3B,WAAW,EACT,OAAO,CAAC,YAAY;YAClB,CAAC,CAAC;gBACE,IAAI,EAAE,OAAO,CAAC,YAAY;gBAC1B,UAAU,EAAE,OAAO,CAAC,iBAAiB,IAAI,SAAS;aACnD;YACH,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;QACxC,SAAS,EAAE,OAAO,CAAC,UAAU;QAC7B,YAAY,EAAE,OAAO,CAAC,aAAa;QACnC,UAAU,EAAE,OAAO,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC;AAED,SAAgB,YAAY,CAAC,KAAqB;IAChD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,SAAgB,qBAAqB,CAAC,QAAmB;IACvD,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,SAAgB,mBAAmB,CACjC,OAAgB,EAChB,eAAwB;IAExB,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;QAChC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,EAAE;KACzC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presenter.test.d.ts","sourceRoot":"","sources":["../src/presenter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
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 presenter_1 = require("./presenter");
|
|
9
|
+
function makeSession(overrides = {}) {
|
|
10
|
+
return {
|
|
11
|
+
id: 'sess-1',
|
|
12
|
+
source: 'kimi',
|
|
13
|
+
events: [],
|
|
14
|
+
tool_counts: { Read: 2 },
|
|
15
|
+
started_at: 1000,
|
|
16
|
+
last_event_at: 2000,
|
|
17
|
+
active_skill: 'architect',
|
|
18
|
+
active_confidence: 'explicit',
|
|
19
|
+
status: 'running',
|
|
20
|
+
...overrides,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
(0, node_test_1.describe)('presenter', () => {
|
|
24
|
+
(0, node_test_1.it)('converts session to client shape', () => {
|
|
25
|
+
const session = makeSession();
|
|
26
|
+
const client = (0, presenter_1.presentSession)(session);
|
|
27
|
+
strict_1.default.equal(client.id, 'sess-1');
|
|
28
|
+
strict_1.default.equal(client.source, 'kimi');
|
|
29
|
+
strict_1.default.equal(client.skill, 'architect');
|
|
30
|
+
strict_1.default.deepEqual(client.activeSkill, { name: 'architect', confidence: 'explicit' });
|
|
31
|
+
strict_1.default.equal(client.status, 'running');
|
|
32
|
+
strict_1.default.equal(client.startTime, 1000);
|
|
33
|
+
strict_1.default.equal(client.lastActivity, 2000);
|
|
34
|
+
strict_1.default.deepEqual(client.toolCounts, { Read: 2 });
|
|
35
|
+
});
|
|
36
|
+
(0, node_test_1.it)('omits active skill when not set', () => {
|
|
37
|
+
const client = (0, presenter_1.presentSession)(makeSession({ active_skill: undefined }));
|
|
38
|
+
strict_1.default.equal(client.activeSkill, undefined);
|
|
39
|
+
strict_1.default.equal(client.skill, undefined);
|
|
40
|
+
});
|
|
41
|
+
(0, node_test_1.it)('presents state as client sessions', () => {
|
|
42
|
+
const state = {
|
|
43
|
+
sessions: {
|
|
44
|
+
'sess-1': makeSession(),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const sessions = (0, presenter_1.presentState)(state);
|
|
48
|
+
strict_1.default.equal(sessions.length, 1);
|
|
49
|
+
strict_1.default.equal(sessions[0].id, 'sess-1');
|
|
50
|
+
});
|
|
51
|
+
(0, node_test_1.it)('creates snapshot message', () => {
|
|
52
|
+
const message = (0, presenter_1.createSnapshotMessage)([makeSession()]);
|
|
53
|
+
strict_1.default.equal(message.type, 'snapshot');
|
|
54
|
+
strict_1.default.equal(message.sessions.length, 1);
|
|
55
|
+
strict_1.default.equal(message.sessions[0].id, 'sess-1');
|
|
56
|
+
});
|
|
57
|
+
(0, node_test_1.it)('creates update message with isActive flag', () => {
|
|
58
|
+
const message = (0, presenter_1.createUpdateMessage)(makeSession(), 'sess-1');
|
|
59
|
+
strict_1.default.equal(message.type, 'update');
|
|
60
|
+
strict_1.default.equal(message.session.id, 'sess-1');
|
|
61
|
+
strict_1.default.equal(message.isActive, true);
|
|
62
|
+
const inactive = (0, presenter_1.createUpdateMessage)(makeSession(), 'sess-2');
|
|
63
|
+
strict_1.default.equal(inactive.isActive, false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=presenter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presenter.test.js","sourceRoot":"","sources":["../src/presenter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { WebSocketServer } from 'ws';
|
|
3
|
+
import type { ServerConfig } from './types';
|
|
4
|
+
import { StateStore } from './state';
|
|
5
|
+
export interface DashboardServer {
|
|
6
|
+
httpServer: http.Server;
|
|
7
|
+
wss: WebSocketServer;
|
|
8
|
+
state: StateStore;
|
|
9
|
+
start: () => Promise<void>;
|
|
10
|
+
stop: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createDashboardServer(config: ServerConfig): DashboardServer;
|
|
13
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAA0B,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAOrC,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;IACxB,GAAG,EAAE,eAAe,CAAC;IACrB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAgK3E"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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"}
|