ccjk 12.2.0 → 12.2.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.
@@ -3,13 +3,13 @@ import { a as getGlobalStateManager, g as getGlobalConvoyManager, S as SessionIn
3
3
  import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
4
4
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
5
5
  import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
6
+ import process__default from 'node:process';
6
7
  import 'node:child_process';
7
8
  import 'node:fs/promises';
8
9
  import 'node:os';
9
10
  import 'node:path';
10
11
  import './main.mjs';
11
12
  import 'module';
12
- import 'node:process';
13
13
  import 'node:stream';
14
14
  import 'node:readline';
15
15
  import 'node:crypto';
@@ -992,6 +992,418 @@ function getGlobalMayorAgent(config) {
992
992
  return globalMayorAgent;
993
993
  }
994
994
 
995
+ class MetricsCollector {
996
+ metrics = /* @__PURE__ */ new Map();
997
+ taskMetrics = /* @__PURE__ */ new Map();
998
+ performanceMetrics = /* @__PURE__ */ new Map();
999
+ maxRecords;
1000
+ retentionPeriod;
1001
+ constructor(options = {}) {
1002
+ this.maxRecords = options.maxRecords ?? 1e3;
1003
+ this.retentionPeriod = options.retentionPeriod ?? 36e5;
1004
+ }
1005
+ /**
1006
+ * Record a metric value
1007
+ */
1008
+ recordMetric(agentId, metricName, value, metadata) {
1009
+ if (!this.metrics.has(agentId)) {
1010
+ this.metrics.set(agentId, /* @__PURE__ */ new Map());
1011
+ }
1012
+ const agentMetrics = this.metrics.get(agentId);
1013
+ if (!agentMetrics.has(metricName)) {
1014
+ agentMetrics.set(metricName, []);
1015
+ }
1016
+ const records = agentMetrics.get(metricName);
1017
+ records.push({
1018
+ timestamp: Date.now(),
1019
+ value,
1020
+ metadata
1021
+ });
1022
+ this.trimRecords(records);
1023
+ }
1024
+ /**
1025
+ * Record CPU usage
1026
+ */
1027
+ recordCpuUsage(agentId, usage) {
1028
+ this.recordMetric(agentId, "cpu_usage", usage);
1029
+ this.updatePerformanceMetrics(agentId, { cpuUsage: usage });
1030
+ }
1031
+ /**
1032
+ * Record memory usage
1033
+ */
1034
+ recordMemoryUsage(agentId, usage) {
1035
+ this.recordMetric(agentId, "memory_usage", usage);
1036
+ this.updatePerformanceMetrics(agentId, { memoryUsage: usage });
1037
+ }
1038
+ /**
1039
+ * Record response time
1040
+ */
1041
+ recordResponseTime(agentId, responseTime) {
1042
+ this.recordMetric(agentId, "response_time", responseTime);
1043
+ this.updatePerformanceMetrics(agentId, { responseTime });
1044
+ }
1045
+ /**
1046
+ * Record task completion
1047
+ */
1048
+ recordTaskCompletion(agentId, success, duration) {
1049
+ if (!this.taskMetrics.has(agentId)) {
1050
+ this.taskMetrics.set(agentId, {
1051
+ totalTasks: 0,
1052
+ completedTasks: 0,
1053
+ failedTasks: 0,
1054
+ avgDuration: 0,
1055
+ successRate: 0
1056
+ });
1057
+ }
1058
+ const metrics = this.taskMetrics.get(agentId);
1059
+ metrics.totalTasks++;
1060
+ if (success) {
1061
+ metrics.completedTasks++;
1062
+ } else {
1063
+ metrics.failedTasks++;
1064
+ }
1065
+ metrics.avgDuration = (metrics.avgDuration * (metrics.totalTasks - 1) + duration) / metrics.totalTasks;
1066
+ metrics.successRate = metrics.completedTasks / metrics.totalTasks;
1067
+ this.recordMetric(agentId, "task_duration", duration, { success });
1068
+ }
1069
+ /**
1070
+ * Record error
1071
+ */
1072
+ recordError(agentId, errorType, errorMessage) {
1073
+ this.recordMetric(agentId, "error", 1, { errorType, errorMessage });
1074
+ this.updatePerformanceMetrics(agentId, { errorCount: 1 });
1075
+ }
1076
+ /**
1077
+ * Get agent metrics
1078
+ */
1079
+ getAgentMetrics(agentId) {
1080
+ const taskMetrics = this.taskMetrics.get(agentId);
1081
+ const cpuRecords = this.getMetricRecords(agentId, "cpu_usage");
1082
+ const memoryRecords = this.getMetricRecords(agentId, "memory_usage");
1083
+ const responseTimeRecords = this.getMetricRecords(agentId, "response_time");
1084
+ const cpuUsage = cpuRecords.length > 0 ? cpuRecords[cpuRecords.length - 1].value : 0;
1085
+ const memoryUsage = memoryRecords.length > 0 ? memoryRecords[memoryRecords.length - 1].value : 0;
1086
+ this.calculateAverage(responseTimeRecords.map((r) => r.value));
1087
+ taskMetrics ? taskMetrics.failedTasks / taskMetrics.totalTasks : 0;
1088
+ return {
1089
+ tasksExecuted: taskMetrics?.totalTasks ?? 0,
1090
+ tasksSucceeded: taskMetrics?.completedTasks ?? 0,
1091
+ tasksFailed: taskMetrics?.failedTasks ?? 0,
1092
+ avgTaskDuration: taskMetrics?.avgDuration ?? 0,
1093
+ successRate: taskMetrics?.successRate ?? 0,
1094
+ totalExecutionTime: taskMetrics?.avgDuration ?? 0,
1095
+ avgConfidence: 0.8,
1096
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
1097
+ cpuUsage,
1098
+ memoryUsage
1099
+ };
1100
+ }
1101
+ /**
1102
+ * Get metric snapshot
1103
+ */
1104
+ getMetricSnapshot(agentId, metricName, timeRange) {
1105
+ const records = this.getMetricRecords(agentId, metricName, timeRange);
1106
+ const values = records.map((r) => r.value);
1107
+ if (values.length === 0) {
1108
+ return {
1109
+ metricName,
1110
+ agentId,
1111
+ timestamp: Date.now(),
1112
+ current: 0,
1113
+ min: 0,
1114
+ max: 0,
1115
+ avg: 0,
1116
+ count: 0
1117
+ };
1118
+ }
1119
+ return {
1120
+ metricName,
1121
+ agentId,
1122
+ timestamp: Date.now(),
1123
+ current: values[values.length - 1],
1124
+ min: Math.min(...values),
1125
+ max: Math.max(...values),
1126
+ avg: this.calculateAverage(values),
1127
+ count: values.length
1128
+ };
1129
+ }
1130
+ /**
1131
+ * Get aggregated metrics
1132
+ */
1133
+ getAggregatedMetrics(agentId, metricName, timeRange) {
1134
+ const records = this.getMetricRecords(agentId, metricName, timeRange);
1135
+ const values = records.map((r) => r.value).sort((a, b) => a - b);
1136
+ if (values.length === 0) {
1137
+ return {
1138
+ min: 0,
1139
+ max: 0,
1140
+ avg: 0,
1141
+ median: 0,
1142
+ p95: 0,
1143
+ p99: 0,
1144
+ count: 0
1145
+ };
1146
+ }
1147
+ return {
1148
+ min: values[0],
1149
+ max: values[values.length - 1],
1150
+ avg: this.calculateAverage(values),
1151
+ median: this.calculatePercentile(values, 50),
1152
+ p95: this.calculatePercentile(values, 95),
1153
+ p99: this.calculatePercentile(values, 99),
1154
+ count: values.length
1155
+ };
1156
+ }
1157
+ /**
1158
+ * Get task metrics
1159
+ */
1160
+ getTaskMetrics(agentId) {
1161
+ return this.taskMetrics.get(agentId);
1162
+ }
1163
+ /**
1164
+ * Get performance metrics
1165
+ */
1166
+ getPerformanceMetrics(agentId) {
1167
+ return this.performanceMetrics.get(agentId);
1168
+ }
1169
+ /**
1170
+ * Get all agents with metrics
1171
+ */
1172
+ getAllAgents() {
1173
+ return Array.from(this.metrics.keys());
1174
+ }
1175
+ /**
1176
+ * Clear metrics for an agent
1177
+ */
1178
+ clearAgentMetrics(agentId) {
1179
+ this.metrics.delete(agentId);
1180
+ this.taskMetrics.delete(agentId);
1181
+ this.performanceMetrics.delete(agentId);
1182
+ }
1183
+ /**
1184
+ * Clear all metrics
1185
+ */
1186
+ clearAll() {
1187
+ this.metrics.clear();
1188
+ this.taskMetrics.clear();
1189
+ this.performanceMetrics.clear();
1190
+ }
1191
+ /**
1192
+ * Export metrics to JSON
1193
+ */
1194
+ exportMetrics(agentId) {
1195
+ if (agentId) {
1196
+ return {
1197
+ agentId,
1198
+ metrics: this.getAgentMetrics(agentId),
1199
+ taskMetrics: this.getTaskMetrics(agentId),
1200
+ performanceMetrics: this.getPerformanceMetrics(agentId),
1201
+ timestamp: Date.now()
1202
+ };
1203
+ }
1204
+ const allMetrics = {};
1205
+ for (const id of this.getAllAgents()) {
1206
+ allMetrics[id] = {
1207
+ metrics: this.getAgentMetrics(id),
1208
+ taskMetrics: this.getTaskMetrics(id),
1209
+ performanceMetrics: this.getPerformanceMetrics(id)
1210
+ };
1211
+ }
1212
+ return {
1213
+ agents: allMetrics,
1214
+ timestamp: Date.now()
1215
+ };
1216
+ }
1217
+ /**
1218
+ * Get metric records
1219
+ */
1220
+ getMetricRecords(agentId, metricName, timeRange) {
1221
+ const agentMetrics = this.metrics.get(agentId);
1222
+ if (!agentMetrics) {
1223
+ return [];
1224
+ }
1225
+ const records = agentMetrics.get(metricName) ?? [];
1226
+ if (timeRange) {
1227
+ const cutoff = Date.now() - timeRange;
1228
+ return records.filter((r) => r.timestamp >= cutoff);
1229
+ }
1230
+ return records;
1231
+ }
1232
+ /**
1233
+ * Update performance metrics
1234
+ */
1235
+ updatePerformanceMetrics(agentId, update) {
1236
+ if (!this.performanceMetrics.has(agentId)) {
1237
+ this.performanceMetrics.set(agentId, {
1238
+ cpuUsage: 0,
1239
+ memoryUsage: 0,
1240
+ responseTime: 0,
1241
+ errorCount: 0,
1242
+ requestCount: 0,
1243
+ timestamp: Date.now()
1244
+ });
1245
+ }
1246
+ const metrics = this.performanceMetrics.get(agentId);
1247
+ if (update.cpuUsage !== void 0) {
1248
+ metrics.cpuUsage = update.cpuUsage;
1249
+ }
1250
+ if (update.memoryUsage !== void 0) {
1251
+ metrics.memoryUsage = update.memoryUsage;
1252
+ }
1253
+ if (update.responseTime !== void 0) {
1254
+ metrics.requestCount++;
1255
+ metrics.responseTime = (metrics.responseTime * (metrics.requestCount - 1) + update.responseTime) / metrics.requestCount;
1256
+ }
1257
+ if (update.errorCount !== void 0) {
1258
+ metrics.errorCount += update.errorCount;
1259
+ }
1260
+ metrics.timestamp = Date.now();
1261
+ }
1262
+ /**
1263
+ * Trim old records
1264
+ */
1265
+ trimRecords(records) {
1266
+ const cutoff = Date.now() - this.retentionPeriod;
1267
+ while (records.length > 0 && records[0].timestamp < cutoff) {
1268
+ records.shift();
1269
+ }
1270
+ while (records.length > this.maxRecords) {
1271
+ records.shift();
1272
+ }
1273
+ }
1274
+ /**
1275
+ * Calculate average
1276
+ */
1277
+ calculateAverage(values) {
1278
+ if (values.length === 0) {
1279
+ return 0;
1280
+ }
1281
+ return values.reduce((sum, val) => sum + val, 0) / values.length;
1282
+ }
1283
+ /**
1284
+ * Calculate percentile
1285
+ */
1286
+ calculatePercentile(sortedValues, percentile) {
1287
+ if (sortedValues.length === 0) {
1288
+ return 0;
1289
+ }
1290
+ const index = Math.ceil(percentile / 100 * sortedValues.length) - 1;
1291
+ return sortedValues[Math.max(0, index)];
1292
+ }
1293
+ }
1294
+ let globalMetricsCollector;
1295
+ function getMetricsCollector(options) {
1296
+ if (!globalMetricsCollector) {
1297
+ globalMetricsCollector = new MetricsCollector(options);
1298
+ }
1299
+ return globalMetricsCollector;
1300
+ }
1301
+
1302
+ const promptUserQuestion = async (question) => {
1303
+ if (!process__default.stdin.isTTY || !process__default.stdout.isTTY) {
1304
+ return null;
1305
+ }
1306
+ try {
1307
+ const inquirer = (await import('./index3.mjs').then(function (n) { return n.c; })).default;
1308
+ const choices = question.options.map((option) => ({
1309
+ name: option.description ? `${option.label} \u2014 ${option.description}` : option.label,
1310
+ value: option.value
1311
+ }));
1312
+ const defaultIndex = typeof question.defaultValue === "string" ? Math.max(0, choices.findIndex((choice) => choice.value === question.defaultValue)) : 0;
1313
+ const { selected } = await inquirer.prompt([
1314
+ {
1315
+ type: "list",
1316
+ name: "selected",
1317
+ message: question.prompt,
1318
+ choices,
1319
+ default: defaultIndex
1320
+ }
1321
+ ]);
1322
+ return {
1323
+ value: selected,
1324
+ source: "option"
1325
+ };
1326
+ } catch {
1327
+ return null;
1328
+ }
1329
+ };
1330
+
1331
+ const DEFAULT_PHASE_SUMMARY = {
1332
+ calls: 0,
1333
+ failures: 0,
1334
+ successRate: 0,
1335
+ avgDurationMs: 0
1336
+ };
1337
+ class ExecutionTelemetry {
1338
+ constructor(maxEvents = 2e3) {
1339
+ this.maxEvents = maxEvents;
1340
+ }
1341
+ events = [];
1342
+ record(event) {
1343
+ const entry = {
1344
+ id: `te-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1345
+ timestamp: Date.now(),
1346
+ ...event
1347
+ };
1348
+ this.events.push(entry);
1349
+ if (this.events.length > this.maxEvents) {
1350
+ this.events.shift();
1351
+ }
1352
+ return entry;
1353
+ }
1354
+ getRecent(limit = 50) {
1355
+ if (limit <= 0) {
1356
+ return [];
1357
+ }
1358
+ return this.events.slice(-limit);
1359
+ }
1360
+ summarize() {
1361
+ const phaseStats = {
1362
+ execution: { ...DEFAULT_PHASE_SUMMARY },
1363
+ intent: { ...DEFAULT_PHASE_SUMMARY },
1364
+ elicitation: { ...DEFAULT_PHASE_SUMMARY },
1365
+ skill: { ...DEFAULT_PHASE_SUMMARY },
1366
+ agent: { ...DEFAULT_PHASE_SUMMARY },
1367
+ mcp: { ...DEFAULT_PHASE_SUMMARY },
1368
+ route: { ...DEFAULT_PHASE_SUMMARY }
1369
+ };
1370
+ let totalSuccess = 0;
1371
+ let durationCount = 0;
1372
+ let durationTotal = 0;
1373
+ for (const event of this.events) {
1374
+ const summary = phaseStats[event.phase];
1375
+ summary.calls++;
1376
+ if (!event.success) {
1377
+ summary.failures++;
1378
+ } else {
1379
+ totalSuccess++;
1380
+ }
1381
+ if (typeof event.durationMs === "number") {
1382
+ durationTotal += event.durationMs;
1383
+ durationCount++;
1384
+ summary.avgDurationMs = (summary.avgDurationMs * (summary.calls - 1) + event.durationMs) / summary.calls;
1385
+ }
1386
+ summary.successRate = summary.calls === 0 ? 0 : (summary.calls - summary.failures) / summary.calls;
1387
+ }
1388
+ return {
1389
+ totalEvents: this.events.length,
1390
+ overallSuccessRate: this.events.length === 0 ? 0 : totalSuccess / this.events.length,
1391
+ avgDurationMs: durationCount === 0 ? 0 : durationTotal / durationCount,
1392
+ phaseStats
1393
+ };
1394
+ }
1395
+ clear() {
1396
+ this.events = [];
1397
+ }
1398
+ }
1399
+ let globalExecutionTelemetry = null;
1400
+ function getGlobalExecutionTelemetry() {
1401
+ if (!globalExecutionTelemetry) {
1402
+ globalExecutionTelemetry = new ExecutionTelemetry();
1403
+ }
1404
+ return globalExecutionTelemetry;
1405
+ }
1406
+
995
1407
  class IntentRouter extends EventEmitter {
996
1408
  config;
997
1409
  // Keywords for intent detection
@@ -1385,15 +1797,78 @@ function getGlobalIntentRouter(config) {
1385
1797
  return globalRouter$1;
1386
1798
  }
1387
1799
 
1800
+ const MCP_TOOL_PROFILES = [
1801
+ {
1802
+ tool: "filesystem",
1803
+ keywords: ["file", "directory", "folder", "workspace", "path", "read", "write"],
1804
+ basePriority: 5,
1805
+ intentBoost: {
1806
+ feature: 2,
1807
+ refactor: 2,
1808
+ bug_fix: 2
1809
+ }
1810
+ },
1811
+ {
1812
+ tool: "github",
1813
+ keywords: ["github", "repository", "repo", "pr", "pull request", "issue", "commit"],
1814
+ basePriority: 4,
1815
+ intentBoost: {
1816
+ feature: 1,
1817
+ bug_fix: 1
1818
+ }
1819
+ },
1820
+ {
1821
+ tool: "web-search",
1822
+ keywords: ["search", "research", "web", "documentation", "docs", "latest", "reference"],
1823
+ basePriority: 3,
1824
+ intentBoost: {
1825
+ question: 2,
1826
+ plan: 1
1827
+ }
1828
+ },
1829
+ {
1830
+ tool: "context7",
1831
+ keywords: ["library", "framework", "package", "sdk", "api docs", "best practice"],
1832
+ basePriority: 4,
1833
+ intentBoost: {
1834
+ feature: 2,
1835
+ plan: 2,
1836
+ question: 1
1837
+ }
1838
+ },
1839
+ {
1840
+ tool: "ide",
1841
+ keywords: ["diagnostic", "error", "lint", "typecheck", "compile", "warning"],
1842
+ basePriority: 3,
1843
+ intentBoost: {
1844
+ bug_fix: 2,
1845
+ refactor: 1
1846
+ }
1847
+ },
1848
+ {
1849
+ tool: "playwright",
1850
+ keywords: ["browser", "webpage", "e2e", "ui test", "automation", "screenshot"],
1851
+ basePriority: 2,
1852
+ intentBoost: {
1853
+ feature: 1,
1854
+ bug_fix: 1
1855
+ }
1856
+ }
1857
+ ];
1388
1858
  class AutoExecutor extends EventEmitter {
1389
1859
  config;
1390
- intentRouter = getGlobalIntentRouter();
1860
+ metricsCollector = getMetricsCollector();
1391
1861
  constructor(config = {}) {
1392
1862
  super();
1393
1863
  this.config = {
1394
1864
  autoCreateSkills: config.autoCreateSkills !== void 0 ? config.autoCreateSkills : true,
1395
1865
  autoCreateAgents: config.autoCreateAgents !== void 0 ? config.autoCreateAgents : true,
1396
1866
  autoSelectMcp: config.autoSelectMcp !== void 0 ? config.autoSelectMcp : true,
1867
+ enableElicitation: config.enableElicitation !== void 0 ? config.enableElicitation : true,
1868
+ maxMcpTools: config.maxMcpTools !== void 0 ? Math.max(1, config.maxMcpTools) : 3,
1869
+ askUserQuestion: config.askUserQuestion || promptUserQuestion,
1870
+ intentRouter: config.intentRouter || getGlobalIntentRouter(),
1871
+ telemetry: config.telemetry || getGlobalExecutionTelemetry(),
1397
1872
  verbose: config.verbose !== void 0 ? config.verbose : false
1398
1873
  };
1399
1874
  }
@@ -1401,36 +1876,141 @@ class AutoExecutor extends EventEmitter {
1401
1876
  * Execute user request automatically
1402
1877
  */
1403
1878
  async execute(userInput) {
1879
+ const executionId = `exec-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1880
+ const startedAt = Date.now();
1404
1881
  this.emit("execution:started", { input: userInput });
1882
+ this.config.telemetry.record({
1883
+ executionId,
1884
+ phase: "execution",
1885
+ action: "start",
1886
+ success: true,
1887
+ metadata: {
1888
+ inputLength: userInput.length
1889
+ }
1890
+ });
1405
1891
  try {
1406
- const routeResult = await this.intentRouter.route(userInput);
1407
- const { route, intent } = routeResult;
1892
+ const routeStart = Date.now();
1893
+ const routeResult = await this.config.intentRouter.route(userInput);
1894
+ this.config.telemetry.record({
1895
+ executionId,
1896
+ phase: "intent",
1897
+ action: "route",
1898
+ success: true,
1899
+ durationMs: Date.now() - routeStart,
1900
+ metadata: {
1901
+ initialRoute: routeResult.route,
1902
+ confidence: routeResult.intent.confidence,
1903
+ intentType: routeResult.intent.type,
1904
+ complexity: routeResult.intent.complexity
1905
+ }
1906
+ });
1907
+ const elicitationResult = await this.resolveRouteWithElicitation(
1908
+ routeResult.route,
1909
+ routeResult.intent,
1910
+ executionId
1911
+ );
1912
+ const route = elicitationResult.route;
1913
+ const intent = elicitationResult.intent;
1408
1914
  this.log(`Intent analyzed: ${intent.type} (${intent.complexity})`);
1409
1915
  this.log(`Suggested route: ${route}`);
1916
+ const skillDetectStart = Date.now();
1410
1917
  const skillReq = await this.detectSkillRequirement(userInput, intent);
1918
+ this.config.telemetry.record({
1919
+ executionId,
1920
+ phase: "skill",
1921
+ action: "detect",
1922
+ success: true,
1923
+ durationMs: Date.now() - skillDetectStart,
1924
+ metadata: {
1925
+ needed: skillReq.needed,
1926
+ reason: skillReq.reason
1927
+ }
1928
+ });
1929
+ const agentDetectStart = Date.now();
1411
1930
  const agentReq = await this.detectAgentRequirement(userInput, intent);
1931
+ this.config.telemetry.record({
1932
+ executionId,
1933
+ phase: "agent",
1934
+ action: "detect",
1935
+ success: true,
1936
+ durationMs: Date.now() - agentDetectStart,
1937
+ metadata: {
1938
+ needed: agentReq.needed,
1939
+ reason: agentReq.reason
1940
+ }
1941
+ });
1942
+ const mcpDetectStart = Date.now();
1412
1943
  const mcpReq = await this.detectMcpRequirement(userInput, intent);
1944
+ this.config.telemetry.record({
1945
+ executionId,
1946
+ phase: "mcp",
1947
+ action: "detect",
1948
+ success: true,
1949
+ durationMs: Date.now() - mcpDetectStart,
1950
+ metadata: {
1951
+ needed: mcpReq.needed,
1952
+ selectedTools: mcpReq.tools,
1953
+ candidates: mcpReq.candidates,
1954
+ reason: mcpReq.reason
1955
+ }
1956
+ });
1413
1957
  const agentsCreated = [];
1414
1958
  const skillsCreated = [];
1415
1959
  const mcpToolsUsed = [];
1416
1960
  if (this.config.autoCreateSkills && skillReq.needed) {
1417
1961
  this.log(`Auto-creating skill: ${skillReq.skillName}`);
1962
+ const skillCreateStart = Date.now();
1418
1963
  const skillId = await this.autoCreateSkill(skillReq);
1419
1964
  skillsCreated.push(skillId);
1965
+ this.config.telemetry.record({
1966
+ executionId,
1967
+ phase: "skill",
1968
+ action: "create",
1969
+ success: true,
1970
+ durationMs: Date.now() - skillCreateStart,
1971
+ metadata: {
1972
+ skillId,
1973
+ skillName: skillReq.skillName
1974
+ }
1975
+ });
1420
1976
  this.emit("skill:created", { skillId, skillReq });
1421
1977
  }
1422
1978
  if (this.config.autoCreateAgents && agentReq.needed) {
1423
1979
  this.log(`Auto-creating agent: ${agentReq.domain}`);
1980
+ const agentCreateStart = Date.now();
1424
1981
  const agentId = await this.autoCreateAgent(agentReq);
1425
1982
  agentsCreated.push(agentId);
1983
+ this.config.telemetry.record({
1984
+ executionId,
1985
+ phase: "agent",
1986
+ action: "create",
1987
+ success: true,
1988
+ durationMs: Date.now() - agentCreateStart,
1989
+ metadata: {
1990
+ agentId,
1991
+ agentType: agentReq.agentType,
1992
+ domain: agentReq.domain
1993
+ }
1994
+ });
1426
1995
  this.emit("agent:created", { agentId, agentReq });
1427
1996
  }
1428
1997
  if (this.config.autoSelectMcp && mcpReq.needed) {
1429
1998
  this.log(`Auto-selecting MCP tools: ${mcpReq.tools.join(", ")}`);
1430
1999
  mcpToolsUsed.push(...mcpReq.tools);
2000
+ this.config.telemetry.record({
2001
+ executionId,
2002
+ phase: "mcp",
2003
+ action: "select",
2004
+ success: true,
2005
+ metadata: {
2006
+ tools: mcpReq.tools,
2007
+ candidates: mcpReq.candidates
2008
+ }
2009
+ });
1431
2010
  this.emit("mcp:selected", { tools: mcpReq.tools, mcpReq });
1432
2011
  }
1433
2012
  let result;
2013
+ const routeExecutionStart = Date.now();
1434
2014
  switch (route) {
1435
2015
  case "mayor":
1436
2016
  result = await this.executeMayor(userInput, intent, agentsCreated, skillsCreated, mcpToolsUsed);
@@ -1447,13 +2027,174 @@ class AutoExecutor extends EventEmitter {
1447
2027
  default:
1448
2028
  throw new Error(`Unknown route: ${route}`);
1449
2029
  }
2030
+ const routeDuration = Date.now() - routeExecutionStart;
2031
+ this.config.telemetry.record({
2032
+ executionId,
2033
+ phase: "route",
2034
+ action: route,
2035
+ success: true,
2036
+ durationMs: routeDuration,
2037
+ metadata: {
2038
+ intentType: intent.type,
2039
+ complexity: intent.complexity
2040
+ }
2041
+ });
2042
+ const totalDuration = Date.now() - startedAt;
2043
+ this.metricsCollector.recordResponseTime("auto-executor", totalDuration);
2044
+ this.metricsCollector.recordTaskCompletion("auto-executor", true, totalDuration);
2045
+ this.config.telemetry.record({
2046
+ executionId,
2047
+ phase: "execution",
2048
+ action: "complete",
2049
+ success: true,
2050
+ durationMs: totalDuration,
2051
+ metadata: {
2052
+ route,
2053
+ agentsCreated: agentsCreated.length,
2054
+ skillsCreated: skillsCreated.length,
2055
+ mcpToolsUsed: mcpToolsUsed.length
2056
+ }
2057
+ });
2058
+ result.insights = this.buildExecutionInsights({
2059
+ initialRoute: routeResult.route,
2060
+ resolvedRoute: route,
2061
+ elicitationAsked: elicitationResult.elicitationAsked,
2062
+ userSelectedRoute: elicitationResult.userSelectedRoute,
2063
+ mcpReq,
2064
+ totalDurationMs: totalDuration,
2065
+ executionId
2066
+ });
1450
2067
  this.emit("execution:completed", result);
1451
2068
  return result;
1452
2069
  } catch (error) {
2070
+ const totalDuration = Date.now() - startedAt;
2071
+ const errorMessage = this.getErrorMessage(error);
2072
+ this.metricsCollector.recordResponseTime("auto-executor", totalDuration);
2073
+ this.metricsCollector.recordTaskCompletion("auto-executor", false, totalDuration);
2074
+ this.metricsCollector.recordError("auto-executor", "execution_error", errorMessage);
2075
+ this.config.telemetry.record({
2076
+ executionId,
2077
+ phase: "execution",
2078
+ action: "complete",
2079
+ success: false,
2080
+ durationMs: totalDuration,
2081
+ metadata: {
2082
+ error: errorMessage
2083
+ }
2084
+ });
1453
2085
  this.emit("execution:failed", { error, input: userInput });
1454
2086
  throw error;
1455
2087
  }
1456
2088
  }
2089
+ /**
2090
+ * Resolve route with optional structured elicitation.
2091
+ * This keeps model autonomy but lets users disambiguate complex intent.
2092
+ */
2093
+ async resolveRouteWithElicitation(suggestedRoute, intent, executionId) {
2094
+ if (!this.config.enableElicitation || !this.shouldAskRouteQuestion(intent)) {
2095
+ return {
2096
+ route: suggestedRoute,
2097
+ intent,
2098
+ elicitationAsked: false,
2099
+ userSelectedRoute: false
2100
+ };
2101
+ }
2102
+ const question = this.buildRouteQuestion(suggestedRoute, intent);
2103
+ const askStart = Date.now();
2104
+ const answer = await this.config.askUserQuestion(question);
2105
+ this.config.telemetry.record({
2106
+ executionId,
2107
+ phase: "elicitation",
2108
+ action: "route-choice",
2109
+ success: true,
2110
+ durationMs: Date.now() - askStart,
2111
+ metadata: {
2112
+ asked: true,
2113
+ suggestedRoute,
2114
+ answered: Boolean(answer),
2115
+ selected: answer?.value
2116
+ }
2117
+ });
2118
+ if (!answer) {
2119
+ return {
2120
+ route: suggestedRoute,
2121
+ intent,
2122
+ elicitationAsked: true,
2123
+ userSelectedRoute: false
2124
+ };
2125
+ }
2126
+ return this.applyRouteAnswer(suggestedRoute, intent, answer);
2127
+ }
2128
+ shouldAskRouteQuestion(intent) {
2129
+ if (intent.complexity === "trivial" || intent.complexity === "simple") {
2130
+ return false;
2131
+ }
2132
+ const lowConfidence = intent.confidence < 0.65;
2133
+ const multiRouteIndicators = intent.requiresPlanning && intent.requiresMultipleAgents;
2134
+ return lowConfidence || multiRouteIndicators;
2135
+ }
2136
+ buildRouteQuestion(suggestedRoute, intent) {
2137
+ const routeLabels = {
2138
+ direct: "Direct execution",
2139
+ feature: "Feature implementation",
2140
+ plan: "Plan first",
2141
+ mayor: "Multi-agent orchestration"
2142
+ };
2143
+ const options = [
2144
+ {
2145
+ value: suggestedRoute,
2146
+ label: `Use recommended: ${routeLabels[suggestedRoute]}`,
2147
+ description: `Best guess from intent analysis (confidence ${Math.round(intent.confidence * 100)}%)`
2148
+ },
2149
+ {
2150
+ value: "plan",
2151
+ label: routeLabels.plan,
2152
+ description: "Start with architecture and implementation plan"
2153
+ },
2154
+ {
2155
+ value: "feature",
2156
+ label: routeLabels.feature,
2157
+ description: "Implement directly with focused feature workflow"
2158
+ },
2159
+ {
2160
+ value: "direct",
2161
+ label: routeLabels.direct,
2162
+ description: "Run quickly without extra orchestration"
2163
+ },
2164
+ {
2165
+ value: "mayor",
2166
+ label: routeLabels.mayor,
2167
+ description: "Use specialized agents for decomposition and coordination"
2168
+ }
2169
+ ].filter((option, index, arr) => arr.findIndex((x) => x.value === option.value) === index);
2170
+ return {
2171
+ id: "execution-route-choice",
2172
+ prompt: "How should I execute this request?",
2173
+ options,
2174
+ defaultValue: suggestedRoute
2175
+ };
2176
+ }
2177
+ applyRouteAnswer(suggestedRoute, intent, answer) {
2178
+ const selectedRoute = ["direct", "feature", "plan", "mayor"].includes(answer.value) ? answer.value : suggestedRoute;
2179
+ if (selectedRoute === suggestedRoute) {
2180
+ return {
2181
+ route: suggestedRoute,
2182
+ intent,
2183
+ elicitationAsked: true,
2184
+ userSelectedRoute: false
2185
+ };
2186
+ }
2187
+ return {
2188
+ route: selectedRoute,
2189
+ intent: {
2190
+ ...intent,
2191
+ suggestedRoute: selectedRoute,
2192
+ reasoning: `${intent.reasoning} \u2022 User selected route: ${selectedRoute}`
2193
+ },
2194
+ elicitationAsked: true,
2195
+ userSelectedRoute: true
2196
+ };
2197
+ }
1457
2198
  /**
1458
2199
  * Detect if a new skill is needed
1459
2200
  */
@@ -1576,31 +2317,28 @@ class AutoExecutor extends EventEmitter {
1576
2317
  /**
1577
2318
  * Detect which MCP tools are needed
1578
2319
  */
1579
- async detectMcpRequirement(input, _intent) {
2320
+ async detectMcpRequirement(input, intent) {
1580
2321
  const normalized = input.toLowerCase();
1581
- const tools = [];
1582
- if (normalized.includes("file") || normalized.includes("directory") || normalized.includes("folder")) {
1583
- tools.push("filesystem");
1584
- }
1585
- if (normalized.includes("github") || normalized.includes("repository") || normalized.includes("pr")) {
1586
- tools.push("github");
1587
- }
1588
- if (normalized.includes("search") || normalized.includes("documentation") || normalized.includes("docs")) {
1589
- tools.push("web-search");
1590
- }
1591
- if (normalized.includes("browser") || normalized.includes("webpage") || normalized.includes("ui test")) {
1592
- tools.push("playwright");
1593
- }
1594
- if (normalized.includes("library") || normalized.includes("framework") || normalized.includes("package")) {
1595
- tools.push("context7");
1596
- }
1597
- if (normalized.includes("diagnostic") || normalized.includes("error") || normalized.includes("lint")) {
1598
- tools.push("ide");
1599
- }
2322
+ const scoredTools = MCP_TOOL_PROFILES.map((profile) => {
2323
+ const matchedKeywords = profile.keywords.filter((keyword) => normalized.includes(keyword));
2324
+ if (matchedKeywords.length === 0) {
2325
+ return null;
2326
+ }
2327
+ const intentBoost = profile.intentBoost?.[intent.type] ?? 0;
2328
+ const complexityBoost = intent.complexity === "complex" || intent.complexity === "very_complex" ? 1 : 0;
2329
+ const score = profile.basePriority + matchedKeywords.length * 2 + intentBoost + complexityBoost;
2330
+ return {
2331
+ tool: profile.tool,
2332
+ score
2333
+ };
2334
+ }).filter((item) => item !== null).sort((a, b) => b.score - a.score);
2335
+ const candidates = scoredTools.map((item) => item.tool);
2336
+ const tools = scoredTools.slice(0, this.config.maxMcpTools).map((item) => item.tool);
1600
2337
  return {
1601
2338
  needed: tools.length > 0,
1602
2339
  tools,
1603
- reason: tools.length > 0 ? `Requires MCP tools: ${tools.join(", ")}` : "No MCP tools needed"
2340
+ candidates,
2341
+ reason: tools.length > 0 ? candidates.length > tools.length ? `Selected top ${tools.length}/${candidates.length} MCP tools by capability score: ${tools.join(", ")}` : `Requires MCP tools: ${tools.join(", ")}` : "No MCP tools needed"
1604
2342
  };
1605
2343
  }
1606
2344
  /**
@@ -1778,6 +2516,48 @@ class AutoExecutor extends EventEmitter {
1778
2516
  details: { input }
1779
2517
  };
1780
2518
  }
2519
+ buildExecutionInsights(options) {
2520
+ return {
2521
+ decisionProfile: options.userSelectedRoute ? "user_guided" : "automatic",
2522
+ routeDecision: {
2523
+ initial: options.initialRoute,
2524
+ final: options.resolvedRoute,
2525
+ elicitationAsked: options.elicitationAsked,
2526
+ userSelectedRoute: options.userSelectedRoute
2527
+ },
2528
+ mcpSelection: {
2529
+ selected: options.mcpReq.tools,
2530
+ candidates: options.mcpReq.candidates,
2531
+ truncated: options.mcpReq.candidates.length > options.mcpReq.tools.length,
2532
+ reason: options.mcpReq.reason
2533
+ },
2534
+ telemetry: {
2535
+ totalDurationMs: options.totalDurationMs,
2536
+ eventCount: this.getExecutionTelemetryEventCount(options.executionId)
2537
+ }
2538
+ };
2539
+ }
2540
+ getExecutionTelemetryEventCount(executionId) {
2541
+ return this.config.telemetry.getRecent(500).filter((event) => event.executionId === executionId).length;
2542
+ }
2543
+ /**
2544
+ * Get aggregated execution telemetry.
2545
+ */
2546
+ getTelemetrySummary() {
2547
+ return this.config.telemetry.summarize();
2548
+ }
2549
+ /**
2550
+ * Get recent execution telemetry events.
2551
+ */
2552
+ getTelemetryEvents(limit = 50) {
2553
+ return this.config.telemetry.getRecent(limit);
2554
+ }
2555
+ getErrorMessage(error) {
2556
+ if (error instanceof Error) {
2557
+ return error.message;
2558
+ }
2559
+ return String(error);
2560
+ }
1781
2561
  /**
1782
2562
  * Log message if verbose
1783
2563
  */
@@ -1960,6 +2740,7 @@ class CliInterceptor extends EventEmitter {
1960
2740
  showIntentMessage(_input) {
1961
2741
  console.log("\n\u{1F9E0} Analyzing your request...");
1962
2742
  console.log(" System will automatically handle: skills, agents, MCP tools\n");
2743
+ console.log(" Smart mode: ambiguity checks + capability-ranked tool selection + telemetry\n");
1963
2744
  }
1964
2745
  /**
1965
2746
  * Enable interceptor
@@ -2223,6 +3004,27 @@ ${"=".repeat(60)}`);
2223
3004
  }
2224
3005
  console.log();
2225
3006
  }
3007
+ if (result.insights) {
3008
+ console.log("\u2728 Smart Upgrade Signals:");
3009
+ console.log(` Route decision: ${result.insights.routeDecision.initial} \u2192 ${result.insights.routeDecision.final}`);
3010
+ if (result.insights.routeDecision.userSelectedRoute) {
3011
+ console.log(" Mode: User-guided route disambiguation");
3012
+ } else if (result.insights.routeDecision.elicitationAsked) {
3013
+ console.log(" Mode: Asked for route preference (kept recommended)");
3014
+ } else {
3015
+ console.log(" Mode: Fully automatic route decision");
3016
+ }
3017
+ if (result.insights.mcpSelection.selected.length > 0) {
3018
+ if (result.insights.mcpSelection.truncated) {
3019
+ console.log(` MCP ranking: selected ${result.insights.mcpSelection.selected.length} of ${result.insights.mcpSelection.candidates.length} candidates`);
3020
+ }
3021
+ console.log(` MCP reason: ${result.insights.mcpSelection.reason}`);
3022
+ } else {
3023
+ console.log(" MCP reason: no external tools needed");
3024
+ }
3025
+ console.log(` Telemetry: ${result.insights.telemetry.eventCount} events, ${result.insights.telemetry.totalDurationMs}ms`);
3026
+ console.log();
3027
+ }
2226
3028
  if (result.convoyId) {
2227
3029
  console.log(`\u{1F4E6} Convoy: ${result.convoyId}`);
2228
3030
  console.log();
@@ -1,3 +1,3 @@
1
- const version = "12.2.0";
1
+ const version = "12.2.1";
2
2
 
3
3
  export { version };
package/dist/cli.mjs CHANGED
File without changes
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "ccjk",
3
3
  "type": "module",
4
- "version": "12.2.0",
4
+ "version": "12.2.1",
5
+ "packageManager": "pnpm@10.17.1",
5
6
  "description": "CLI toolkit for Claude Code and Codex setup. Simplifies MCP service installation, API configuration, workflow management, and multi-provider support with guided interactive setup.",
6
7
  "author": {
7
8
  "name": "CCJK Team",
@@ -80,66 +81,6 @@
80
81
  "engines": {
81
82
  "node": ">=20"
82
83
  },
83
- "dependencies": {
84
- "fdir": "^6.5.0",
85
- "globby": "^14.1.0",
86
- "ioredis": "^5.9.3",
87
- "tar": "^7.5.9",
88
- "tinyglobby": "^0.2.15",
89
- "web-tree-sitter": "^0.26.5",
90
- "better-sqlite3": "^12.6.2"
91
- },
92
- "devDependencies": {
93
- "@antfu/eslint-config": "^5.4.1",
94
- "@types/better-sqlite3": "^7.6.13",
95
- "@types/fs-extra": "^11.0.4",
96
- "@types/inquirer": "^9.0.9",
97
- "@types/node": "^22.18.6",
98
- "@types/semver": "^7.7.1",
99
- "@types/uuid": "^11.0.0",
100
- "@typescript-eslint/eslint-plugin": "^6.0.0",
101
- "@typescript-eslint/parser": "^6.0.0",
102
- "@vitest/coverage-v8": "^3.2.4",
103
- "@vitest/ui": "^3.2.4",
104
- "concurrently": "^9.2.1",
105
- "eslint": "^9.36.0",
106
- "eslint-plugin-format": "^1.4.0",
107
- "husky": "^9.1.7",
108
- "lint-staged": "^16.2.7",
109
- "pkgroll": "^2.26.3",
110
- "prettier": "^3.8.1",
111
- "shx": "^0.4.0",
112
- "tsx": "^4.21.0",
113
- "typescript": "^5.9.3",
114
- "unbuild": "^3.6.1",
115
- "vitest": "^3.2.4",
116
- "@anthropic-ai/sdk": "^0.52.0",
117
- "ansis": "^4.2.0",
118
- "cac": "^6.7.14",
119
- "chokidar": "^4.0.3",
120
- "consola": "^3.4.2",
121
- "dayjs": "^1.11.19",
122
- "find-up-simple": "^1.0.1",
123
- "fs-extra": "^11.3.3",
124
- "gray-matter": "^4.0.3",
125
- "handlebars": "^4.7.8",
126
- "i18next": "^25.8.13",
127
- "i18next-fs-backend": "^2.6.1",
128
- "inquirer": "^12.9.6",
129
- "inquirer-toggle": "^1.0.1",
130
- "lowdb": "^7.0.1",
131
- "nanoid": "^5.1.6",
132
- "ofetch": "^1.5.1",
133
- "ohash": "^1.1.4",
134
- "ora": "^8.2.0",
135
- "pathe": "^2.0.3",
136
- "semver": "^7.7.4",
137
- "smol-toml": "^1.6.0",
138
- "tinyexec": "^1.0.2",
139
- "trash": "^10.1.0",
140
- "tweetnacl": "^1.0.3",
141
- "uuid": "^11.1.0"
142
- },
143
84
  "scripts": {
144
85
  "dev": "tsx ./src/cli.ts",
145
86
  "build": "unbuild",
@@ -147,6 +88,7 @@
147
88
  "typecheck": "tsc --noEmit",
148
89
  "release:verify": "node scripts/release-verify.mjs",
149
90
  "release:verify:full": "node scripts/release-verify.mjs --with-tests",
91
+ "prepublishOnly": "node scripts/validate-prepublish.mjs && pnpm contract:check && pnpm build && pnpm test:run",
150
92
  "lint": "eslint",
151
93
  "lint:fix": "eslint --fix",
152
94
  "test": "vitest",
@@ -168,6 +110,7 @@
168
110
  "test:integration:run": "NODE_ENV=test vitest run --config vitest.integration.config.ts",
169
111
  "test:integration:ui": "NODE_ENV=test vitest --config vitest.integration.config.ts --ui",
170
112
  "test:integration:coverage": "NODE_ENV=test vitest run --config vitest.integration.config.ts --coverage",
113
+ "prepare": "husky",
171
114
  "format": "prettier --write src/**/*.ts",
172
115
  "prepublish:fix": "node scripts/fix-package-catalog.mjs",
173
116
  "cleanup": "node scripts/cleanup.js",
@@ -202,5 +145,65 @@
202
145
  "i18n:check": "tsx scripts/check-i18n.ts",
203
146
  "i18n:report": "tsx scripts/check-i18n.ts --report",
204
147
  "contract:check": "node scripts/check-remote-contract.mjs"
148
+ },
149
+ "dependencies": {
150
+ "fdir": "^6.5.0",
151
+ "globby": "^14.1.0",
152
+ "ioredis": "^5.9.3",
153
+ "tar": "^7.5.9",
154
+ "tinyglobby": "^0.2.15",
155
+ "web-tree-sitter": "^0.26.5",
156
+ "better-sqlite3": "^12.6.2"
157
+ },
158
+ "devDependencies": {
159
+ "@antfu/eslint-config": "^5.4.1",
160
+ "@types/better-sqlite3": "^7.6.13",
161
+ "@types/fs-extra": "^11.0.4",
162
+ "@types/inquirer": "^9.0.9",
163
+ "@types/node": "^22.18.6",
164
+ "@types/semver": "^7.7.1",
165
+ "@types/uuid": "^11.0.0",
166
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
167
+ "@typescript-eslint/parser": "^6.0.0",
168
+ "@vitest/coverage-v8": "^3.2.4",
169
+ "@vitest/ui": "^3.2.4",
170
+ "concurrently": "^9.2.1",
171
+ "eslint": "^9.36.0",
172
+ "eslint-plugin-format": "^1.4.0",
173
+ "husky": "^9.1.7",
174
+ "lint-staged": "^16.2.7",
175
+ "pkgroll": "^2.26.3",
176
+ "prettier": "^3.8.1",
177
+ "shx": "^0.4.0",
178
+ "tsx": "^4.21.0",
179
+ "typescript": "^5.9.3",
180
+ "unbuild": "^3.6.1",
181
+ "vitest": "^3.2.4",
182
+ "@anthropic-ai/sdk": "^0.52.0",
183
+ "ansis": "^4.2.0",
184
+ "cac": "^6.7.14",
185
+ "chokidar": "^4.0.3",
186
+ "consola": "^3.4.2",
187
+ "dayjs": "^1.11.19",
188
+ "find-up-simple": "^1.0.1",
189
+ "fs-extra": "^11.3.3",
190
+ "gray-matter": "^4.0.3",
191
+ "handlebars": "^4.7.8",
192
+ "i18next": "^25.8.13",
193
+ "i18next-fs-backend": "^2.6.1",
194
+ "inquirer": "^12.9.6",
195
+ "inquirer-toggle": "^1.0.1",
196
+ "lowdb": "^7.0.1",
197
+ "nanoid": "^5.1.6",
198
+ "ofetch": "^1.5.1",
199
+ "ohash": "^1.1.4",
200
+ "ora": "^8.2.0",
201
+ "pathe": "^2.0.3",
202
+ "semver": "^7.7.4",
203
+ "smol-toml": "^1.6.0",
204
+ "tinyexec": "^1.0.2",
205
+ "trash": "^10.1.0",
206
+ "tweetnacl": "^1.0.3",
207
+ "uuid": "^11.1.0"
205
208
  }
206
- }
209
+ }