ccjk 12.0.9 → 12.0.11

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 (34) hide show
  1. package/dist/chunks/agents.mjs +9 -3
  2. package/dist/chunks/auto-bootstrap.mjs +1 -1
  3. package/dist/chunks/boost.mjs +15 -8
  4. package/dist/chunks/ccjk-agents.mjs +8 -5
  5. package/dist/chunks/ccjk-all.mjs +1 -1
  6. package/dist/chunks/ccjk-skills.mjs +2 -2
  7. package/dist/chunks/cli-hook.mjs +5 -3
  8. package/dist/chunks/constants.mjs +1 -1
  9. package/dist/chunks/context-loader.mjs +9 -1
  10. package/dist/chunks/convoy-manager.mjs +108 -3
  11. package/dist/chunks/mcp.mjs +3 -3
  12. package/dist/chunks/onboarding-wizard.mjs +51 -25
  13. package/dist/chunks/package.mjs +1 -1
  14. package/dist/chunks/plugin.mjs +1 -1
  15. package/dist/chunks/skills-sync.mjs +1 -1
  16. package/dist/chunks/status.mjs +33 -0
  17. package/dist/index.d.mts +10 -0
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.mjs +2 -2
  20. package/dist/shared/{ccjk.B364Fu0N.mjs → ccjk.CtXhbEqb.mjs} +24 -3
  21. package/dist/templates/agents/fullstack-developer.json +70 -0
  22. package/dist/templates/agents/go-expert.json +69 -0
  23. package/dist/templates/agents/index.json +64 -0
  24. package/dist/templates/agents/python-expert.json +69 -0
  25. package/dist/templates/agents/react-specialist.json +69 -0
  26. package/dist/templates/agents/testing-automation-expert.json +70 -0
  27. package/dist/templates/agents/typescript-architect.json +69 -0
  28. package/dist/templates/claude-code/common/settings.json +107 -0
  29. package/dist/templates/hooks/post-test/coverage.json +21 -0
  30. package/dist/templates/hooks/post-test/summary.json +21 -0
  31. package/dist/templates/hooks/pre-commit/eslint.json +22 -0
  32. package/dist/templates/hooks/pre-commit/prettier.json +22 -0
  33. package/dist/templates/skills/index.json +132 -0
  34. package/package.json +1 -1
@@ -6,7 +6,7 @@ import { c as resolve } from '../shared/ccjk.bQ7Dh1g4.mjs';
6
6
  import { e as executionTracer } from '../shared/ccjk.CePkJq2S.mjs';
7
7
  import { t as taskPersistence } from '../shared/ccjk.BFxsJM0k.mjs';
8
8
  import { contextLoader } from './context-loader.mjs';
9
- import { g as getGlobalConvoyManager } from './convoy-manager.mjs';
9
+ import { S as SessionIntelligence, g as getGlobalConvoyManager } from './convoy-manager.mjs';
10
10
  import '../shared/ccjk.BAGoDD49.mjs';
11
11
  import 'node:process';
12
12
  import '../shared/ccjk.Cjgrln_h.mjs';
@@ -16,11 +16,12 @@ import 'better-sqlite3';
16
16
  import 'node:fs';
17
17
  import 'tinyglobby';
18
18
  import '../shared/ccjk.BxSmJ8B7.mjs';
19
+ import 'node:child_process';
20
+ import 'node:fs/promises';
19
21
  import 'node:os';
22
+ import 'node:path';
20
23
  import './main.mjs';
21
24
  import 'module';
22
- import 'node:child_process';
23
- import 'node:path';
24
25
  import 'node:stream';
25
26
  import 'node:readline';
26
27
 
@@ -2675,18 +2676,23 @@ class BrainOrchestrator extends EventEmitter {
2675
2676
  task.metadata.custom = {};
2676
2677
  }
2677
2678
  task.metadata.custom.context = contextLoader.formatForLLM(context);
2679
+ const intel = SessionIntelligence.getInstance();
2680
+ intel.recordMessage("user", task.name);
2678
2681
  try {
2679
2682
  this.state.status = "planning";
2683
+ intel.updatePhase("exploring");
2680
2684
  this.log(`Starting orchestration for task: ${task.name}`);
2681
2685
  executionTracer.logDecision("orchestrator", `Planning task: ${task.name}`);
2682
2686
  const plan = await this.createPlan(task, strategy);
2683
2687
  this.emit("plan:created", plan);
2684
2688
  this.state.status = "executing";
2689
+ intel.updatePhase("executing");
2685
2690
  this.state.currentPlan = plan;
2686
2691
  this.state.startTime = (/* @__PURE__ */ new Date()).toISOString();
2687
2692
  this.emit("plan:started", plan.id);
2688
2693
  const result = await this.executePlan(plan);
2689
2694
  this.state.status = "idle";
2695
+ intel.updatePhase("reviewing");
2690
2696
  this.emit("plan:completed", result);
2691
2697
  executionTracer.logAgentEnd("orchestrator", { success: true });
2692
2698
  executionTracer.endSession(sessionId);
@@ -12,7 +12,7 @@ const __dirname = dirname(__filename);
12
12
  const CLOUD_CONFIG_DIR = join(CCJK_CONFIG_DIR, "cloud");
13
13
  const DEVICE_CONFIG_FILE = join(CLOUD_CONFIG_DIR, "device.json");
14
14
  const CLOUD_STATE_FILE = join(CLOUD_CONFIG_DIR, "state.json");
15
- const CLOUD_API_ENDPOINT = "https://api.api.claudehome.cn/v1";
15
+ const CLOUD_API_ENDPOINT = "https://api.claudehome.cn/api/v1";
16
16
  const AUTO_SYNC_INTERVAL = 30 * 60 * 1e3;
17
17
  const AUTO_UPGRADE_CHECK_INTERVAL = 6 * 60 * 60 * 1e3;
18
18
  function generateDeviceFingerprint() {
@@ -343,23 +343,30 @@ async function boost(options = {}) {
343
343
  console.log(a.gray("\n--dry-run: No changes applied.\n"));
344
344
  return;
345
345
  }
346
+ let selectedActions = actions;
346
347
  if (!options.yes) {
347
348
  const { default: inquirer } = await import('./index3.mjs').then(function (n) { return n.c; });
348
- const { confirm } = await inquirer.prompt([{
349
- type: "confirm",
350
- name: "confirm",
351
- message: `Apply ${actions.length} optimization${actions.length > 1 ? "s" : ""}?`,
352
- default: true
349
+ const { selected } = await inquirer.prompt([{
350
+ type: "checkbox",
351
+ name: "selected",
352
+ message: "Select optimizations to apply:",
353
+ choices: actions.map((a, i) => ({
354
+ name: `${a.rec.priority === "high" ? "[HIGH] " : "[MED] "}${a.label}`,
355
+ value: i,
356
+ checked: a.rec.priority === "high"
357
+ // pre-check high priority
358
+ }))
353
359
  }]);
354
- if (!confirm) {
355
- console.log(a.gray("\nCancelled.\n"));
360
+ if (!selected.length) {
361
+ console.log(a.gray("\nNothing selected. Cancelled.\n"));
356
362
  return;
357
363
  }
364
+ selectedActions = selected.map((i) => actions[i]);
358
365
  }
359
366
  console.log("");
360
367
  let applied = 0;
361
368
  let failed = 0;
362
- for (const action of actions) {
369
+ for (const action of selectedActions) {
363
370
  spinner = ora(action.label).start();
364
371
  try {
365
372
  const result = await executeRecommendation(action.rec);
@@ -84,17 +84,19 @@ function validateAgentDefinition(agent) {
84
84
 
85
85
  const _dirname = dirname(fileURLToPath(import.meta.url));
86
86
  const AGENT_TEMPLATES_DIR = join(_dirname, "..", "templates", "agents");
87
- const AGENT_TEMPLATES_DIR_FALLBACK = join(process.cwd(), "templates", "agents");
87
+ const AGENT_TEMPLATES_DIR_DEV = join(_dirname, "..", "..", "templates", "agents");
88
88
  function getAgentTemplatesDir() {
89
89
  if (existsSync(AGENT_TEMPLATES_DIR)) {
90
90
  return AGENT_TEMPLATES_DIR;
91
91
  }
92
- return AGENT_TEMPLATES_DIR_FALLBACK;
92
+ if (existsSync(AGENT_TEMPLATES_DIR_DEV)) {
93
+ return AGENT_TEMPLATES_DIR_DEV;
94
+ }
95
+ return join(process.cwd(), "templates", "agents");
93
96
  }
94
97
  async function loadAgentTemplates() {
95
98
  const templatesDir = getAgentTemplatesDir();
96
99
  if (!existsSync(templatesDir)) {
97
- console.warn("Agent templates directory not found:", templatesDir);
98
100
  return [];
99
101
  }
100
102
  const templates = [];
@@ -113,8 +115,8 @@ async function loadAgentTemplates() {
113
115
  mcpServers: template.mcpServers || [],
114
116
  persona: template.persona,
115
117
  capabilities: template.capabilities || [],
118
+ tags: template.metadata?.tags || [],
116
119
  confidence: 0.8,
117
- // Default confidence
118
120
  reason: `Matches project type and includes relevant skills: ${(template.skills || []).join(", ")}`
119
121
  };
120
122
  templates.push(recommendation);
@@ -169,10 +171,11 @@ async function ccjkAgents(options = {}) {
169
171
  (skill) => frameworks.includes(skill) || languages.includes(skill) || projectType.includes(skill)
170
172
  ) || t.capabilities.some(
171
173
  (cap) => frameworks.includes(cap) || languages.includes(cap) || projectType.includes(cap)
174
+ ) || (t.tags || []).some(
175
+ (tag) => frameworks.some((fw) => fw.toLowerCase().includes(tag) || tag.includes(fw.toLowerCase())) || languages.some((lang) => lang.toLowerCase().includes(tag) || tag.includes(lang.toLowerCase())) || projectType.toLowerCase().includes(tag)
172
176
  )
173
177
  );
174
178
  if (recommendations.length === 0) {
175
- consola.warn(isZh ? "\u672A\u627E\u5230\u5408\u9002\u7684\u4EE3\u7406\uFF0C\u4F7F\u7528\u6240\u6709\u6A21\u677F" : "No suitable agents found, using all templates");
176
179
  recommendations = allTemplates;
177
180
  }
178
181
  try {
@@ -1,6 +1,6 @@
1
1
  import a from './index2.mjs';
2
2
  import { c as consola } from '../shared/ccjk.UIvifqNE.mjs';
3
- import { c as createCompleteCloudClient } from '../shared/ccjk.B364Fu0N.mjs';
3
+ import { c as createCompleteCloudClient } from '../shared/ccjk.CtXhbEqb.mjs';
4
4
  import { i18n, ensureI18nInitialized } from './index5.mjs';
5
5
  import { createHash } from 'node:crypto';
6
6
  import { promises, readFileSync } from 'node:fs';
@@ -36,7 +36,7 @@ async function ccjkSkills(options = {}) {
36
36
  const opts = {
37
37
  lang: options.lang || "en",
38
38
  interactive: options.interactive ?? true,
39
- category: options.category || "custom",
39
+ category: options.category || "",
40
40
  tags: options.tags || [],
41
41
  exclude: options.exclude || [],
42
42
  dryRun: options.dryRun ?? false,
@@ -273,7 +273,7 @@ async function getLocalRecommendations(analysis, _options) {
273
273
  templatePath: "react-patterns.md"
274
274
  });
275
275
  }
276
- if (fwMap.next > 0.5) {
276
+ if ((fwMap["next.js"] || fwMap.next) > 0.5) {
277
277
  skills.push({
278
278
  id: "nextjs-optimization",
279
279
  name: { "en": "Next.js Optimization", "zh-CN": "Next.js \u6027\u80FD\u4F18\u5316" },
@@ -1,13 +1,14 @@
1
1
  import { EventEmitter } from 'node:events';
2
- import { a as getGlobalStateManager, g as getGlobalConvoyManager } from './convoy-manager.mjs';
2
+ import { a as getGlobalStateManager, g as getGlobalConvoyManager, S as SessionIntelligence } from './convoy-manager.mjs';
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 'node:child_process';
7
+ import 'node:fs/promises';
6
8
  import 'node:os';
9
+ import 'node:path';
7
10
  import './main.mjs';
8
11
  import 'module';
9
- import 'node:child_process';
10
- import 'node:path';
11
12
  import 'node:process';
12
13
  import 'node:stream';
13
14
  import 'node:readline';
@@ -2134,6 +2135,7 @@ class BrainCliHook extends EventEmitter {
2134
2135
  await this.initialize();
2135
2136
  }
2136
2137
  try {
2138
+ SessionIntelligence.getInstance().recordMessage("user", userInput);
2137
2139
  const result = await processUserInput(userInput);
2138
2140
  if (result.handled && result.result) {
2139
2141
  this.emit("hook:handled", { input: userInput, result: result.result });
@@ -49,7 +49,7 @@ const CLOUD_ENDPOINTS = {
49
49
  * Used for: plugin discovery, installation, ratings
50
50
  */
51
51
  PLUGINS: {
52
- BASE_URL: "https://api.api.claudehome.cn",
52
+ BASE_URL: "https://api.claudehome.cn",
53
53
  API_VERSION: "/v1"
54
54
  },
55
55
  /**
@@ -14,6 +14,13 @@ const DEPTH_TOKEN_BUDGETS = {
14
14
  L2: Number.POSITIVE_INFINITY
15
15
  // Full content
16
16
  };
17
+ const PHASE_BUDGET_MULTIPLIERS = {
18
+ exploring: 2,
19
+ executing: 0.6,
20
+ generating: 0.4,
21
+ reviewing: 1.2,
22
+ idle: 1
23
+ };
17
24
  const CHARS_PER_TOKEN = 4;
18
25
  function estimateTokens(text) {
19
26
  return Math.ceil(text.length / CHARS_PER_TOKEN);
@@ -58,7 +65,8 @@ class ContextLoader {
58
65
  layers = ["project", "domain", "task", "execution"],
59
66
  task
60
67
  } = options;
61
- const effectiveBudget = tokenBudget ?? this.defaultTokenBudget;
68
+ const phaseMultiplier = options.taskPhase ? PHASE_BUDGET_MULTIPLIERS[options.taskPhase] ?? 1 : 1;
69
+ const effectiveBudget = Math.round((tokenBudget ?? this.defaultTokenBudget) * phaseMultiplier);
62
70
  const depth = this.resolveDepth(effectiveBudget, explicitDepth);
63
71
  const cacheKey = this.getCacheKey(projectRoot, layers, task?.id, depth);
64
72
  const cached = this.cache.get(cacheKey);
@@ -1,10 +1,115 @@
1
- import { EventEmitter } from 'node:events';
2
- import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
1
+ import 'node:child_process';
3
2
  import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
3
+ import 'node:fs/promises';
4
4
  import { homedir } from 'node:os';
5
+ import 'node:path';
6
+ import { EventEmitter } from 'node:events';
7
+ import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
5
8
  import { x as K } from './main.mjs';
6
9
  import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
7
10
 
11
+ function detectTaskPhase(history) {
12
+ if (history.length === 0) return "idle";
13
+ const recent = history.slice(-10);
14
+ const recentText = recent.map((h) => h.content).join(" ").toLowerCase();
15
+ if (recentText.includes("write") || recentText.includes("create") || recentText.includes("generating"))
16
+ return "generating";
17
+ if (recentText.includes("test") || recentText.includes("review") || recentText.includes("check"))
18
+ return "reviewing";
19
+ if (recentText.includes("edit") || recentText.includes("bash") || recentText.includes("run"))
20
+ return "executing";
21
+ if (recentText.includes("read") || recentText.includes("search") || recentText.includes("grep"))
22
+ return "exploring";
23
+ return "idle";
24
+ }
25
+ function extractFilePaths(content) {
26
+ const matches = content.match(/(?:\/[\w./\-]+\.\w+|[\w./\-]+\.(?:ts|js|json|md|py|go|rs))/g);
27
+ return matches ? [...new Set(matches)] : [];
28
+ }
29
+ class SessionIntelligence {
30
+ session;
31
+ constructor(session) {
32
+ this.session = session;
33
+ if (!session.intelligence) {
34
+ session.intelligence = {
35
+ taskPhase: "idle",
36
+ filesTouched: [],
37
+ keyDecisions: [],
38
+ toolCallCount: 0,
39
+ compressionWatermark: 0
40
+ };
41
+ }
42
+ }
43
+ get state() {
44
+ return this.session.intelligence;
45
+ }
46
+ /**
47
+ * Observe a new history entry and update intelligence state.
48
+ * Call this after every message added to the session.
49
+ */
50
+ observe(entry) {
51
+ const intel = this.state;
52
+ if (!intel.userOriginalIntent && entry.role === "user" && entry.content.trim().length > 10) {
53
+ intel.userOriginalIntent = entry.content.slice(0, 500);
54
+ }
55
+ const files = extractFilePaths(entry.content);
56
+ for (const f of files) {
57
+ if (!intel.filesTouched.includes(f)) {
58
+ intel.filesTouched.push(f);
59
+ }
60
+ }
61
+ if (entry.role === "assistant" && /\b(bash|read|write|edit|grep|glob)\b/i.test(entry.content)) {
62
+ intel.toolCallCount++;
63
+ }
64
+ intel.taskPhase = detectTaskPhase(this.session.history);
65
+ }
66
+ /**
67
+ * Record a key decision explicitly.
68
+ */
69
+ recordDecision(decision) {
70
+ const intel = this.state;
71
+ if (!intel.keyDecisions.includes(decision)) {
72
+ intel.keyDecisions.push(decision.slice(0, 200));
73
+ if (intel.keyDecisions.length > 20) {
74
+ intel.keyDecisions.shift();
75
+ }
76
+ }
77
+ }
78
+ /**
79
+ * Mark that history up to index N has been compressed.
80
+ */
81
+ markCompressed(upToIndex) {
82
+ this.state.compressionWatermark = upToIndex;
83
+ }
84
+ /**
85
+ * Generate a system prompt injection that preserves intent across compaction.
86
+ * Inject this whenever context is about to be compressed.
87
+ */
88
+ getSystemPromptInjection() {
89
+ const intel = this.state;
90
+ const parts = ["<!-- session-intelligence -->"];
91
+ if (intel.userOriginalIntent) {
92
+ parts.push(`Original user intent: ${intel.userOriginalIntent}`);
93
+ }
94
+ if (intel.keyDecisions.length > 0) {
95
+ parts.push(`Key decisions: ${intel.keyDecisions.join("; ")}`);
96
+ }
97
+ if (intel.filesTouched.length > 0) {
98
+ parts.push(`Files touched: ${intel.filesTouched.slice(-20).join(", ")}`);
99
+ }
100
+ parts.push(`Task phase: ${intel.taskPhase} | Tool calls: ${intel.toolCallCount}`);
101
+ parts.push("<!-- /session-intelligence -->");
102
+ return parts.join("\n");
103
+ }
104
+ /**
105
+ * Returns true if the session has enough context to be worth preserving.
106
+ */
107
+ hasSignificantContext() {
108
+ const intel = this.state;
109
+ return !!intel.userOriginalIntent || intel.toolCallCount > 3 || intel.filesTouched.length > 0;
110
+ }
111
+ }
112
+
8
113
  class GitBackedStateManager extends EventEmitter {
9
114
  config;
10
115
  worktrees = /* @__PURE__ */ new Map();
@@ -877,4 +982,4 @@ const convoyManager = {
877
982
  getGlobalConvoyManager: getGlobalConvoyManager
878
983
  };
879
984
 
880
- export { getGlobalStateManager as a, gitBackedState as b, convoyManager as c, getGlobalConvoyManager as g };
985
+ export { SessionIntelligence as S, getGlobalStateManager as a, gitBackedState as b, convoyManager as c, getGlobalConvoyManager as g };
@@ -301,7 +301,7 @@ async function mcpDoctor(options = {}) {
301
301
  console.log("");
302
302
  }
303
303
 
304
- const DEFAULT_API_URL = "https://api.api.claudehome.cn/v1/mcp-marketplace";
304
+ const DEFAULT_API_URL = "https://api.claudehome.cn/api/v1/skills";
305
305
  const REQUEST_TIMEOUT = 3e4;
306
306
  const MAX_RETRY_ATTEMPTS = 3;
307
307
  const RETRY_DELAY = 1e3;
@@ -355,7 +355,7 @@ class MarketplaceClient {
355
355
  async search(options = {}) {
356
356
  this.log("Searching packages with options:", options);
357
357
  const params = this.buildSearchParams(options);
358
- const response = await this.request("/search", {
358
+ const response = await this.request("", {
359
359
  method: "GET",
360
360
  params
361
361
  });
@@ -660,7 +660,7 @@ class MarketplaceClient {
660
660
  */
661
661
  buildSearchParams(options) {
662
662
  return {
663
- q: options.query,
663
+ keyword: options.query,
664
664
  category: options.category,
665
665
  tags: options.tags,
666
666
  sortBy: options.sortBy,
@@ -31,40 +31,61 @@ function isOnboardingCompleted() {
31
31
  const state = readOnboardingState();
32
32
  return state?.completed === true;
33
33
  }
34
- async function runOnboardingWizard() {
34
+ async function runOnboardingWizard(options = {}) {
35
+ if (options.reset) {
36
+ try {
37
+ writeOnboardingState({ completed: false, completedAt: "", completedSteps: [] });
38
+ } catch {
39
+ }
40
+ }
41
+ const existingState = readOnboardingState();
42
+ const completedSteps = new Set(existingState?.completedSteps ?? []);
35
43
  const isZh = i18n.language === "zh-CN";
36
44
  console.log("");
37
45
  console.log(a.bold.yellow(isZh ? "\u{1F389} \u6B22\u8FCE\u4F7F\u7528 CCJK\uFF01" : "\u{1F389} Welcome to CCJK!"));
38
46
  console.log(a.dim(isZh ? " \u8BA9\u6211\u4EEC\u7528 3 \u6B65\u5B8C\u6210\u521D\u59CB\u5316\u914D\u7F6E" : " Let's get you set up in 3 steps"));
39
47
  console.log("");
40
- console.log(a.bold(`${isZh ? "\u6B65\u9AA4 1/3" : "Step 1/3"}: ${isZh ? "\u73AF\u5883\u68C0\u6D4B" : "Environment Detection"}`));
41
- try {
42
- const { detectSmartDefaults } = await import('./smart-defaults.mjs').then(function (n) { return n.s; });
43
- const defaults = await detectSmartDefaults();
44
- if (defaults) {
45
- console.log(a.green(` \u2714 ${isZh ? "\u68C0\u6D4B\u5230" : "Detected"}: ${defaults.codeToolType || "claude-code"}`));
46
- if (defaults.mcpServices?.length) {
47
- console.log(a.dim(` ${isZh ? "\u63A8\u8350 MCP \u670D\u52A1" : "Recommended MCP"}: ${defaults.mcpServices.slice(0, 3).join(", ")}`));
48
+ const step1Done = completedSteps.has(1);
49
+ console.log(a.bold(`${isZh ? "\u6B65\u9AA4 1/3" : "Step 1/3"}: ${isZh ? "\u73AF\u5883\u68C0\u6D4B" : "Environment Detection"}${step1Done ? a.green(" \u2714") : ""}`));
50
+ if (!step1Done) {
51
+ try {
52
+ const { detectSmartDefaults } = await import('./smart-defaults.mjs').then(function (n) { return n.s; });
53
+ const defaults = await detectSmartDefaults();
54
+ if (defaults) {
55
+ console.log(a.green(` \u2714 ${isZh ? "\u68C0\u6D4B\u5230" : "Detected"}: ${defaults.codeToolType || "claude-code"}`));
56
+ if (defaults.mcpServices?.length) {
57
+ console.log(a.dim(` ${isZh ? "\u63A8\u8350 MCP \u670D\u52A1" : "Recommended MCP"}: ${defaults.mcpServices.slice(0, 3).join(", ")}`));
58
+ }
59
+ } else {
60
+ console.log(a.dim(` ${isZh ? "\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E" : "Using default configuration"}`));
48
61
  }
49
- } else {
50
- console.log(a.dim(` ${isZh ? "\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E" : "Using default configuration"}`));
62
+ completedSteps.add(1);
63
+ } catch {
64
+ console.log(a.dim(` ${isZh ? "\u73AF\u5883\u68C0\u6D4B\u8DF3\u8FC7" : "Environment detection skipped"}`));
51
65
  }
52
- } catch {
53
- console.log(a.dim(` ${isZh ? "\u73AF\u5883\u68C0\u6D4B\u8DF3\u8FC7" : "Environment detection skipped"}`));
66
+ } else {
67
+ console.log(a.dim(` ${isZh ? "\u5DF2\u5B8C\u6210\uFF0C\u8DF3\u8FC7" : "Already done, skipping"}`));
54
68
  }
55
69
  console.log("");
56
- console.log(a.bold(`${isZh ? "\u6B65\u9AA4 2/3" : "Step 2/3"}: ${isZh ? "API \u914D\u7F6E" : "API Configuration"}`));
57
- try {
58
- const { getExistingApiConfig } = await import('./config.mjs').then(function (n) { return n.j; });
59
- const existing = getExistingApiConfig();
60
- if (existing?.key || existing?.url) {
61
- console.log(a.green(` \u2714 ${isZh ? "\u5DF2\u914D\u7F6E" : "Already configured"}`));
62
- } else {
63
- const { configureApiFeature } = await import('./features.mjs');
64
- await configureApiFeature();
70
+ const step2Done = completedSteps.has(2);
71
+ console.log(a.bold(`${isZh ? "\u6B65\u9AA4 2/3" : "Step 2/3"}: ${isZh ? "API \u914D\u7F6E" : "API Configuration"}${step2Done ? a.green(" \u2714") : ""}`));
72
+ if (!step2Done) {
73
+ try {
74
+ const { getExistingApiConfig } = await import('./config.mjs').then(function (n) { return n.j; });
75
+ const existing = getExistingApiConfig();
76
+ if (existing?.key || existing?.url) {
77
+ console.log(a.green(` \u2714 ${isZh ? "\u5DF2\u914D\u7F6E" : "Already configured"}`));
78
+ completedSteps.add(2);
79
+ } else {
80
+ const { configureApiFeature } = await import('./features.mjs');
81
+ await configureApiFeature();
82
+ completedSteps.add(2);
83
+ }
84
+ } catch {
85
+ console.log(a.yellow(` ${isZh ? "\u26A0 API \u914D\u7F6E\u8DF3\u8FC7\uFF0C\u7A0D\u540E\u53EF\u901A\u8FC7\u83DC\u5355\u914D\u7F6E" : "\u26A0 API setup skipped, configure later via menu"}`));
65
86
  }
66
- } catch {
67
- console.log(a.yellow(` ${isZh ? "\u26A0 API \u914D\u7F6E\u8DF3\u8FC7\uFF0C\u7A0D\u540E\u53EF\u901A\u8FC7\u83DC\u5355\u914D\u7F6E" : "\u26A0 API setup skipped, configure later via menu"}`));
87
+ } else {
88
+ console.log(a.dim(` ${isZh ? "\u5DF2\u5B8C\u6210\uFF0C\u8DF3\u8FC7" : "Already done, skipping"}`));
68
89
  }
69
90
  console.log("");
70
91
  console.log(a.bold(`${isZh ? "\u6B65\u9AA4 3/3" : "Step 3/3"}: ${isZh ? "\u73AF\u5883\u9A8C\u8BC1" : "Verification"}`));
@@ -85,7 +106,12 @@ async function runOnboardingWizard() {
85
106
  console.log(a.dim(` ${isZh ? "\u9A8C\u8BC1\u8DF3\u8FC7" : "Verification skipped"}`));
86
107
  }
87
108
  console.log("");
88
- writeOnboardingState({ completed: true, completedAt: (/* @__PURE__ */ new Date()).toISOString() });
109
+ completedSteps.add(3);
110
+ writeOnboardingState({
111
+ completed: true,
112
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
113
+ completedSteps: Array.from(completedSteps)
114
+ });
89
115
  console.log(a.bold.green(isZh ? "\u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01\u8FDB\u5165\u4E3B\u83DC\u5355..." : "\u2705 Setup complete! Loading main menu..."));
90
116
  console.log("");
91
117
  }
@@ -1,3 +1,3 @@
1
- const version = "12.0.8";
1
+ const version = "12.0.10";
2
2
 
3
3
  export { version };
@@ -318,7 +318,7 @@ class LocalPluginCache {
318
318
  }
319
319
  }
320
320
 
321
- const DEFAULT_CLOUD_API_URL = "https://api.claudehome.cn/api/v1/plugins";
321
+ const DEFAULT_CLOUD_API_URL = "https://api.claudehome.cn/api/v1/skills";
322
322
  const REQUEST_TIMEOUT = 3e4;
323
323
  const MAX_RETRY_ATTEMPTS = 3;
324
324
  const RETRY_DELAY = 1e3;
@@ -5624,7 +5624,7 @@ function extractMetadata(data, filePath) {
5624
5624
  return metadata;
5625
5625
  }
5626
5626
 
5627
- process__default.env.CCJK_CLOUD_API_URL || "https://api.api.claudehome.cn/v1";
5627
+ process__default.env.CCJK_CLOUD_API_URL || "https://api.claudehome.cn/api/v1";
5628
5628
  const SYNC_STATE_FILE = join(CCJK_CONFIG_DIR, "skills-sync-state.json");
5629
5629
  const DEFAULT_TIMEOUT = 3e4;
5630
5630
  function loadSyncState() {
@@ -236,6 +236,38 @@ function renderHealthSection(report, compact) {
236
236
  }
237
237
  return lines;
238
238
  }
239
+ function suggestNextAction(health, ctx) {
240
+ const lines = [];
241
+ lines.push(heading("Next Step"));
242
+ const score = health.totalScore;
243
+ const hasFailures = health.results.some((r) => r.status === "fail");
244
+ const hasWarnings = health.results.some((r) => r.status === "warn");
245
+ if (hasFailures) {
246
+ const firstFail = health.results.find((r) => r.status === "fail");
247
+ lines.push(` ${a.red("\u2192")} Fix ${a.bold(firstFail.name)}: ${firstFail.message}`);
248
+ if (firstFail.command) {
249
+ lines.push(` ${a.cyan(firstFail.command)}`);
250
+ } else {
251
+ lines.push(` ${a.cyan("ccjk boost")} to auto-fix`);
252
+ }
253
+ return lines;
254
+ }
255
+ if (score < 60) {
256
+ lines.push(` ${a.yellow("\u2192")} Score is ${score}/100. Run ${a.cyan("ccjk boost")} to optimize.`);
257
+ return lines;
258
+ }
259
+ if (hasWarnings) {
260
+ const warnCount = health.results.filter((r) => r.status === "warn").length;
261
+ lines.push(` ${a.yellow("\u2192")} ${warnCount} warning${warnCount > 1 ? "s" : ""} remaining. Run ${a.cyan("ccjk boost --dry-run")} to preview fixes.`);
262
+ return lines;
263
+ }
264
+ if (score >= 80) {
265
+ lines.push(` ${a.green("\u2192")} Setup looks great. Start coding or run ${a.cyan("ccjk brain status")} to check session.`);
266
+ } else {
267
+ lines.push(` ${a.green("\u2192")} Almost there. Run ${a.cyan("ccjk boost")} to push past ${score}.`);
268
+ }
269
+ return lines;
270
+ }
239
271
  async function statusCommand(options = {}) {
240
272
  try {
241
273
  const [ctx, defaults, installed, health] = await Promise.all([
@@ -270,6 +302,7 @@ async function statusCommand(options = {}) {
270
302
  sections.push(renderCompressionMetricsSection());
271
303
  } catch {
272
304
  }
305
+ sections.push(suggestNextAction(health, ctx));
273
306
  console.log();
274
307
  for (let i = 0; i < sections.length; i++) {
275
308
  console.log(sections[i].join("\n"));
package/dist/index.d.mts CHANGED
@@ -3244,6 +3244,15 @@ declare class CloudClient {
3244
3244
  * Calculate retry delay with exponential backoff
3245
3245
  */
3246
3246
  private calculateRetryDelay;
3247
+ /**
3248
+ * Parse server response — handles all 5 response formats from Miaoda API:
3249
+ * 1. { success: true, data: {} } — auth/user/config/admin modules
3250
+ * 2. { success: false, error: { message } } — error from above modules
3251
+ * 3. { data: {} } — usage/license/skill modules
3252
+ * 4. bare object — subscription/llm/storage modules
3253
+ * 5. { error: "..." } — bare error
3254
+ */
3255
+ parseResponse<T>(raw: unknown): T;
3247
3256
  /**
3248
3257
  * Handle fetch errors and convert to CloudClientError
3249
3258
  */
@@ -3611,6 +3620,7 @@ interface AgentRecommendation {
3611
3620
  mcpServers: string[];
3612
3621
  persona?: string;
3613
3622
  capabilities: string[];
3623
+ tags?: string[];
3614
3624
  confidence: number;
3615
3625
  reason: string;
3616
3626
  }
package/dist/index.d.ts CHANGED
@@ -3244,6 +3244,15 @@ declare class CloudClient {
3244
3244
  * Calculate retry delay with exponential backoff
3245
3245
  */
3246
3246
  private calculateRetryDelay;
3247
+ /**
3248
+ * Parse server response — handles all 5 response formats from Miaoda API:
3249
+ * 1. { success: true, data: {} } — auth/user/config/admin modules
3250
+ * 2. { success: false, error: { message } } — error from above modules
3251
+ * 3. { data: {} } — usage/license/skill modules
3252
+ * 4. bare object — subscription/llm/storage modules
3253
+ * 5. { error: "..." } — bare error
3254
+ */
3255
+ parseResponse<T>(raw: unknown): T;
3247
3256
  /**
3248
3257
  * Handle fetch errors and convert to CloudClientError
3249
3258
  */
@@ -3611,6 +3620,7 @@ interface AgentRecommendation {
3611
3620
  mcpServers: string[];
3612
3621
  persona?: string;
3613
3622
  capabilities: string[];
3623
+ tags?: string[];
3614
3624
  confidence: number;
3615
3625
  reason: string;
3616
3626
  }
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { a as createCloudClient } from './shared/ccjk.B364Fu0N.mjs';
2
- export { C as CachedCloudClient, b as CloudCache, d as CloudClient, F as FallbackCloudClient, R as RetryableCloudClient, T as TelemetryReporter, c as createCompleteCloudClient, g as getTelemetry, i as initializeTelemetry, r as retryUtils, s as stopTelemetry, t as telemetryUtils, e as trackEvent, w as withRetry } from './shared/ccjk.B364Fu0N.mjs';
1
+ import { a as createCloudClient } from './shared/ccjk.CtXhbEqb.mjs';
2
+ export { C as CachedCloudClient, b as CloudCache, d as CloudClient, F as FallbackCloudClient, R as RetryableCloudClient, T as TelemetryReporter, c as createCompleteCloudClient, g as getTelemetry, i as initializeTelemetry, r as retryUtils, s as stopTelemetry, t as telemetryUtils, e as trackEvent, w as withRetry } from './shared/ccjk.CtXhbEqb.mjs';
3
3
  export { C as CloudError, a as CloudErrorCode, b as CloudErrorFactory, f as formatErrorForLogging, g as getRetryDelay, h as handleCloudError, i as isAuthError, c as isRateLimitError, d as isRetryableError, e as isRetryableErrorCode } from './shared/ccjk.D8ZLYSZZ.mjs';
4
4
  export { T as TemplatesClient, a as createTemplatesClient, g as getTemplatesClient } from './shared/ccjk.UIvifqNE.mjs';
5
5
  import { e as extractString } from './shared/ccjk.C2jHOZVP.mjs';