@oro.ad/nuxt-claude-devtools 1.2.0 → 1.3.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.
- package/README.md +105 -13
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/B8uzckkK.js +1 -0
- package/dist/client/_nuxt/{CPQSDiF7.js → BAb1fJOF.js} +4 -4
- package/dist/client/_nuxt/BB1-kxmm.js +1 -0
- package/dist/client/_nuxt/BMZIbUUD.js +1 -0
- package/dist/client/_nuxt/BSF2Vz9o.js +1 -0
- package/dist/client/_nuxt/BSVkH7b6.js +1 -0
- package/dist/client/_nuxt/{08Mb3FOO.js → BYp73eMl.js} +1 -1
- package/dist/client/_nuxt/B_BoWmnX.js +1 -0
- package/dist/client/_nuxt/BcZxFXBD.js +1 -0
- package/dist/client/_nuxt/BflmC3YB.js +1 -0
- package/dist/client/_nuxt/BnXQTjo-.js +1 -0
- package/dist/client/_nuxt/C--9REmc.js +1 -0
- package/dist/client/_nuxt/CDQtmRaX.js +1 -0
- package/dist/client/_nuxt/CHeJJZL9.js +1 -0
- package/dist/client/_nuxt/{CSlPuO5s.js → COus5Ssl.js} +1 -1
- package/dist/client/_nuxt/{o1jjB-UO.js → CPA0s6N9.js} +1 -1
- package/dist/client/_nuxt/CRkq21kc.js +1 -0
- package/dist/client/_nuxt/Cgba93Y9.js +1 -0
- package/dist/client/_nuxt/D2l4TRxW.js +1 -0
- package/dist/client/_nuxt/DC_XB519.js +1 -0
- package/dist/client/_nuxt/DEys9N1G.js +1 -0
- package/dist/client/_nuxt/{b4Upel01.js → DGQ4s7ae.js} +1 -1
- package/dist/client/_nuxt/DH8Ugy8E.js +1 -0
- package/dist/client/_nuxt/DSt96JPY.js +4 -0
- package/dist/client/_nuxt/DbJLoP3G.js +1 -0
- package/dist/client/_nuxt/DeGmaFBY.js +1 -0
- package/dist/client/_nuxt/DgfRwrFR.js +1 -0
- package/dist/client/_nuxt/{CLKqRoht.js → DolUcBed.js} +1 -1
- package/dist/client/_nuxt/M6QPYocW.js +1 -0
- package/dist/client/_nuxt/QumocfwJ.js +1 -0
- package/dist/client/_nuxt/TQi6eIO6.js +1 -0
- package/dist/client/_nuxt/V4UvAcd3.js +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/2be12f06-336a-4fdd-b982-2f6c682c14a6.json +1 -0
- package/dist/client/_nuxt/d8BPa19J.js +1 -0
- package/dist/client/_nuxt/entry.BMxUr06A.css +1 -0
- package/dist/client/_nuxt/qbS8UemQ.js +1 -0
- package/dist/client/_nuxt/wDw60tEC.js +10 -0
- package/dist/client/_nuxt/xEjB6ozD.js +1 -0
- package/dist/client/agents/index.html +1 -1
- package/dist/client/commands/index.html +1 -1
- package/dist/client/docs/index.html +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/mcp/index.html +1 -1
- package/dist/client/plugins/index.html +1 -0
- package/dist/client/settings/index.html +1 -0
- package/dist/client/skills/index.html +1 -1
- package/dist/module.d.mts +12 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +27 -5
- package/dist/runtime/constants.d.ts +29 -0
- package/dist/runtime/constants.js +5 -0
- package/dist/runtime/overlay/components/ChatOverlay.d.vue.ts +7 -0
- package/dist/runtime/overlay/components/ChatOverlay.vue +893 -0
- package/dist/runtime/overlay/components/ChatOverlay.vue.d.ts +7 -0
- package/dist/runtime/overlay/components/MarkdownContent.d.vue.ts +6 -0
- package/dist/runtime/overlay/components/MarkdownContent.vue +31 -0
- package/dist/runtime/overlay/components/MarkdownContent.vue.d.ts +6 -0
- package/dist/runtime/overlay/components/ToolCallBlock.d.vue.ts +8 -0
- package/dist/runtime/overlay/components/ToolCallBlock.vue +77 -0
- package/dist/runtime/overlay/components/ToolCallBlock.vue.d.ts +8 -0
- package/dist/runtime/overlay/plugin.client.d.ts +6 -0
- package/dist/runtime/overlay/plugin.client.js +29 -0
- package/dist/runtime/server/agents-manager.d.ts +17 -4
- package/dist/runtime/server/agents-manager.js +38 -109
- package/dist/runtime/server/base-resource-manager.d.ts +90 -0
- package/dist/runtime/server/base-resource-manager.js +201 -0
- package/dist/runtime/server/claude-session.d.ts +11 -1
- package/dist/runtime/server/claude-session.js +246 -27
- package/dist/runtime/server/commands-manager.d.ts +12 -4
- package/dist/runtime/server/commands-manager.js +25 -100
- package/dist/runtime/server/constants.d.ts +94 -0
- package/dist/runtime/server/constants.js +18 -0
- package/dist/runtime/server/docs-manager.d.ts +7 -0
- package/dist/runtime/server/docs-manager.js +112 -3
- package/dist/runtime/server/history-manager.d.ts +1 -0
- package/dist/runtime/server/history-manager.js +25 -3
- package/dist/runtime/server/plugins/socket.io.js +5 -3
- package/dist/runtime/server/plugins-manager.d.ts +84 -0
- package/dist/runtime/server/plugins-manager.js +338 -0
- package/dist/runtime/server/settings-manager.d.ts +17 -0
- package/dist/runtime/server/settings-manager.js +70 -0
- package/dist/runtime/server/share-manager.d.ts +24 -0
- package/dist/runtime/server/share-manager.js +96 -0
- package/dist/runtime/server/skills-manager.d.ts +18 -4
- package/dist/runtime/server/skills-manager.js +32 -159
- package/dist/runtime/shared/composables/useClaudeChat.d.ts +35 -0
- package/dist/runtime/shared/composables/useClaudeChat.js +264 -0
- package/dist/runtime/shared/composables/useShare.d.ts +42 -0
- package/dist/runtime/shared/composables/useShare.js +192 -0
- package/dist/runtime/shared/composables/useVoiceInput.d.ts +8 -0
- package/dist/runtime/shared/composables/useVoiceInput.js +77 -0
- package/dist/runtime/shared/constants.d.ts +28 -0
- package/dist/runtime/shared/constants.js +6 -0
- package/dist/runtime/shared/index.d.ts +9 -0
- package/dist/runtime/shared/index.js +5 -0
- package/dist/runtime/shared/types.d.ts +48 -0
- package/dist/runtime/shared/types.js +0 -0
- package/dist/runtime/types.d.ts +2 -0
- package/dist/types.d.mts +1 -1
- package/package.json +5 -3
- package/dist/client/_nuxt/BMi2eT6G.js +0 -1
- package/dist/client/_nuxt/BiBLVxWh.js +0 -1
- package/dist/client/_nuxt/BnRGpZsC.js +0 -8
- package/dist/client/_nuxt/C2GhPw5d.js +0 -7
- package/dist/client/_nuxt/D8683igF.js +0 -7
- package/dist/client/_nuxt/DBIw6BGF.js +0 -1
- package/dist/client/_nuxt/DCgjfr8H.js +0 -9
- package/dist/client/_nuxt/bl5iU4Kz.js +0 -1
- package/dist/client/_nuxt/builds/meta/35284331-5e85-46e0-9058-988fea05336c.json +0 -1
- package/dist/client/_nuxt/entry.BhHeZ_Nj.css +0 -1
- package/dist/client/_nuxt/nKfsBgPE.js +0 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MarkdownResourceManager } from './base-resource-manager.js';
|
|
1
2
|
export interface SlashCommand {
|
|
2
3
|
name: string;
|
|
3
4
|
path: string;
|
|
@@ -7,12 +8,18 @@ export interface SlashCommand {
|
|
|
7
8
|
content: string;
|
|
8
9
|
rawContent: string;
|
|
9
10
|
updatedAt: string;
|
|
11
|
+
/** Source of the command: 'project' for local .claude/, or plugin name */
|
|
12
|
+
source?: string;
|
|
10
13
|
}
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
interface CommandFrontmatter {
|
|
15
|
+
'description'?: string;
|
|
16
|
+
'allowed-tools'?: string;
|
|
17
|
+
'disable-model-invocation'?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare class CommandsManager extends MarkdownResourceManager<SlashCommand, CommandFrontmatter> {
|
|
13
20
|
constructor(projectPath: string);
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
protected buildFrontmatter(command: Partial<SlashCommand>): string;
|
|
22
|
+
protected toResource(name: string, frontmatter: CommandFrontmatter, body: string, rawContent: string, updatedAt: string): SlashCommand;
|
|
16
23
|
getCommands(): SlashCommand[];
|
|
17
24
|
getCommand(name: string): SlashCommand | null;
|
|
18
25
|
saveCommand(name: string, content: string, options?: {
|
|
@@ -22,3 +29,4 @@ export declare class CommandsManager {
|
|
|
22
29
|
}): SlashCommand;
|
|
23
30
|
deleteCommand(name: string): boolean;
|
|
24
31
|
}
|
|
32
|
+
export {};
|
|
@@ -1,132 +1,57 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { basename, join } from "node:path";
|
|
3
1
|
import { createLogger } from "../logger.js";
|
|
2
|
+
import { MarkdownResourceManager } from "./base-resource-manager.js";
|
|
3
|
+
import { COMMANDS_SUBDIR } from "./constants.js";
|
|
4
4
|
const log = createLogger("commands", { timestamp: true });
|
|
5
|
-
export class CommandsManager {
|
|
6
|
-
commandsDir;
|
|
5
|
+
export class CommandsManager extends MarkdownResourceManager {
|
|
7
6
|
constructor(projectPath) {
|
|
8
|
-
|
|
9
|
-
if (!existsSync(this.commandsDir)) {
|
|
10
|
-
mkdirSync(this.commandsDir, { recursive: true });
|
|
11
|
-
log("Created commands directory", { path: this.commandsDir });
|
|
12
|
-
}
|
|
7
|
+
super(projectPath, COMMANDS_SUBDIR, log);
|
|
13
8
|
}
|
|
14
|
-
// Parse frontmatter from markdown content
|
|
15
|
-
parseFrontmatter(content) {
|
|
16
|
-
const frontmatterRegex = /^---\n((?:[^\n]*\n)*?)---\n([\s\S]*)$/;
|
|
17
|
-
const match = content.match(frontmatterRegex);
|
|
18
|
-
if (!match) {
|
|
19
|
-
return { frontmatter: {}, body: content };
|
|
20
|
-
}
|
|
21
|
-
const [, yaml, body] = match;
|
|
22
|
-
const frontmatter = {};
|
|
23
|
-
for (const line of yaml.split("\n")) {
|
|
24
|
-
const colonIndex = line.indexOf(":");
|
|
25
|
-
if (colonIndex === -1) continue;
|
|
26
|
-
const key = line.slice(0, colonIndex).trim();
|
|
27
|
-
const value = line.slice(colonIndex + 1).trim();
|
|
28
|
-
if (key === "description") {
|
|
29
|
-
frontmatter.description = value;
|
|
30
|
-
} else if (key === "allowed-tools") {
|
|
31
|
-
frontmatter["allowed-tools"] = value;
|
|
32
|
-
} else if (key === "disable-model-invocation") {
|
|
33
|
-
frontmatter["disable-model-invocation"] = value === "true";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return { frontmatter, body: body.trim() };
|
|
37
|
-
}
|
|
38
|
-
// Build frontmatter string
|
|
39
9
|
buildFrontmatter(command) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
lines.push(`allowed-tools: ${command.allowedTools.join(", ")}`);
|
|
46
|
-
}
|
|
47
|
-
if (command.disableModelInvocation !== void 0) {
|
|
48
|
-
lines.push(`disable-model-invocation: ${command.disableModelInvocation}`);
|
|
49
|
-
}
|
|
50
|
-
lines.push("---");
|
|
51
|
-
return lines.join("\n");
|
|
52
|
-
}
|
|
53
|
-
// Get all slash commands
|
|
54
|
-
getCommands() {
|
|
55
|
-
const commands = [];
|
|
56
|
-
if (!existsSync(this.commandsDir)) return commands;
|
|
57
|
-
const entries = readdirSync(this.commandsDir);
|
|
58
|
-
for (const entry of entries) {
|
|
59
|
-
if (!entry.endsWith(".md")) continue;
|
|
60
|
-
const fullPath = join(this.commandsDir, entry);
|
|
61
|
-
const stat = statSync(fullPath);
|
|
62
|
-
if (stat.isDirectory()) continue;
|
|
63
|
-
const rawContent = readFileSync(fullPath, "utf-8");
|
|
64
|
-
const { frontmatter, body } = this.parseFrontmatter(rawContent);
|
|
65
|
-
commands.push({
|
|
66
|
-
name: basename(entry, ".md"),
|
|
67
|
-
path: entry,
|
|
68
|
-
description: frontmatter.description,
|
|
69
|
-
allowedTools: frontmatter["allowed-tools"] ? frontmatter["allowed-tools"].split(",").map((s) => s.trim()) : void 0,
|
|
70
|
-
disableModelInvocation: frontmatter["disable-model-invocation"],
|
|
71
|
-
content: body,
|
|
72
|
-
rawContent,
|
|
73
|
-
updatedAt: stat.mtime.toISOString()
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
return commands.sort((a, b) => a.name.localeCompare(b.name));
|
|
10
|
+
return this.buildFrontmatterLines([
|
|
11
|
+
{ key: "description", value: command.description },
|
|
12
|
+
{ key: "allowed-tools", value: command.allowedTools },
|
|
13
|
+
{ key: "disable-model-invocation", value: command.disableModelInvocation }
|
|
14
|
+
]);
|
|
77
15
|
}
|
|
78
|
-
|
|
79
|
-
getCommand(name) {
|
|
80
|
-
const fileName = name.endsWith(".md") ? name : `${name}.md`;
|
|
81
|
-
const fullPath = join(this.commandsDir, fileName);
|
|
82
|
-
if (!existsSync(fullPath)) return null;
|
|
83
|
-
const stat = statSync(fullPath);
|
|
84
|
-
const rawContent = readFileSync(fullPath, "utf-8");
|
|
85
|
-
const { frontmatter, body } = this.parseFrontmatter(rawContent);
|
|
16
|
+
toResource(name, frontmatter, body, rawContent, updatedAt) {
|
|
86
17
|
return {
|
|
87
|
-
name
|
|
88
|
-
path:
|
|
18
|
+
name,
|
|
19
|
+
path: `${name}.md`,
|
|
89
20
|
description: frontmatter.description,
|
|
90
21
|
allowedTools: frontmatter["allowed-tools"] ? frontmatter["allowed-tools"].split(",").map((s) => s.trim()) : void 0,
|
|
91
22
|
disableModelInvocation: frontmatter["disable-model-invocation"],
|
|
92
23
|
content: body,
|
|
93
24
|
rawContent,
|
|
94
|
-
updatedAt
|
|
25
|
+
updatedAt
|
|
95
26
|
};
|
|
96
27
|
}
|
|
97
|
-
//
|
|
28
|
+
// Public API methods
|
|
29
|
+
getCommands() {
|
|
30
|
+
return this.getAll();
|
|
31
|
+
}
|
|
32
|
+
getCommand(name) {
|
|
33
|
+
return this.getOne(name);
|
|
34
|
+
}
|
|
98
35
|
saveCommand(name, content, options) {
|
|
99
|
-
const safeName =
|
|
100
|
-
const fileName = `${safeName}.md`;
|
|
101
|
-
const fullPath = join(this.commandsDir, fileName);
|
|
36
|
+
const safeName = this.sanitizeName(name);
|
|
102
37
|
const frontmatter = this.buildFrontmatter({
|
|
103
38
|
description: options?.description,
|
|
104
39
|
allowedTools: options?.allowedTools,
|
|
105
40
|
disableModelInvocation: options?.disableModelInvocation
|
|
106
41
|
});
|
|
107
|
-
const rawContent =
|
|
108
|
-
|
|
109
|
-
${content}`;
|
|
110
|
-
writeFileSync(fullPath, rawContent, "utf-8");
|
|
111
|
-
log("Saved command", { name: safeName });
|
|
42
|
+
const { rawContent, updatedAt } = this.saveResource(safeName, frontmatter, content);
|
|
112
43
|
return {
|
|
113
44
|
name: safeName,
|
|
114
|
-
path:
|
|
45
|
+
path: `${safeName}.md`,
|
|
115
46
|
description: options?.description,
|
|
116
47
|
allowedTools: options?.allowedTools,
|
|
117
48
|
disableModelInvocation: options?.disableModelInvocation,
|
|
118
49
|
content,
|
|
119
50
|
rawContent,
|
|
120
|
-
updatedAt
|
|
51
|
+
updatedAt
|
|
121
52
|
};
|
|
122
53
|
}
|
|
123
|
-
// Delete command
|
|
124
54
|
deleteCommand(name) {
|
|
125
|
-
|
|
126
|
-
const fullPath = join(this.commandsDir, fileName);
|
|
127
|
-
if (!existsSync(fullPath)) return false;
|
|
128
|
-
unlinkSync(fullPath);
|
|
129
|
-
log("Deleted command", { name });
|
|
130
|
-
return true;
|
|
55
|
+
return this.delete(name);
|
|
131
56
|
}
|
|
132
57
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side constants for nuxt-claude-devtools
|
|
3
|
+
* Defines file paths, directory names, and configuration file names
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Claude's standard configuration directory
|
|
7
|
+
* Contains: commands, agents, skills, docs
|
|
8
|
+
* Standard location recognized by Claude CLI
|
|
9
|
+
*/
|
|
10
|
+
export declare const CLAUDE_DIR = ".claude";
|
|
11
|
+
/**
|
|
12
|
+
* DevTools-specific data directory
|
|
13
|
+
* Contains: history.json, settings.json, share.json, llms.json
|
|
14
|
+
* Separate from .claude to avoid conflicts with Claude CLI
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEVTOOLS_DATA_DIR = ".claude-devtools";
|
|
17
|
+
/**
|
|
18
|
+
* Directory for custom slash commands
|
|
19
|
+
* Path: .claude/commands/
|
|
20
|
+
*/
|
|
21
|
+
export declare const COMMANDS_SUBDIR = "commands";
|
|
22
|
+
/**
|
|
23
|
+
* Directory for agent definitions
|
|
24
|
+
* Path: .claude/agents/
|
|
25
|
+
*/
|
|
26
|
+
export declare const AGENTS_SUBDIR = "agents";
|
|
27
|
+
/**
|
|
28
|
+
* Directory for skill definitions
|
|
29
|
+
* Path: .claude/skills/
|
|
30
|
+
*/
|
|
31
|
+
export declare const SKILLS_SUBDIR = "skills";
|
|
32
|
+
/**
|
|
33
|
+
* Directory for project documentation
|
|
34
|
+
* Path: .claude/docs/
|
|
35
|
+
* Claude automatically reads files from this directory
|
|
36
|
+
*/
|
|
37
|
+
export declare const DOCS_SUBDIR = "docs";
|
|
38
|
+
/**
|
|
39
|
+
* Project guidelines file in repository root
|
|
40
|
+
* Claude reads this file for project-specific instructions
|
|
41
|
+
*/
|
|
42
|
+
export declare const CLAUDE_MD_FILE = "CLAUDE.md";
|
|
43
|
+
/**
|
|
44
|
+
* Skill definition file name inside skill subdirectories
|
|
45
|
+
* Path: .claude/skills/<skill-name>/SKILL.md
|
|
46
|
+
*/
|
|
47
|
+
export declare const SKILL_FILE = "SKILL.md";
|
|
48
|
+
/**
|
|
49
|
+
* Conversation history storage
|
|
50
|
+
* Path: .claude-devtools/history.json
|
|
51
|
+
*/
|
|
52
|
+
export declare const HISTORY_FILE = "history.json";
|
|
53
|
+
/**
|
|
54
|
+
* DevTools settings storage
|
|
55
|
+
* Path: .claude-devtools/settings.json
|
|
56
|
+
*/
|
|
57
|
+
export declare const SETTINGS_FILE = "settings.json";
|
|
58
|
+
/**
|
|
59
|
+
* Collaborative sharing data
|
|
60
|
+
* Path: .claude-devtools/share.json
|
|
61
|
+
*/
|
|
62
|
+
export declare const SHARE_FILE = "share.json";
|
|
63
|
+
/**
|
|
64
|
+
* External documentation sources (llms.txt URLs)
|
|
65
|
+
* Path: .claude-devtools/llms.json
|
|
66
|
+
*/
|
|
67
|
+
export declare const LLMS_FILE = "llms.json";
|
|
68
|
+
/**
|
|
69
|
+
* Default extension for markdown resources
|
|
70
|
+
*/
|
|
71
|
+
export declare const MD_EXTENSION = ".md";
|
|
72
|
+
/**
|
|
73
|
+
* Default plugins cache directory (relative to user home)
|
|
74
|
+
* Path: ~/.claude/plugins/cache
|
|
75
|
+
*/
|
|
76
|
+
export declare const DEFAULT_PLUGINS_CACHE_PATH = ".claude/plugins/cache";
|
|
77
|
+
/**
|
|
78
|
+
* Plugin manifest directory name inside plugin root
|
|
79
|
+
*/
|
|
80
|
+
export declare const PLUGIN_MANIFEST_DIR = ".claude-plugin";
|
|
81
|
+
/**
|
|
82
|
+
* Plugin manifest file name
|
|
83
|
+
*/
|
|
84
|
+
export declare const PLUGIN_MANIFEST_FILE = "plugin.json";
|
|
85
|
+
/**
|
|
86
|
+
* Claude settings file (for reading enabled plugins)
|
|
87
|
+
* Path: ~/.claude/settings.json (user scope)
|
|
88
|
+
*/
|
|
89
|
+
export declare const CLAUDE_SETTINGS_FILE = "settings.json";
|
|
90
|
+
/**
|
|
91
|
+
* Claude local settings file (project scope, gitignored)
|
|
92
|
+
* Path: .claude/settings.local.json
|
|
93
|
+
*/
|
|
94
|
+
export declare const CLAUDE_SETTINGS_LOCAL_FILE = "settings.local.json";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const CLAUDE_DIR = ".claude";
|
|
2
|
+
export const DEVTOOLS_DATA_DIR = ".claude-devtools";
|
|
3
|
+
export const COMMANDS_SUBDIR = "commands";
|
|
4
|
+
export const AGENTS_SUBDIR = "agents";
|
|
5
|
+
export const SKILLS_SUBDIR = "skills";
|
|
6
|
+
export const DOCS_SUBDIR = "docs";
|
|
7
|
+
export const CLAUDE_MD_FILE = "CLAUDE.md";
|
|
8
|
+
export const SKILL_FILE = "SKILL.md";
|
|
9
|
+
export const HISTORY_FILE = "history.json";
|
|
10
|
+
export const SETTINGS_FILE = "settings.json";
|
|
11
|
+
export const SHARE_FILE = "share.json";
|
|
12
|
+
export const LLMS_FILE = "llms.json";
|
|
13
|
+
export const MD_EXTENSION = ".md";
|
|
14
|
+
export const DEFAULT_PLUGINS_CACHE_PATH = ".claude/plugins/cache";
|
|
15
|
+
export const PLUGIN_MANIFEST_DIR = ".claude-plugin";
|
|
16
|
+
export const PLUGIN_MANIFEST_FILE = "plugin.json";
|
|
17
|
+
export const CLAUDE_SETTINGS_FILE = "settings.json";
|
|
18
|
+
export const CLAUDE_SETTINGS_LOCAL_FILE = "settings.local.json";
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export declare const CRITICAL_FILES: readonly ["nuxt.config.ts", "nuxt.config.js", "app.config.ts", "app.config.js", ".nuxtrc", "tsconfig.json"];
|
|
2
|
+
export declare function isCriticalFile(filePath: string): boolean;
|
|
3
|
+
export declare function getCriticalFileName(filePath: string): string | null;
|
|
1
4
|
export interface DocFile {
|
|
2
5
|
path: string;
|
|
3
6
|
name: string;
|
|
@@ -36,6 +39,10 @@ export declare class DocsManager {
|
|
|
36
39
|
exists: boolean;
|
|
37
40
|
updatedAt: string;
|
|
38
41
|
};
|
|
42
|
+
private static readonly CRITICAL_FILES_START;
|
|
43
|
+
private static readonly CRITICAL_FILES_END;
|
|
44
|
+
ensureCriticalFilesSection(autoConfirm?: boolean): void;
|
|
45
|
+
private generateCriticalFilesSection;
|
|
39
46
|
private loadLlmsStore;
|
|
40
47
|
private saveLlmsStore;
|
|
41
48
|
getLlmsSources(): LlmsSource[];
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, relative } from "node:path";
|
|
3
3
|
import { createLogger } from "../logger.js";
|
|
4
|
+
import { CLAUDE_DIR, CLAUDE_MD_FILE, DEVTOOLS_DATA_DIR, DOCS_SUBDIR, LLMS_FILE, SETTINGS_FILE } from "./constants.js";
|
|
4
5
|
const log = createLogger("docs", { timestamp: true });
|
|
6
|
+
export const CRITICAL_FILES = [
|
|
7
|
+
"nuxt.config.ts",
|
|
8
|
+
"nuxt.config.js",
|
|
9
|
+
"app.config.ts",
|
|
10
|
+
"app.config.js",
|
|
11
|
+
".nuxtrc",
|
|
12
|
+
"tsconfig.json"
|
|
13
|
+
];
|
|
14
|
+
export function isCriticalFile(filePath) {
|
|
15
|
+
const fileName = basename(filePath);
|
|
16
|
+
return CRITICAL_FILES.includes(fileName);
|
|
17
|
+
}
|
|
18
|
+
export function getCriticalFileName(filePath) {
|
|
19
|
+
const fileName = basename(filePath);
|
|
20
|
+
if (CRITICAL_FILES.includes(fileName)) {
|
|
21
|
+
return fileName;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
5
25
|
export class DocsManager {
|
|
6
26
|
docsDir;
|
|
7
27
|
llmsPath;
|
|
8
28
|
projectPath;
|
|
9
29
|
constructor(projectPath) {
|
|
10
30
|
this.projectPath = projectPath;
|
|
11
|
-
this.docsDir = join(projectPath,
|
|
12
|
-
this.llmsPath = join(projectPath,
|
|
31
|
+
this.docsDir = join(projectPath, CLAUDE_DIR, DOCS_SUBDIR);
|
|
32
|
+
this.llmsPath = join(projectPath, DEVTOOLS_DATA_DIR, LLMS_FILE);
|
|
13
33
|
if (!existsSync(this.docsDir)) {
|
|
14
34
|
mkdirSync(this.docsDir, { recursive: true });
|
|
15
35
|
log("Created docs directory", { path: this.docsDir });
|
|
@@ -84,7 +104,7 @@ export class DocsManager {
|
|
|
84
104
|
}
|
|
85
105
|
// ============ CLAUDE.md ============
|
|
86
106
|
get claudeMdPath() {
|
|
87
|
-
return join(this.projectPath,
|
|
107
|
+
return join(this.projectPath, CLAUDE_MD_FILE);
|
|
88
108
|
}
|
|
89
109
|
// Get CLAUDE.md content
|
|
90
110
|
getClaudeMd() {
|
|
@@ -110,6 +130,95 @@ export class DocsManager {
|
|
|
110
130
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
111
131
|
};
|
|
112
132
|
}
|
|
133
|
+
// Section markers for auto-generated content
|
|
134
|
+
static CRITICAL_FILES_START = "<!-- NUXT-DEVTOOLS:CRITICAL-FILES -->";
|
|
135
|
+
static CRITICAL_FILES_END = "<!-- /NUXT-DEVTOOLS:CRITICAL-FILES -->";
|
|
136
|
+
// Ensure CLAUDE.md has the critical files warning section
|
|
137
|
+
// Always updates the auto-generated section on startup to ensure latest instructions
|
|
138
|
+
ensureCriticalFilesSection(autoConfirm = false) {
|
|
139
|
+
const { content, exists } = this.getClaudeMd();
|
|
140
|
+
const criticalFilesSection = this.generateCriticalFilesSection(autoConfirm);
|
|
141
|
+
if (!exists) {
|
|
142
|
+
const newContent = `# Project Guidelines
|
|
143
|
+
|
|
144
|
+
${criticalFilesSection}
|
|
145
|
+
`;
|
|
146
|
+
this.saveClaudeMd(newContent);
|
|
147
|
+
log("Created CLAUDE.md with critical files section");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (content.includes(DocsManager.CRITICAL_FILES_START)) {
|
|
151
|
+
const startIdx = content.indexOf(DocsManager.CRITICAL_FILES_START);
|
|
152
|
+
const endIdx = content.indexOf(DocsManager.CRITICAL_FILES_END);
|
|
153
|
+
if (endIdx > startIdx) {
|
|
154
|
+
const before = content.substring(0, startIdx);
|
|
155
|
+
const after = content.substring(endIdx + DocsManager.CRITICAL_FILES_END.length);
|
|
156
|
+
const newContent = before + criticalFilesSection + after;
|
|
157
|
+
this.saveClaudeMd(newContent);
|
|
158
|
+
log("Updated critical files section in CLAUDE.md");
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
const newContent = content.trimEnd() + "\n\n" + criticalFilesSection + "\n";
|
|
162
|
+
this.saveClaudeMd(newContent);
|
|
163
|
+
log("Added critical files section to CLAUDE.md");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
generateCriticalFilesSection(autoConfirm) {
|
|
167
|
+
const filesList = CRITICAL_FILES.map((f) => `- \`${f}\``).join("\n");
|
|
168
|
+
const settingsPath = `${DEVTOOLS_DATA_DIR}/${SETTINGS_FILE}`;
|
|
169
|
+
return `${DocsManager.CRITICAL_FILES_START}
|
|
170
|
+
## \u26A0\uFE0F Critical Configuration Files
|
|
171
|
+
|
|
172
|
+
The following files trigger a full Nuxt restart when modified:
|
|
173
|
+
${filesList}
|
|
174
|
+
|
|
175
|
+
### \u{1F534} MANDATORY CHECK (EVERY TIME, NO EXCEPTIONS)
|
|
176
|
+
|
|
177
|
+
**BEFORE modifying ANY of these files, you MUST:**
|
|
178
|
+
|
|
179
|
+
\`\`\`
|
|
180
|
+
1. READ ${settingsPath}
|
|
181
|
+
2. CHECK criticalFiles.autoConfirm value
|
|
182
|
+
3. IF false OR file missing \u2192 STOP and ASK user
|
|
183
|
+
4. IF true \u2192 inform user, then proceed
|
|
184
|
+
\`\`\`
|
|
185
|
+
|
|
186
|
+
**This check is REQUIRED every single time, even if you checked before in this session.**
|
|
187
|
+
|
|
188
|
+
### Order of Operations
|
|
189
|
+
|
|
190
|
+
1. **Complete ALL prerequisite tasks FIRST**
|
|
191
|
+
- Create all new files that will be referenced
|
|
192
|
+
- Install all dependencies
|
|
193
|
+
- Write all related code
|
|
194
|
+
|
|
195
|
+
2. **Verify prerequisites exist**
|
|
196
|
+
- All files referenced in config change must exist
|
|
197
|
+
- All imports must be valid
|
|
198
|
+
|
|
199
|
+
3. **Check settings file** (read \`${settingsPath}\`)
|
|
200
|
+
|
|
201
|
+
4. **Act based on autoConfirm setting**
|
|
202
|
+
|
|
203
|
+
### Example: Adding i18n locale
|
|
204
|
+
|
|
205
|
+
\`\`\`
|
|
206
|
+
Step 1: Create locales/es.json \u2713 prerequisite
|
|
207
|
+
Step 2: Read ${settingsPath} \u2713 check flag
|
|
208
|
+
Step 3: If autoConfirm=false \u2192 ask user
|
|
209
|
+
Step 4: Update nuxt.config.ts \u2713 only after confirmation
|
|
210
|
+
\`\`\`
|
|
211
|
+
|
|
212
|
+
### Current Setting
|
|
213
|
+
|
|
214
|
+
**autoConfirm: ${autoConfirm ? "ENABLED" : "DISABLED"}**
|
|
215
|
+
|
|
216
|
+
${autoConfirm ? "\u2192 Inform user about restart, no confirmation needed." : '\u2192 MUST ask user and WAIT for explicit "yes" before proceeding.'}
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
After restart, conversation history is preserved. User can send "continue" to resume.
|
|
220
|
+
${DocsManager.CRITICAL_FILES_END}`;
|
|
221
|
+
}
|
|
113
222
|
// ============ LLMS Sources ============
|
|
114
223
|
loadLlmsStore() {
|
|
115
224
|
try {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { createLogger } from "../logger.js";
|
|
4
|
+
import { DEVTOOLS_DATA_DIR, HISTORY_FILE } from "./constants.js";
|
|
4
5
|
const log = createLogger("history", { timestamp: true });
|
|
5
6
|
export class HistoryManager {
|
|
6
7
|
storePath;
|
|
@@ -8,8 +9,8 @@ export class HistoryManager {
|
|
|
8
9
|
projectPath;
|
|
9
10
|
constructor(projectPath) {
|
|
10
11
|
this.projectPath = projectPath;
|
|
11
|
-
const historyDir = join(projectPath,
|
|
12
|
-
this.storePath = join(historyDir,
|
|
12
|
+
const historyDir = join(projectPath, DEVTOOLS_DATA_DIR);
|
|
13
|
+
this.storePath = join(historyDir, HISTORY_FILE);
|
|
13
14
|
if (!existsSync(historyDir)) {
|
|
14
15
|
mkdirSync(historyDir, { recursive: true });
|
|
15
16
|
log("Created history directory", { path: historyDir });
|
|
@@ -75,7 +76,8 @@ export class HistoryManager {
|
|
|
75
76
|
conversation.messages.push(message);
|
|
76
77
|
conversation.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
77
78
|
if (!conversation.title && message.role === "user") {
|
|
78
|
-
|
|
79
|
+
const content = message.content.replace(/^\[context\]\n[\s\S]*?\n\[\/context\]\n?/, "").trim();
|
|
80
|
+
conversation.title = content.substring(0, 50) + (content.length > 50 ? "..." : "");
|
|
79
81
|
}
|
|
80
82
|
this.saveStore();
|
|
81
83
|
}
|
|
@@ -181,4 +183,24 @@ export class HistoryManager {
|
|
|
181
183
|
const conversation = this.store.activeConversationId ? this.store.conversations.find((c) => c.id === this.store.activeConversationId) : null;
|
|
182
184
|
return !!conversation && conversation.messages.length > 0;
|
|
183
185
|
}
|
|
186
|
+
// Save partial assistant message (for preserving state before config changes)
|
|
187
|
+
savePartialAssistantMessage(message) {
|
|
188
|
+
const conversation = this.getActiveConversation();
|
|
189
|
+
const lastMessage = conversation.messages[conversation.messages.length - 1];
|
|
190
|
+
if (lastMessage && lastMessage.role === "assistant") {
|
|
191
|
+
lastMessage.content = message.content;
|
|
192
|
+
lastMessage.contentBlocks = message.contentBlocks;
|
|
193
|
+
lastMessage.timestamp = message.timestamp;
|
|
194
|
+
if (message.model) lastMessage.model = message.model;
|
|
195
|
+
} else {
|
|
196
|
+
conversation.messages.push(message);
|
|
197
|
+
}
|
|
198
|
+
conversation.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
199
|
+
try {
|
|
200
|
+
writeFileSync(this.storePath, JSON.stringify(this.store, null, 2));
|
|
201
|
+
log("Saved partial assistant message", { messageId: message.id });
|
|
202
|
+
} catch (error) {
|
|
203
|
+
log("Failed to save partial assistant message", { error });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
184
206
|
}
|
|
@@ -2,6 +2,7 @@ import { defineNitroPlugin, useRuntimeConfig } from "nitropack/runtime";
|
|
|
2
2
|
import { Server as Engine } from "engine.io";
|
|
3
3
|
import { Server } from "socket.io";
|
|
4
4
|
import { defineEventHandler } from "h3";
|
|
5
|
+
import { SOCKET_PATH } from "../../constants.js";
|
|
5
6
|
import { createLogger } from "../../logger.js";
|
|
6
7
|
import { getClaudeSessionInstance, initClaudeSession } from "../claude-session.js";
|
|
7
8
|
const log = createLogger("plugin");
|
|
@@ -17,7 +18,8 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
17
18
|
command: claudeConfig.claude.command,
|
|
18
19
|
args: claudeConfig.claude.args,
|
|
19
20
|
rootDir: claudeConfig.rootDir,
|
|
20
|
-
tunnelOrigin: claudeConfig.tunnelOrigin || null
|
|
21
|
+
tunnelOrigin: claudeConfig.tunnelOrigin || null,
|
|
22
|
+
pluginsCachePath: claudeConfig.pluginsCachePath || null
|
|
21
23
|
});
|
|
22
24
|
const engine = new Engine();
|
|
23
25
|
const io = new Server();
|
|
@@ -26,7 +28,7 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
26
28
|
if (session) {
|
|
27
29
|
session.attachSocketIO(io);
|
|
28
30
|
}
|
|
29
|
-
nitroApp.router.use(
|
|
31
|
+
nitroApp.router.use(`${SOCKET_PATH}/`, defineEventHandler({
|
|
30
32
|
handler(event) {
|
|
31
33
|
engine.handleRequest(event.node.req, event.node.res);
|
|
32
34
|
event._handled = true;
|
|
@@ -44,5 +46,5 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
}));
|
|
47
|
-
log(
|
|
49
|
+
log(`Socket.IO server ready on ${SOCKET_PATH}/`);
|
|
48
50
|
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type PluginScope = 'user' | 'project' | 'local' | 'managed';
|
|
2
|
+
export interface PluginManifest {
|
|
3
|
+
name: string;
|
|
4
|
+
version?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
author?: {
|
|
7
|
+
name?: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
url?: string;
|
|
10
|
+
};
|
|
11
|
+
homepage?: string;
|
|
12
|
+
repository?: string;
|
|
13
|
+
license?: string;
|
|
14
|
+
keywords?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface InstalledPlugin {
|
|
17
|
+
/** Plugin identifier (name@marketplace) */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Plugin name */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Marketplace name */
|
|
22
|
+
marketplace: string;
|
|
23
|
+
/** Installation scope */
|
|
24
|
+
scope: PluginScope;
|
|
25
|
+
/** Whether plugin is enabled */
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
/** Plugin manifest (if available from cache) */
|
|
28
|
+
manifest?: PluginManifest;
|
|
29
|
+
/** Path to plugin in cache (if found) */
|
|
30
|
+
cachePath?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface Marketplace {
|
|
33
|
+
/** Marketplace identifier */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Source (GitHub repo, URL, or local path) */
|
|
36
|
+
source: string;
|
|
37
|
+
/** Whether auto-update is enabled */
|
|
38
|
+
autoUpdate?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface PluginSkill {
|
|
41
|
+
name: string;
|
|
42
|
+
description: string;
|
|
43
|
+
content: string;
|
|
44
|
+
pluginName: string;
|
|
45
|
+
/** Full invocation name: plugin-name:skill-name */
|
|
46
|
+
fullName: string;
|
|
47
|
+
}
|
|
48
|
+
export interface PluginCommand {
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
content: string;
|
|
52
|
+
pluginName: string;
|
|
53
|
+
/** Full invocation name: plugin-name:command-name */
|
|
54
|
+
fullName: string;
|
|
55
|
+
}
|
|
56
|
+
export interface PluginAgent {
|
|
57
|
+
name: string;
|
|
58
|
+
description: string;
|
|
59
|
+
prompt: string;
|
|
60
|
+
pluginName: string;
|
|
61
|
+
}
|
|
62
|
+
export declare class PluginsManager {
|
|
63
|
+
private projectPath;
|
|
64
|
+
private pluginsCachePath;
|
|
65
|
+
private userClaudeDir;
|
|
66
|
+
constructor(projectPath: string, customCachePath?: string | null);
|
|
67
|
+
private readSettingsFile;
|
|
68
|
+
private getUserSettings;
|
|
69
|
+
private getProjectSettings;
|
|
70
|
+
private getLocalSettings;
|
|
71
|
+
private parsePluginId;
|
|
72
|
+
private findPluginInCache;
|
|
73
|
+
private readPluginManifest;
|
|
74
|
+
private normalizePluginList;
|
|
75
|
+
getInstalledPlugins(): InstalledPlugin[];
|
|
76
|
+
getMarketplaces(): Marketplace[];
|
|
77
|
+
private parseFrontmatter;
|
|
78
|
+
getPluginSkills(pluginPath: string, pluginName: string): PluginSkill[];
|
|
79
|
+
getPluginCommands(pluginPath: string, pluginName: string): PluginCommand[];
|
|
80
|
+
getPluginAgents(pluginPath: string, pluginName: string): PluginAgent[];
|
|
81
|
+
getAllPluginSkills(): PluginSkill[];
|
|
82
|
+
getAllPluginCommands(): PluginCommand[];
|
|
83
|
+
getAllPluginAgents(): PluginAgent[];
|
|
84
|
+
}
|