@airmcp-dev/meter 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +17 -0
  2. package/dist/classifier/index.d.ts +5 -0
  3. package/dist/classifier/index.d.ts.map +1 -0
  4. package/dist/classifier/index.js +6 -0
  5. package/dist/classifier/index.js.map +1 -0
  6. package/dist/classifier/layer-classifier.d.ts +15 -0
  7. package/dist/classifier/layer-classifier.d.ts.map +1 -0
  8. package/dist/classifier/layer-classifier.js +40 -0
  9. package/dist/classifier/layer-classifier.js.map +1 -0
  10. package/dist/classifier/layer-defs.d.ts +4 -0
  11. package/dist/classifier/layer-defs.d.ts.map +1 -0
  12. package/dist/classifier/layer-defs.js +60 -0
  13. package/dist/classifier/layer-defs.js.map +1 -0
  14. package/dist/classifier/rules.d.ts +14 -0
  15. package/dist/classifier/rules.d.ts.map +1 -0
  16. package/dist/classifier/rules.js +67 -0
  17. package/dist/classifier/rules.js.map +1 -0
  18. package/dist/cost/budget.d.ts +17 -0
  19. package/dist/cost/budget.d.ts.map +1 -0
  20. package/dist/cost/budget.js +74 -0
  21. package/dist/cost/budget.js.map +1 -0
  22. package/dist/cost/call-tracker.d.ts +23 -0
  23. package/dist/cost/call-tracker.d.ts.map +1 -0
  24. package/dist/cost/call-tracker.js +70 -0
  25. package/dist/cost/call-tracker.js.map +1 -0
  26. package/dist/cost/index.d.ts +4 -0
  27. package/dist/cost/index.d.ts.map +1 -0
  28. package/dist/cost/index.js +6 -0
  29. package/dist/cost/index.js.map +1 -0
  30. package/dist/cost/token-tracker.d.ts +19 -0
  31. package/dist/cost/token-tracker.d.ts.map +1 -0
  32. package/dist/cost/token-tracker.js +54 -0
  33. package/dist/cost/token-tracker.js.map +1 -0
  34. package/dist/index.d.ts +14 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +18 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/metrics/aggregator.d.ts +15 -0
  39. package/dist/metrics/aggregator.d.ts.map +1 -0
  40. package/dist/metrics/aggregator.js +51 -0
  41. package/dist/metrics/aggregator.js.map +1 -0
  42. package/dist/metrics/collector.d.ts +28 -0
  43. package/dist/metrics/collector.d.ts.map +1 -0
  44. package/dist/metrics/collector.js +38 -0
  45. package/dist/metrics/collector.js.map +1 -0
  46. package/dist/metrics/exporter.d.ts +13 -0
  47. package/dist/metrics/exporter.d.ts.map +1 -0
  48. package/dist/metrics/exporter.js +55 -0
  49. package/dist/metrics/exporter.js.map +1 -0
  50. package/dist/metrics/index.d.ts +4 -0
  51. package/dist/metrics/index.d.ts.map +1 -0
  52. package/dist/metrics/index.js +6 -0
  53. package/dist/metrics/index.js.map +1 -0
  54. package/dist/router/cost-router.d.ts +23 -0
  55. package/dist/router/cost-router.d.ts.map +1 -0
  56. package/dist/router/cost-router.js +43 -0
  57. package/dist/router/cost-router.js.map +1 -0
  58. package/dist/router/index.d.ts +3 -0
  59. package/dist/router/index.d.ts.map +1 -0
  60. package/dist/router/index.js +4 -0
  61. package/dist/router/index.js.map +1 -0
  62. package/dist/types.d.ts +77 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +4 -0
  65. package/dist/types.js.map +1 -0
  66. package/package.json +31 -0
package/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ Copyright 2026 CodePedia Labs (labs@codepedia.kr)
@@ -0,0 +1,5 @@
1
+ export { LayerClassifier } from './layer-classifier.js';
2
+ export { LAYER_DEFINITIONS, getLayerDef } from './layer-defs.js';
3
+ export { BUILTIN_RULES } from './rules.js';
4
+ export type { ClassificationRule } from './rules.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/classifier/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — classifier/index.ts
3
+ export { LayerClassifier } from './layer-classifier.js';
4
+ export { LAYER_DEFINITIONS, getLayerDef } from './layer-defs.js';
5
+ export { BUILTIN_RULES } from './rules.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/classifier/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,0CAA0C;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ClassificationResult } from '../types.js';
2
+ import { type ClassificationRule } from './rules.js';
3
+ export declare class LayerClassifier {
4
+ private rules;
5
+ constructor(customRules?: ClassificationRule[]);
6
+ /**
7
+ * 도구 호출을 분류한다.
8
+ * 첫 번째 매칭 규칙의 결과를 반환.
9
+ * 매칭 없으면 L4(중간) 기본값.
10
+ */
11
+ classify(toolName: string, params?: Record<string, any>): ClassificationResult;
12
+ /** 규칙을 추가한다 (최우선) */
13
+ addRule(rule: ClassificationRule): void;
14
+ }
15
+ //# sourceMappingURL=layer-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-classifier.d.ts","sourceRoot":"","sources":["../../src/classifier/layer-classifier.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAS,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEpE,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAuB;gBAExB,WAAW,CAAC,EAAE,kBAAkB,EAAE;IAK9C;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,oBAAoB;IAmB9E,qBAAqB;IACrB,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI;CAGxC"}
@@ -0,0 +1,40 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — classifier/layer-classifier.ts
3
+ //
4
+ // 도구 호출을 L1~L7로 자동 분류하는 엔진.
5
+ // 내장 규칙 + 사용자 정의 규칙 평가.
6
+ import { BUILTIN_RULES } from './rules.js';
7
+ export class LayerClassifier {
8
+ rules;
9
+ constructor(customRules) {
10
+ // 사용자 규칙이 내장 규칙보다 우선
11
+ this.rules = [...(customRules || []), ...BUILTIN_RULES];
12
+ }
13
+ /**
14
+ * 도구 호출을 분류한다.
15
+ * 첫 번째 매칭 규칙의 결과를 반환.
16
+ * 매칭 없으면 L4(중간) 기본값.
17
+ */
18
+ classify(toolName, params) {
19
+ for (const rule of this.rules) {
20
+ if (rule.match(toolName, params)) {
21
+ return {
22
+ layer: rule.layer,
23
+ confidence: rule.confidence,
24
+ reason: rule.reason,
25
+ };
26
+ }
27
+ }
28
+ // 기본값: L4 (중간)
29
+ return {
30
+ layer: 'L4',
31
+ confidence: 0.3,
32
+ reason: 'No matching rule — default to L4',
33
+ };
34
+ }
35
+ /** 규칙을 추가한다 (최우선) */
36
+ addRule(rule) {
37
+ this.rules.unshift(rule);
38
+ }
39
+ }
40
+ //# sourceMappingURL=layer-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-classifier.js","sourceRoot":"","sources":["../../src/classifier/layer-classifier.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,qDAAqD;AACrD,EAAE;AACF,4BAA4B;AAC5B,wBAAwB;AAGxB,OAAO,EAAE,aAAa,EAA2B,MAAM,YAAY,CAAC;AAEpE,MAAM,OAAO,eAAe;IAClB,KAAK,CAAuB;IAEpC,YAAY,WAAkC;QAC5C,qBAAqB;QACrB,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC;IAC1D,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,QAAgB,EAAE,MAA4B;QACrD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;gBACjC,OAAO;oBACL,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,eAAe;QACf,OAAO;YACL,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,GAAG;YACf,MAAM,EAAE,kCAAkC;SAC3C,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,OAAO,CAAC,IAAwB;QAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import type { Layer, LayerDef } from '../types.js';
2
+ export declare const LAYER_DEFINITIONS: Record<Layer, LayerDef>;
3
+ export declare function getLayerDef(layer: Layer): LayerDef;
4
+ //# sourceMappingURL=layer-defs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-defs.d.ts","sourceRoot":"","sources":["../../src/classifier/layer-defs.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAkDrD,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAElD"}
@@ -0,0 +1,60 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — classifier/layer-defs.ts
3
+ //
4
+ // Pylon-7 기반 7계층 정의.
5
+ // 상위(L1)→하위(L7)로 갈수록 토큰 소모와 위험도 증가.
6
+ export const LAYER_DEFINITIONS = {
7
+ L1: {
8
+ layer: 'L1',
9
+ name: 'Static Response',
10
+ description: 'No LLM needed. Cached/static data return.',
11
+ costWeight: 1,
12
+ riskLevel: 0,
13
+ },
14
+ L2: {
15
+ layer: 'L2',
16
+ name: 'Simple Lookup',
17
+ description: 'DB query, file read. Minimal processing.',
18
+ costWeight: 3,
19
+ riskLevel: 0.1,
20
+ },
21
+ L3: {
22
+ layer: 'L3',
23
+ name: 'Transform',
24
+ description: 'Data transformation, format conversion.',
25
+ costWeight: 5,
26
+ riskLevel: 0.15,
27
+ },
28
+ L4: {
29
+ layer: 'L4',
30
+ name: 'Compute',
31
+ description: 'Calculation, aggregation, analysis.',
32
+ costWeight: 10,
33
+ riskLevel: 0.2,
34
+ },
35
+ L5: {
36
+ layer: 'L5',
37
+ name: 'External API',
38
+ description: 'External service call. Network I/O.',
39
+ costWeight: 20,
40
+ riskLevel: 0.4,
41
+ },
42
+ L6: {
43
+ layer: 'L6',
44
+ name: 'LLM Inference',
45
+ description: 'AI model call. High token cost.',
46
+ costWeight: 50,
47
+ riskLevel: 0.6,
48
+ },
49
+ L7: {
50
+ layer: 'L7',
51
+ name: 'Multi-Step Agent',
52
+ description: 'Autonomous agent with tool chaining. Highest cost/risk.',
53
+ costWeight: 100,
54
+ riskLevel: 0.9,
55
+ },
56
+ };
57
+ export function getLayerDef(layer) {
58
+ return LAYER_DEFINITIONS[layer];
59
+ }
60
+ //# sourceMappingURL=layer-defs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-defs.js","sourceRoot":"","sources":["../../src/classifier/layer-defs.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,+CAA+C;AAC/C,EAAE;AACF,qBAAqB;AACrB,oCAAoC;AAIpC,MAAM,CAAC,MAAM,iBAAiB,GAA4B;IACxD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,2CAA2C;QACxD,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,CAAC;KACb;IACD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,GAAG;KACf;IACD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,yCAAyC;QACtD,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,IAAI;KAChB;IACD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,qCAAqC;QAClD,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,GAAG;KACf;IACD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,qCAAqC;QAClD,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,GAAG;KACf;IACD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,iCAAiC;QAC9C,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,GAAG;KACf;IACD,EAAE,EAAE;QACF,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,yDAAyD;QACtE,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,GAAG;KACf;CACF,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Layer } from '../types.js';
2
+ export interface ClassificationRule {
3
+ /** 매칭 조건 */
4
+ match: (toolName: string, params?: Record<string, any>) => boolean;
5
+ /** 분류 결과 */
6
+ layer: Layer;
7
+ /** 신뢰도 (0~1) */
8
+ confidence: number;
9
+ /** 이유 */
10
+ reason: string;
11
+ }
12
+ /** 내장 분류 규칙 */
13
+ export declare const BUILTIN_RULES: ClassificationRule[];
14
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/classifier/rules.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,kBAAkB;IACjC,YAAY;IACZ,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;IACnE,YAAY;IACZ,KAAK,EAAE,KAAK,CAAC;IACb,gBAAgB;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS;IACT,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAe;AACf,eAAO,MAAM,aAAa,EAAE,kBAAkB,EAgE7C,CAAC"}
@@ -0,0 +1,67 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — classifier/rules.ts
3
+ //
4
+ // 도구 호출을 7계층으로 분류하는 규칙.
5
+ // 도구명, 파라미터 패턴, 메타데이터 기반 휴리스틱.
6
+ /** 내장 분류 규칙 */
7
+ export const BUILTIN_RULES = [
8
+ // L1: 캐시/상수 반환
9
+ {
10
+ match: (name) => /^(ping|health|version|echo)$/i.test(name),
11
+ layer: 'L1',
12
+ confidence: 0.95,
13
+ reason: 'Static response tool',
14
+ },
15
+ // L2: 단순 조회
16
+ {
17
+ match: (name) => /^(get|read|find|lookup|list|show|fetch_local)$/i.test(name),
18
+ layer: 'L2',
19
+ confidence: 0.8,
20
+ reason: 'Simple data lookup',
21
+ },
22
+ // L3: 변환
23
+ {
24
+ match: (name) => /^(convert|transform|format|parse|encode|decode)$/i.test(name),
25
+ layer: 'L3',
26
+ confidence: 0.8,
27
+ reason: 'Data transformation',
28
+ },
29
+ // L4: 연산
30
+ {
31
+ match: (name) => /^(compute|calculate|aggregate|analyze|summarize|count)$/i.test(name),
32
+ layer: 'L4',
33
+ confidence: 0.75,
34
+ reason: 'Computation/analysis',
35
+ },
36
+ // L5: 외부 API
37
+ {
38
+ match: (name, params) => {
39
+ if (/^(fetch|request|call_api|webhook|http|post|put|delete)$/i.test(name))
40
+ return true;
41
+ // URL 파라미터가 있으면 외부 호출로 판단
42
+ if (params) {
43
+ const vals = Object.values(params).map(String);
44
+ return vals.some((v) => /^https?:\/\//.test(v));
45
+ }
46
+ return false;
47
+ },
48
+ layer: 'L5',
49
+ confidence: 0.85,
50
+ reason: 'External API call',
51
+ },
52
+ // L6: LLM 추론
53
+ {
54
+ match: (name) => /^(generate|complete|chat|embed|infer|predict|classify_ai)$/i.test(name),
55
+ layer: 'L6',
56
+ confidence: 0.9,
57
+ reason: 'LLM inference',
58
+ },
59
+ // L7: 에이전트
60
+ {
61
+ match: (name) => /^(agent|think|plan|execute|reason|chain|orchestrate)$/i.test(name),
62
+ layer: 'L7',
63
+ confidence: 0.85,
64
+ reason: 'Multi-step agent operation',
65
+ },
66
+ ];
67
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/classifier/rules.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,0CAA0C;AAC1C,EAAE;AACF,wBAAwB;AACxB,+BAA+B;AAe/B,eAAe;AACf,MAAM,CAAC,MAAM,aAAa,GAAyB;IACjD,eAAe;IACf;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC;QAC3D,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,sBAAsB;KAC/B;IAED,YAAY;IACZ;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,iDAAiD,CAAC,IAAI,CAAC,IAAI,CAAC;QAC7E,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,GAAG;QACf,MAAM,EAAE,oBAAoB;KAC7B;IAED,SAAS;IACT;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,mDAAmD,CAAC,IAAI,CAAC,IAAI,CAAC;QAC/E,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,GAAG;QACf,MAAM,EAAE,qBAAqB;KAC9B;IAED,SAAS;IACT;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,0DAA0D,CAAC,IAAI,CAAC,IAAI,CAAC;QACtF,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,sBAAsB;KAC/B;IAED,aAAa;IACb;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACtB,IAAI,0DAA0D,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YACvF,0BAA0B;YAC1B,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,mBAAmB;KAC5B;IAED,aAAa;IACb;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,6DAA6D,CAAC,IAAI,CAAC,IAAI,CAAC;QACzF,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,GAAG;QACf,MAAM,EAAE,eAAe;KACxB;IAED,WAAW;IACX;QACE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,wDAAwD,CAAC,IAAI,CAAC,IAAI,CAAC;QACpF,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,4BAA4B;KACrC;CACF,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { BudgetConfig, BudgetCheckResult } from '../types.js';
2
+ import { TokenTracker } from './token-tracker.js';
3
+ export declare class BudgetManager {
4
+ private config;
5
+ private tracker;
6
+ constructor(config: BudgetConfig, tracker: TokenTracker);
7
+ /**
8
+ * 호출 전에 예산 내인지 확인한다.
9
+ * block 모드면 초과 시 차단, warn 모드면 경고만.
10
+ */
11
+ check(estimatedTokens?: number): BudgetCheckResult;
12
+ /** 설정을 업데이트한다 */
13
+ updateConfig(config: Partial<BudgetConfig>): void;
14
+ /** 현재 설정을 반환한다 */
15
+ getConfig(): BudgetConfig;
16
+ }
17
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/cost/budget.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAc,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAe;gBAElB,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY;IAKvD;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,iBAAiB;IAuDlD,iBAAiB;IACjB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAIjD,kBAAkB;IAClB,SAAS,IAAI,YAAY;CAG1B"}
@@ -0,0 +1,74 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — cost/budget.ts
3
+ //
4
+ // 토큰/비용 예산 관리.
5
+ // 일일/월간 한도를 설정하고 초과 시 경고 또는 차단.
6
+ export class BudgetManager {
7
+ config;
8
+ tracker;
9
+ constructor(config, tracker) {
10
+ this.config = config;
11
+ this.tracker = tracker;
12
+ }
13
+ /**
14
+ * 호출 전에 예산 내인지 확인한다.
15
+ * block 모드면 초과 시 차단, warn 모드면 경고만.
16
+ */
17
+ check(estimatedTokens) {
18
+ // 호출당 토큰 제한
19
+ if (this.config.maxTokensPerCall && estimatedTokens) {
20
+ if (estimatedTokens > this.config.maxTokensPerCall) {
21
+ return {
22
+ allowed: this.config.onExceed !== 'block',
23
+ remaining: this.config.maxTokensPerCall - estimatedTokens,
24
+ limit: this.config.maxTokensPerCall,
25
+ period: 'per-call',
26
+ };
27
+ }
28
+ }
29
+ // 일일 한도
30
+ if (this.config.dailyLimit) {
31
+ const todayCost = this.tracker.today().reduce((sum, u) => sum + u.estimatedCost, 0);
32
+ const remaining = this.config.dailyLimit - todayCost;
33
+ if (remaining <= 0) {
34
+ return {
35
+ allowed: this.config.onExceed !== 'block',
36
+ remaining,
37
+ limit: this.config.dailyLimit,
38
+ period: 'daily',
39
+ };
40
+ }
41
+ }
42
+ // 월간 한도
43
+ if (this.config.monthlyLimit) {
44
+ const monthStart = new Date();
45
+ monthStart.setDate(1);
46
+ monthStart.setHours(0, 0, 0, 0);
47
+ const monthCost = this.tracker.since(monthStart).reduce((sum, u) => sum + u.estimatedCost, 0);
48
+ const remaining = this.config.monthlyLimit - monthCost;
49
+ if (remaining <= 0) {
50
+ return {
51
+ allowed: this.config.onExceed !== 'block',
52
+ remaining,
53
+ limit: this.config.monthlyLimit,
54
+ period: 'monthly',
55
+ };
56
+ }
57
+ }
58
+ return {
59
+ allowed: true,
60
+ remaining: Infinity,
61
+ limit: 0,
62
+ period: 'daily',
63
+ };
64
+ }
65
+ /** 설정을 업데이트한다 */
66
+ updateConfig(config) {
67
+ Object.assign(this.config, config);
68
+ }
69
+ /** 현재 설정을 반환한다 */
70
+ getConfig() {
71
+ return { ...this.config };
72
+ }
73
+ }
74
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/cost/budget.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,qCAAqC;AACrC,EAAE;AACF,eAAe;AACf,gCAAgC;AAKhC,MAAM,OAAO,aAAa;IAChB,MAAM,CAAe;IACrB,OAAO,CAAe;IAE9B,YAAY,MAAoB,EAAE,OAAqB;QACrD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAwB;QAC5B,YAAY;QACZ,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,eAAe,EAAE,CAAC;YACpD,IAAI,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACnD,OAAO;oBACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO;oBACzC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,eAAe;oBACzD,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB;oBACnC,MAAM,EAAE,UAAU;iBACnB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,QAAQ;QACR,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;YACpF,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;YAErD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO;oBACzC,SAAS;oBACT,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;oBAC7B,MAAM,EAAE,OAAO;iBAChB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,QAAQ;QACR,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;YAC9B,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACtB,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAEhC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;YAC9F,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC;YAEvD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO;oBACzC,SAAS;oBACT,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;oBAC/B,MAAM,EAAE,SAAS;iBAClB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,QAAQ;YACnB,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,YAAY,CAAC,MAA6B;QACxC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,kBAAkB;IAClB,SAAS;QACP,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ import type { CallMetric, Layer } from '../types.js';
2
+ export declare class CallTracker {
3
+ private metrics;
4
+ private maxHistory;
5
+ constructor(maxHistory?: number);
6
+ /** 호출 메트릭을 기록한다 */
7
+ record(toolName: string, layer: Layer, latencyMs: number, success: boolean, serverId?: string): CallMetric;
8
+ /** 총 호출 수 */
9
+ totalCalls(): number;
10
+ /** 성공률 (0~1) */
11
+ successRate(): number;
12
+ /** 평균 지연시간 (ms) */
13
+ avgLatency(): number;
14
+ /** 계층별 호출 분포 */
15
+ layerDistribution(): Record<Layer, number>;
16
+ /** 도구별 호출 수 */
17
+ toolCounts(): Record<string, number>;
18
+ /** 기간별 필터 */
19
+ since(date: Date): CallMetric[];
20
+ /** 전체 기록 */
21
+ getAll(): readonly CallMetric[];
22
+ }
23
+ //# sourceMappingURL=call-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-tracker.d.ts","sourceRoot":"","sources":["../../src/cost/call-tracker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAErD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,GAAE,MAAe;IAIvC,mBAAmB;IACnB,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,UAAU;IAkBb,aAAa;IACb,UAAU,IAAI,MAAM;IAIpB,gBAAgB;IAChB,WAAW,IAAI,MAAM;IAMrB,mBAAmB;IACnB,UAAU,IAAI,MAAM;IAMpB,gBAAgB;IAChB,iBAAiB,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;IAQ1C,eAAe;IACf,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQpC,aAAa;IACb,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,EAAE;IAI/B,YAAY;IACZ,MAAM,IAAI,SAAS,UAAU,EAAE;CAGhC"}
@@ -0,0 +1,70 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — cost/call-tracker.ts
3
+ //
4
+ // 도구 호출 횟수와 지연시간을 추적한다.
5
+ export class CallTracker {
6
+ metrics = [];
7
+ maxHistory;
8
+ constructor(maxHistory = 10_000) {
9
+ this.maxHistory = maxHistory;
10
+ }
11
+ /** 호출 메트릭을 기록한다 */
12
+ record(toolName, layer, latencyMs, success, serverId) {
13
+ const metric = {
14
+ toolName,
15
+ serverId,
16
+ layer,
17
+ latencyMs,
18
+ success,
19
+ timestamp: new Date(),
20
+ };
21
+ this.metrics.push(metric);
22
+ if (this.metrics.length > this.maxHistory) {
23
+ this.metrics = this.metrics.slice(-this.maxHistory);
24
+ }
25
+ return metric;
26
+ }
27
+ /** 총 호출 수 */
28
+ totalCalls() {
29
+ return this.metrics.length;
30
+ }
31
+ /** 성공률 (0~1) */
32
+ successRate() {
33
+ if (this.metrics.length === 0)
34
+ return 1;
35
+ const success = this.metrics.filter((m) => m.success).length;
36
+ return success / this.metrics.length;
37
+ }
38
+ /** 평균 지연시간 (ms) */
39
+ avgLatency() {
40
+ if (this.metrics.length === 0)
41
+ return 0;
42
+ const sum = this.metrics.reduce((s, m) => s + m.latencyMs, 0);
43
+ return sum / this.metrics.length;
44
+ }
45
+ /** 계층별 호출 분포 */
46
+ layerDistribution() {
47
+ const dist = { L1: 0, L2: 0, L3: 0, L4: 0, L5: 0, L6: 0, L7: 0 };
48
+ for (const m of this.metrics) {
49
+ dist[m.layer]++;
50
+ }
51
+ return dist;
52
+ }
53
+ /** 도구별 호출 수 */
54
+ toolCounts() {
55
+ const counts = {};
56
+ for (const m of this.metrics) {
57
+ counts[m.toolName] = (counts[m.toolName] || 0) + 1;
58
+ }
59
+ return counts;
60
+ }
61
+ /** 기간별 필터 */
62
+ since(date) {
63
+ return this.metrics.filter((m) => m.timestamp >= date);
64
+ }
65
+ /** 전체 기록 */
66
+ getAll() {
67
+ return this.metrics;
68
+ }
69
+ }
70
+ //# sourceMappingURL=call-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-tracker.js","sourceRoot":"","sources":["../../src/cost/call-tracker.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2CAA2C;AAC3C,EAAE;AACF,wBAAwB;AAIxB,MAAM,OAAO,WAAW;IACd,OAAO,GAAiB,EAAE,CAAC;IAC3B,UAAU,CAAS;IAE3B,YAAY,aAAqB,MAAM;QACrC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,mBAAmB;IACnB,MAAM,CACJ,QAAgB,EAChB,KAAY,EACZ,SAAiB,EACjB,OAAgB,EAChB,QAAiB;QAEjB,MAAM,MAAM,GAAe;YACzB,QAAQ;YACR,QAAQ;YACR,KAAK;YACL,SAAS;YACT,OAAO;YACP,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa;IACb,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,gBAAgB;IAChB,WAAW;QACT,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAC7D,OAAO,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IACvC,CAAC;IAED,mBAAmB;IACnB,UAAU;QACR,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC9D,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IACnC,CAAC;IAED,gBAAgB;IAChB,iBAAiB;QACf,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAA2B,CAAC;QAC1F,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe;IACf,UAAU;QACR,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa;IACb,KAAK,CAAC,IAAU;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,YAAY;IACZ,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { TokenTracker } from './token-tracker.js';
2
+ export { CallTracker } from './call-tracker.js';
3
+ export { BudgetManager } from './budget.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cost/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — cost/index.ts
3
+ export { TokenTracker } from './token-tracker.js';
4
+ export { CallTracker } from './call-tracker.js';
5
+ export { BudgetManager } from './budget.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cost/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,oCAAoC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { TokenUsage } from '../types.js';
2
+ export declare class TokenTracker {
3
+ private history;
4
+ private maxHistory;
5
+ constructor(maxHistory?: number);
6
+ /** 토큰 사용을 기록한다 */
7
+ record(toolName: string, input: number, output: number, costPerToken?: number): TokenUsage;
8
+ /** 총 토큰 사용량 */
9
+ totalTokens(): number;
10
+ /** 총 추정 비용 */
11
+ totalCost(): number;
12
+ /** 도구별 토큰 사용량 */
13
+ byTool(): Record<string, number>;
14
+ /** 기간별 필터 */
15
+ since(date: Date): TokenUsage[];
16
+ /** 오늘 사용량 */
17
+ today(): TokenUsage[];
18
+ }
19
+ //# sourceMappingURL=token-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-tracker.d.ts","sourceRoot":"","sources":["../../src/cost/token-tracker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,GAAE,MAAe;IAIvC,kBAAkB;IAClB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAE,MAAU,GAAG,UAAU;IAkB7F,eAAe;IACf,WAAW,IAAI,MAAM;IAIrB,cAAc;IACd,SAAS,IAAI,MAAM;IAInB,iBAAiB;IACjB,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQhC,aAAa;IACb,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,EAAE;IAI/B,aAAa;IACb,KAAK,IAAI,UAAU,EAAE;CAKtB"}
@@ -0,0 +1,54 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — cost/token-tracker.ts
3
+ //
4
+ // 도구 호출별 토큰 사용량을 추적한다.
5
+ export class TokenTracker {
6
+ history = [];
7
+ maxHistory;
8
+ constructor(maxHistory = 10_000) {
9
+ this.maxHistory = maxHistory;
10
+ }
11
+ /** 토큰 사용을 기록한다 */
12
+ record(toolName, input, output, costPerToken = 0) {
13
+ const usage = {
14
+ toolName,
15
+ inputTokens: input,
16
+ outputTokens: output,
17
+ totalTokens: input + output,
18
+ estimatedCost: (input + output) * costPerToken,
19
+ timestamp: new Date(),
20
+ };
21
+ this.history.push(usage);
22
+ if (this.history.length > this.maxHistory) {
23
+ this.history = this.history.slice(-this.maxHistory);
24
+ }
25
+ return usage;
26
+ }
27
+ /** 총 토큰 사용량 */
28
+ totalTokens() {
29
+ return this.history.reduce((sum, u) => sum + u.totalTokens, 0);
30
+ }
31
+ /** 총 추정 비용 */
32
+ totalCost() {
33
+ return this.history.reduce((sum, u) => sum + u.estimatedCost, 0);
34
+ }
35
+ /** 도구별 토큰 사용량 */
36
+ byTool() {
37
+ const result = {};
38
+ for (const u of this.history) {
39
+ result[u.toolName] = (result[u.toolName] || 0) + u.totalTokens;
40
+ }
41
+ return result;
42
+ }
43
+ /** 기간별 필터 */
44
+ since(date) {
45
+ return this.history.filter((u) => u.timestamp >= date);
46
+ }
47
+ /** 오늘 사용량 */
48
+ today() {
49
+ const start = new Date();
50
+ start.setHours(0, 0, 0, 0);
51
+ return this.since(start);
52
+ }
53
+ }
54
+ //# sourceMappingURL=token-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-tracker.js","sourceRoot":"","sources":["../../src/cost/token-tracker.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4CAA4C;AAC5C,EAAE;AACF,uBAAuB;AAIvB,MAAM,OAAO,YAAY;IACf,OAAO,GAAiB,EAAE,CAAC;IAC3B,UAAU,CAAS;IAE3B,YAAY,aAAqB,MAAM;QACrC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,kBAAkB;IAClB,MAAM,CAAC,QAAgB,EAAE,KAAa,EAAE,MAAc,EAAE,eAAuB,CAAC;QAC9E,MAAM,KAAK,GAAe;YACxB,QAAQ;YACR,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,KAAK,GAAG,MAAM;YAC3B,aAAa,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,YAAY;YAC9C,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe;IACf,WAAW;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,cAAc;IACd,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,iBAAiB;IACjB,MAAM;QACJ,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;QACjE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa;IACb,KAAK,CAAC,IAAU;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,aAAa;IACb,KAAK;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ export { LayerClassifier } from './classifier/index.js';
2
+ export { LAYER_DEFINITIONS, getLayerDef } from './classifier/index.js';
3
+ export { BUILTIN_RULES } from './classifier/index.js';
4
+ export { TokenTracker } from './cost/index.js';
5
+ export { CallTracker } from './cost/index.js';
6
+ export { BudgetManager } from './cost/index.js';
7
+ export { MetricsCollector } from './metrics/index.js';
8
+ export { MetricsAggregator } from './metrics/index.js';
9
+ export { MetricsExporter } from './metrics/index.js';
10
+ export { selectCheapest } from './router/index.js';
11
+ export type { Layer, LayerDef, ClassificationResult, TokenUsage, CallMetric, AggregatedMetrics, BudgetConfig, BudgetCheckResult, } from './types.js';
12
+ export type { ClassificationRule } from './classifier/index.js';
13
+ export type { CostCandidate, CostRouteResult } from './router/index.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnD,YAAY,EACV,KAAK,EACL,QAAQ,EACR,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — index.ts
3
+ // re-export only. 로직 없음.
4
+ // ── Classifier ──
5
+ export { LayerClassifier } from './classifier/index.js';
6
+ export { LAYER_DEFINITIONS, getLayerDef } from './classifier/index.js';
7
+ export { BUILTIN_RULES } from './classifier/index.js';
8
+ // ── Cost ──
9
+ export { TokenTracker } from './cost/index.js';
10
+ export { CallTracker } from './cost/index.js';
11
+ export { BudgetManager } from './cost/index.js';
12
+ // ── Metrics ──
13
+ export { MetricsCollector } from './metrics/index.js';
14
+ export { MetricsAggregator } from './metrics/index.js';
15
+ export { MetricsExporter } from './metrics/index.js';
16
+ // ── Router ──
17
+ export { selectCheapest } from './router/index.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,+BAA+B;AAC/B,yBAAyB;AAEzB,mBAAmB;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,eAAe;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { AggregatedMetrics } from '../types.js';
2
+ import { MetricsCollector } from './collector.js';
3
+ export declare class MetricsAggregator {
4
+ private collector;
5
+ constructor(collector: MetricsCollector);
6
+ /**
7
+ * 지정 기간의 집계 메트릭을 반환한다.
8
+ */
9
+ aggregate(from: Date, to?: Date): AggregatedMetrics;
10
+ /** 최근 1시간 집계 */
11
+ lastHour(): AggregatedMetrics;
12
+ /** 오늘 집계 */
13
+ today(): AggregatedMetrics;
14
+ }
15
+ //# sourceMappingURL=aggregator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregator.d.ts","sourceRoot":"","sources":["../../src/metrics/aggregator.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAS,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAmB;gBAExB,SAAS,EAAE,gBAAgB;IAIvC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAE,IAAiB,GAAG,iBAAiB;IA+B/D,gBAAgB;IAChB,QAAQ,IAAI,iBAAiB;IAI7B,YAAY;IACZ,KAAK,IAAI,iBAAiB;CAK3B"}
@@ -0,0 +1,51 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — metrics/aggregator.ts
3
+ //
4
+ // 시간별 메트릭 집계.
5
+ // 분/시간/일 단위로 집계하여 추세 분석 가능.
6
+ export class MetricsAggregator {
7
+ collector;
8
+ constructor(collector) {
9
+ this.collector = collector;
10
+ }
11
+ /**
12
+ * 지정 기간의 집계 메트릭을 반환한다.
13
+ */
14
+ aggregate(from, to = new Date()) {
15
+ const calls = this.collector.calls.since(from);
16
+ const tokens = this.collector.tokens.since(from);
17
+ const totalCalls = calls.length;
18
+ const successCount = calls.filter((c) => c.success).length;
19
+ const avgLatency = totalCalls > 0 ? calls.reduce((s, c) => s + c.latencyMs, 0) / totalCalls : 0;
20
+ const layerDist = { L1: 0, L2: 0, L3: 0, L4: 0, L5: 0, L6: 0, L7: 0 };
21
+ for (const c of calls) {
22
+ layerDist[c.layer]++;
23
+ }
24
+ const toolCounts = {};
25
+ for (const c of calls) {
26
+ toolCounts[c.toolName] = (toolCounts[c.toolName] || 0) + 1;
27
+ }
28
+ return {
29
+ totalCalls,
30
+ successRate: totalCalls > 0 ? successCount / totalCalls : 1,
31
+ avgLatencyMs: avgLatency,
32
+ totalTokens: tokens.reduce((s, t) => s + t.totalTokens, 0),
33
+ totalCost: tokens.reduce((s, t) => s + t.estimatedCost, 0),
34
+ layerDistribution: layerDist,
35
+ toolCounts,
36
+ from,
37
+ to,
38
+ };
39
+ }
40
+ /** 최근 1시간 집계 */
41
+ lastHour() {
42
+ return this.aggregate(new Date(Date.now() - 3600_000));
43
+ }
44
+ /** 오늘 집계 */
45
+ today() {
46
+ const start = new Date();
47
+ start.setHours(0, 0, 0, 0);
48
+ return this.aggregate(start);
49
+ }
50
+ }
51
+ //# sourceMappingURL=aggregator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregator.js","sourceRoot":"","sources":["../../src/metrics/aggregator.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4CAA4C;AAC5C,EAAE;AACF,cAAc;AACd,4BAA4B;AAK5B,MAAM,OAAO,iBAAiB;IACpB,SAAS,CAAmB;IAEpC,YAAY,SAA2B;QACrC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,IAAU,EAAE,KAAW,IAAI,IAAI,EAAE;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEjD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;QAChC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAC3D,MAAM,UAAU,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhG,MAAM,SAAS,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAA2B,CAAC;QAC/F,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,UAAU,GAA2B,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO;YACL,UAAU;YACV,WAAW,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAC3D,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAC1D,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;YAC1D,iBAAiB,EAAE,SAAS;YAC5B,UAAU;YACV,IAAI;YACJ,EAAE;SACH,CAAC;IACJ,CAAC;IAED,gBAAgB;IAChB,QAAQ;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,YAAY;IACZ,KAAK;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import type { Layer } from '../types.js';
2
+ import { CallTracker } from '../cost/call-tracker.js';
3
+ import { TokenTracker } from '../cost/token-tracker.js';
4
+ export declare class MetricsCollector {
5
+ readonly calls: CallTracker;
6
+ readonly tokens: TokenTracker;
7
+ constructor();
8
+ /**
9
+ * 도구 호출을 기록한다 (호출 메트릭 + 토큰 사용 동시).
10
+ */
11
+ recordCall(toolName: string, layer: Layer, latencyMs: number, success: boolean, tokenUsage?: {
12
+ input: number;
13
+ output: number;
14
+ costPerToken?: number;
15
+ }, serverId?: string): void;
16
+ /**
17
+ * 현재 시점의 스냅샷을 반환한다.
18
+ */
19
+ snapshot(): {
20
+ totalCalls: number;
21
+ successRate: number;
22
+ avgLatencyMs: number;
23
+ totalTokens: number;
24
+ totalCost: number;
25
+ layerDistribution: Record<Layer, number>;
26
+ };
27
+ }
28
+ //# sourceMappingURL=collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/metrics/collector.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA6C,KAAK,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;;IAO9B;;OAEG;IACH,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,EACrE,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI;IAaP;;OAEG;IACH,QAAQ,IAAI;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;KAC1C;CAUF"}
@@ -0,0 +1,38 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — metrics/collector.ts
3
+ //
4
+ // 메트릭 수집기. CallTracker + TokenTracker의 데이터를 모아서
5
+ // 집계 가능한 형태로 관리.
6
+ import { CallTracker } from '../cost/call-tracker.js';
7
+ import { TokenTracker } from '../cost/token-tracker.js';
8
+ export class MetricsCollector {
9
+ calls;
10
+ tokens;
11
+ constructor() {
12
+ this.calls = new CallTracker();
13
+ this.tokens = new TokenTracker();
14
+ }
15
+ /**
16
+ * 도구 호출을 기록한다 (호출 메트릭 + 토큰 사용 동시).
17
+ */
18
+ recordCall(toolName, layer, latencyMs, success, tokenUsage, serverId) {
19
+ this.calls.record(toolName, layer, latencyMs, success, serverId);
20
+ if (tokenUsage) {
21
+ this.tokens.record(toolName, tokenUsage.input, tokenUsage.output, tokenUsage.costPerToken || 0);
22
+ }
23
+ }
24
+ /**
25
+ * 현재 시점의 스냅샷을 반환한다.
26
+ */
27
+ snapshot() {
28
+ return {
29
+ totalCalls: this.calls.totalCalls(),
30
+ successRate: this.calls.successRate(),
31
+ avgLatencyMs: this.calls.avgLatency(),
32
+ totalTokens: this.tokens.totalTokens(),
33
+ totalCost: this.tokens.totalCost(),
34
+ layerDistribution: this.calls.layerDistribution(),
35
+ };
36
+ }
37
+ }
38
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/metrics/collector.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2CAA2C;AAC3C,EAAE;AACF,gDAAgD;AAChD,iBAAiB;AAGjB,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,MAAM,OAAO,gBAAgB;IAClB,KAAK,CAAc;IACnB,MAAM,CAAe;IAE9B;QACE,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,UAAU,CACR,QAAgB,EAChB,KAAY,EACZ,SAAiB,EACjB,OAAgB,EAChB,UAAqE,EACrE,QAAiB;QAEjB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAEjE,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,MAAM,CAChB,QAAQ,EACR,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,MAAM,EACjB,UAAU,CAAC,YAAY,IAAI,CAAC,CAC7B,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QAQN,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YACnC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YACrC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YACrC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;YACtC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;YAClC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE;SAClD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { AggregatedMetrics } from '../types.js';
2
+ export declare class MetricsExporter {
3
+ /**
4
+ * JSON 형식으로 내보낸다.
5
+ */
6
+ toJSON(metrics: AggregatedMetrics): string;
7
+ /**
8
+ * Prometheus 텍스트 형식으로 내보낸다.
9
+ * Prometheus의 /metrics 엔드포인트에서 사용.
10
+ */
11
+ toPrometheus(metrics: AggregatedMetrics): string;
12
+ }
13
+ //# sourceMappingURL=exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../src/metrics/exporter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAS,MAAM,aAAa,CAAC;AAI5D,qBAAa,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM;IAI1C;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM;CA4CjD"}
@@ -0,0 +1,55 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — metrics/exporter.ts
3
+ //
4
+ // 메트릭을 외부 형식으로 내보낸다.
5
+ // Prometheus 텍스트 포맷 + JSON.
6
+ const LAYERS = ['L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'L7'];
7
+ export class MetricsExporter {
8
+ /**
9
+ * JSON 형식으로 내보낸다.
10
+ */
11
+ toJSON(metrics) {
12
+ return JSON.stringify(metrics, null, 2);
13
+ }
14
+ /**
15
+ * Prometheus 텍스트 형식으로 내보낸다.
16
+ * Prometheus의 /metrics 엔드포인트에서 사용.
17
+ */
18
+ toPrometheus(metrics) {
19
+ const lines = [];
20
+ // 총 호출 수
21
+ lines.push('# HELP air_tool_calls_total Total number of tool calls');
22
+ lines.push('# TYPE air_tool_calls_total counter');
23
+ lines.push(`air_tool_calls_total ${metrics.totalCalls}`);
24
+ // 성공률
25
+ lines.push('# HELP air_tool_success_rate Tool call success rate');
26
+ lines.push('# TYPE air_tool_success_rate gauge');
27
+ lines.push(`air_tool_success_rate ${metrics.successRate.toFixed(4)}`);
28
+ // 평균 지연시간
29
+ lines.push('# HELP air_tool_latency_avg_ms Average tool call latency in ms');
30
+ lines.push('# TYPE air_tool_latency_avg_ms gauge');
31
+ lines.push(`air_tool_latency_avg_ms ${metrics.avgLatencyMs.toFixed(2)}`);
32
+ // 총 토큰
33
+ lines.push('# HELP air_tokens_total Total tokens consumed');
34
+ lines.push('# TYPE air_tokens_total counter');
35
+ lines.push(`air_tokens_total ${metrics.totalTokens}`);
36
+ // 총 비용
37
+ lines.push('# HELP air_cost_total Total estimated cost in USD');
38
+ lines.push('# TYPE air_cost_total counter');
39
+ lines.push(`air_cost_total ${metrics.totalCost.toFixed(6)}`);
40
+ // 계층별 분포
41
+ lines.push('# HELP air_layer_calls Tool calls by layer');
42
+ lines.push('# TYPE air_layer_calls gauge');
43
+ for (const layer of LAYERS) {
44
+ lines.push(`air_layer_calls{layer="${layer}"} ${metrics.layerDistribution[layer] || 0}`);
45
+ }
46
+ // 도구별 호출 수
47
+ lines.push('# HELP air_tool_calls Tool calls by tool name');
48
+ lines.push('# TYPE air_tool_calls gauge');
49
+ for (const [tool, count] of Object.entries(metrics.toolCounts)) {
50
+ lines.push(`air_tool_calls{tool="${tool}"} ${count}`);
51
+ }
52
+ return lines.join('\n') + '\n';
53
+ }
54
+ }
55
+ //# sourceMappingURL=exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../src/metrics/exporter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,0CAA0C;AAC1C,EAAE;AACF,qBAAqB;AACrB,4BAA4B;AAI5B,MAAM,MAAM,GAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEnE,MAAM,OAAO,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,OAA0B;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,OAA0B;QACrC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,SAAS;QACT,KAAK,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAEzD,MAAM;QACN,KAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,yBAAyB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEtE,UAAU;QACV,KAAK,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,2BAA2B,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEzE,OAAO;QACP,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAEtD,OAAO;QACP,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAE7D,SAAS;QACT,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,0BAA0B,KAAK,MAAM,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC;QAED,WAAW;QACX,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,wBAAwB,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { MetricsCollector } from './collector.js';
2
+ export { MetricsAggregator } from './aggregator.js';
3
+ export { MetricsExporter } from './exporter.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,6 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — metrics/index.ts
3
+ export { MetricsCollector } from './collector.js';
4
+ export { MetricsAggregator } from './aggregator.js';
5
+ export { MetricsExporter } from './exporter.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,uCAAuC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Layer } from '../types.js';
2
+ export interface CostCandidate {
3
+ serverId: string;
4
+ toolName: string;
5
+ layer: Layer;
6
+ /** 최근 평균 지연시간 (ms) */
7
+ avgLatencyMs?: number;
8
+ /** 최근 성공률 (0~1) */
9
+ successRate?: number;
10
+ }
11
+ export interface CostRouteResult {
12
+ selected: CostCandidate;
13
+ reason: string;
14
+ score: number;
15
+ }
16
+ /**
17
+ * 후보들 중 최소 비용 경로를 선택한다.
18
+ *
19
+ * 점수 = costWeight × (1 / successRate) × latencyFactor
20
+ * → 낮을수록 좋음
21
+ */
22
+ export declare function selectCheapest(candidates: CostCandidate[]): CostRouteResult;
23
+ //# sourceMappingURL=cost-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-router.d.ts","sourceRoot":"","sources":["../../src/router/cost-router.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,sBAAsB;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,eAAe,CAiC3E"}
@@ -0,0 +1,43 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — router/cost-router.ts
3
+ //
4
+ // 최소 비용 경로 라우팅.
5
+ // 같은 도구를 여러 서버가 제공할 때, 계층(L1~L7) 기반으로
6
+ // 가장 비용 효율적인 서버를 선택한다.
7
+ // Pylon-7의 핵심: "최소 비용으로 목적 달성."
8
+ import { LAYER_DEFINITIONS } from '../classifier/layer-defs.js';
9
+ /**
10
+ * 후보들 중 최소 비용 경로를 선택한다.
11
+ *
12
+ * 점수 = costWeight × (1 / successRate) × latencyFactor
13
+ * → 낮을수록 좋음
14
+ */
15
+ export function selectCheapest(candidates) {
16
+ if (candidates.length === 0) {
17
+ throw new Error('No candidates for cost routing');
18
+ }
19
+ if (candidates.length === 1) {
20
+ return {
21
+ selected: candidates[0],
22
+ reason: 'Only one candidate',
23
+ score: 0,
24
+ };
25
+ }
26
+ const scored = candidates.map((c) => {
27
+ const layerDef = LAYER_DEFINITIONS[c.layer];
28
+ const costWeight = layerDef.costWeight;
29
+ const successFactor = 1 / (c.successRate ?? 1);
30
+ const latencyFactor = 1 + (c.avgLatencyMs ?? 0) / 10_000; // 10초 기준 정규화
31
+ const score = costWeight * successFactor * latencyFactor;
32
+ return { candidate: c, score };
33
+ });
34
+ // 점수 오름차순 정렬 (낮을수록 좋음)
35
+ scored.sort((a, b) => a.score - b.score);
36
+ const best = scored[0];
37
+ return {
38
+ selected: best.candidate,
39
+ reason: `Cheapest path: ${best.candidate.layer} (score: ${best.score.toFixed(2)})`,
40
+ score: best.score,
41
+ };
42
+ }
43
+ //# sourceMappingURL=cost-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-router.js","sourceRoot":"","sources":["../../src/router/cost-router.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4CAA4C;AAC5C,EAAE;AACF,gBAAgB;AAChB,sCAAsC;AACtC,uBAAuB;AACvB,gCAAgC;AAGhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAkBhE;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,UAA2B;IACxD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;YACvB,MAAM,EAAE,oBAAoB;YAC5B,KAAK,EAAE,CAAC;SACT,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAClC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;QACvC,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;QAC/C,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,aAAa;QAEvE,MAAM,KAAK,GAAG,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC;QAEzD,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,uBAAuB;IACvB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAEvB,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,MAAM,EAAE,kBAAkB,IAAI,CAAC,SAAS,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAClF,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { selectCheapest } from './cost-router.js';
2
+ export type { CostCandidate, CostRouteResult } from './cost-router.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — router/index.ts
3
+ export { selectCheapest } from './cost-router.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,sCAAsC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,77 @@
1
+ /** 7-Layer 계층 정의 (Pylon-7 기반) */
2
+ export type Layer = 'L1' | 'L2' | 'L3' | 'L4' | 'L5' | 'L6' | 'L7';
3
+ /** 계층별 정보 */
4
+ export interface LayerDef {
5
+ layer: Layer;
6
+ name: string;
7
+ description: string;
8
+ /** 상대적 토큰 비용 (L1=1, L7=100) */
9
+ costWeight: number;
10
+ /** 위험도 (0~1) */
11
+ riskLevel: number;
12
+ }
13
+ /** 분류 결과 */
14
+ export interface ClassificationResult {
15
+ layer: Layer;
16
+ confidence: number;
17
+ reason: string;
18
+ }
19
+ /** 토큰 사용 기록 */
20
+ export interface TokenUsage {
21
+ toolName: string;
22
+ inputTokens: number;
23
+ outputTokens: number;
24
+ totalTokens: number;
25
+ estimatedCost: number;
26
+ timestamp: Date;
27
+ }
28
+ /** 호출 메트릭 */
29
+ export interface CallMetric {
30
+ toolName: string;
31
+ serverId?: string;
32
+ layer: Layer;
33
+ latencyMs: number;
34
+ success: boolean;
35
+ timestamp: Date;
36
+ tokenUsage?: TokenUsage;
37
+ }
38
+ /** 집계 메트릭 */
39
+ export interface AggregatedMetrics {
40
+ /** 총 호출 수 */
41
+ totalCalls: number;
42
+ /** 성공률 (0~1) */
43
+ successRate: number;
44
+ /** 평균 지연시간 (ms) */
45
+ avgLatencyMs: number;
46
+ /** 총 토큰 사용량 */
47
+ totalTokens: number;
48
+ /** 총 추정 비용 ($) */
49
+ totalCost: number;
50
+ /** 계층별 호출 분포 */
51
+ layerDistribution: Record<Layer, number>;
52
+ /** 도구별 호출 수 */
53
+ toolCounts: Record<string, number>;
54
+ /** 집계 시작 시각 */
55
+ from: Date;
56
+ /** 집계 종료 시각 */
57
+ to: Date;
58
+ }
59
+ /** 예산 설정 */
60
+ export interface BudgetConfig {
61
+ /** 일일 최대 비용 ($) */
62
+ dailyLimit?: number;
63
+ /** 월간 최대 비용 ($) */
64
+ monthlyLimit?: number;
65
+ /** 호출당 최대 토큰 */
66
+ maxTokensPerCall?: number;
67
+ /** 예산 초과 시 동작 */
68
+ onExceed: 'warn' | 'block';
69
+ }
70
+ /** 예산 체크 결과 */
71
+ export interface BudgetCheckResult {
72
+ allowed: boolean;
73
+ remaining: number;
74
+ limit: number;
75
+ period: 'daily' | 'monthly' | 'per-call';
76
+ }
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,iCAAiC;AACjC,MAAM,MAAM,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnE,aAAa;AACb,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,YAAY;AACZ,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAe;AACf,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,aAAa;AACb,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,aAAa;AACb,MAAM,WAAW,iBAAiB;IAChC,aAAa;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,iBAAiB,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACzC,eAAe;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe;IACf,IAAI,EAAE,IAAI,CAAC;IACX,eAAe;IACf,EAAE,EAAE,IAAI,CAAC;CACV;AAED,YAAY;AACZ,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB;IACjB,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED,eAAe;AACf,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;CAC1C"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/meter — types.ts
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,+BAA+B"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@airmcp-dev/meter",
3
+ "version": "0.1.0",
4
+ "description": "MCP performance metering — 7-Layer classification, token cost tracking, metrics export",
5
+ "type": "module",
6
+ "files": ["dist", "README.md", "LICENSE"],
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": "./dist/index.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "test": "vitest run",
15
+ "lint": "tsc --noEmit"
16
+ },
17
+ "dependencies": {
18
+ "@airmcp-dev/core": "^0.1.0"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.5.0",
22
+ "vitest": "^2.0.0",
23
+ "@types/node": "^20.0.0"
24
+ },
25
+ "author": "CodePedia Labs",
26
+ "homepage": "https://airmcp.dev",
27
+ "bugs": { "url": "https://github.com/airmcp-dev/air/issues" },
28
+ "repository": { "type": "git", "url": "https://github.com/airmcp-dev/air", "directory": "packages/meter" },
29
+ "keywords": ["mcp", "ai", "agent", "air"],
30
+ "license": "Apache-2.0"
31
+ }