@oro.ad/nuxt-claude-devtools 1.0.7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +180 -13
  2. package/dist/client/200.html +1 -1
  3. package/dist/client/404.html +1 -1
  4. package/dist/client/_nuxt/{B1H6wO_D.js → 08Mb3FOO.js} +1 -1
  5. package/dist/client/_nuxt/BMi2eT6G.js +1 -0
  6. package/dist/client/_nuxt/BiBLVxWh.js +1 -0
  7. package/dist/client/_nuxt/BnRGpZsC.js +8 -0
  8. package/dist/client/_nuxt/C2GhPw5d.js +7 -0
  9. package/dist/client/_nuxt/CLKqRoht.js +1 -0
  10. package/dist/client/_nuxt/CPQSDiF7.js +12 -0
  11. package/dist/client/_nuxt/CSlPuO5s.js +59 -0
  12. package/dist/client/_nuxt/D8683igF.js +7 -0
  13. package/dist/client/_nuxt/DBIw6BGF.js +1 -0
  14. package/dist/client/_nuxt/DCgjfr8H.js +9 -0
  15. package/dist/client/_nuxt/MarkdownContent.WwTYmYZK.css +1 -0
  16. package/dist/client/_nuxt/{D-z88P1l.js → b4Upel01.js} +1 -1
  17. package/dist/client/_nuxt/bl5iU4Kz.js +1 -0
  18. package/dist/client/_nuxt/builds/latest.json +1 -1
  19. package/dist/client/_nuxt/builds/meta/35284331-5e85-46e0-9058-988fea05336c.json +1 -0
  20. package/dist/client/_nuxt/entry.BhHeZ_Nj.css +1 -0
  21. package/dist/client/_nuxt/index.Bomb3OYy.css +1 -0
  22. package/dist/client/_nuxt/nKfsBgPE.js +4 -0
  23. package/dist/client/_nuxt/{BpkYThsl.js → o1jjB-UO.js} +1 -1
  24. package/dist/client/agents/index.html +1 -0
  25. package/dist/client/commands/index.html +1 -0
  26. package/dist/client/docs/index.html +1 -0
  27. package/dist/client/index.html +1 -1
  28. package/dist/client/mcp/index.html +1 -1
  29. package/dist/client/skills/index.html +1 -0
  30. package/dist/module.d.mts +1 -0
  31. package/dist/module.json +1 -1
  32. package/dist/module.mjs +10 -4
  33. package/dist/runtime/logger.js +18 -0
  34. package/dist/runtime/server/agents-manager.d.ts +31 -0
  35. package/dist/runtime/server/agents-manager.js +193 -0
  36. package/dist/runtime/server/claude-session.d.ts +15 -0
  37. package/dist/runtime/server/claude-session.js +456 -5
  38. package/dist/runtime/server/commands-manager.d.ts +24 -0
  39. package/dist/runtime/server/commands-manager.js +132 -0
  40. package/dist/runtime/server/docs-manager.d.ts +48 -0
  41. package/dist/runtime/server/docs-manager.js +189 -0
  42. package/dist/runtime/server/history-manager.d.ts +24 -0
  43. package/dist/runtime/server/history-manager.js +184 -0
  44. package/dist/runtime/server/skills-manager.d.ts +36 -0
  45. package/dist/runtime/server/skills-manager.js +210 -0
  46. package/dist/runtime/types.d.ts +156 -0
  47. package/dist/runtime/types.js +0 -0
  48. package/package.json +16 -1
  49. package/dist/client/_nuxt/C2ORx7Gd.js +0 -1
  50. package/dist/client/_nuxt/CfGtRVGd.js +0 -4
  51. package/dist/client/_nuxt/DJn_CTvm.js +0 -1
  52. package/dist/client/_nuxt/EMyRkg8p.js +0 -1
  53. package/dist/client/_nuxt/PGt8fA_Y.js +0 -1
  54. package/dist/client/_nuxt/builds/meta/88c99fa0-10e0-4015-a61a-e0c6d7a01859.json +0 -1
  55. package/dist/client/_nuxt/entry.Ci1n7Rlt.css +0 -1
package/dist/module.mjs CHANGED
@@ -6,7 +6,7 @@ import { SOCKET_PATH, destroyClaudeSession } from '../dist/runtime/server/claude
6
6
 
7
7
  const DEVTOOLS_UI_ROUTE = "/__claude-devtools";
8
8
  const DEVTOOLS_UI_LOCAL_PORT = 3300;
9
- function setupDevToolsUI(nuxt, resolver) {
9
+ function setupDevToolsUI(nuxt, resolver, options = {}) {
10
10
  const clientPath = resolver.resolve("./client");
11
11
  const isProductionBuild = existsSync(clientPath);
12
12
  if (isProductionBuild) {
@@ -30,13 +30,14 @@ function setupDevToolsUI(nuxt, resolver) {
30
30
  });
31
31
  }
32
32
  nuxt.hook("devtools:customTabs", (tabs) => {
33
+ const hash = options.debug ? "#debug=true" : "";
33
34
  tabs.push({
34
35
  name: "claude-ai",
35
36
  title: "AI",
36
37
  icon: "carbon:machine-learning-model",
37
38
  view: {
38
39
  type: "iframe",
39
- src: DEVTOOLS_UI_ROUTE
40
+ src: `${DEVTOOLS_UI_ROUTE}${hash}`
40
41
  }
41
42
  });
42
43
  });
@@ -50,6 +51,7 @@ const module$1 = defineNuxtModule({
50
51
  },
51
52
  defaults: {
52
53
  enabled: true,
54
+ debug: false,
53
55
  claude: {
54
56
  command: "claude",
55
57
  args: []
@@ -59,6 +61,9 @@ const module$1 = defineNuxtModule({
59
61
  if (!nuxt.options.dev || !options.enabled) {
60
62
  return;
61
63
  }
64
+ if (options.debug) {
65
+ process.env.CLAUDE_DEVTOOLS_DEBUG = "true";
66
+ }
62
67
  const resolver = createResolver(import.meta.url);
63
68
  const tunnel = getTunnelConfig();
64
69
  if (tunnel) {
@@ -75,7 +80,8 @@ const module$1 = defineNuxtModule({
75
80
  };
76
81
  nuxt.options.runtimeConfig.public.claudeDevtools = {
77
82
  socketPath: SOCKET_PATH,
78
- tunnelOrigin: tunnel?.origin || null
83
+ tunnelOrigin: tunnel?.origin || null,
84
+ debug: options?.debug || false
79
85
  };
80
86
  addServerPlugin(resolver.resolve("./runtime/server/plugins/socket.io"));
81
87
  log("Added Socket.IO Nitro plugin");
@@ -83,7 +89,7 @@ const module$1 = defineNuxtModule({
83
89
  log("Cleaning up Claude session");
84
90
  destroyClaudeSession();
85
91
  });
86
- setupDevToolsUI(nuxt, resolver);
92
+ setupDevToolsUI(nuxt, resolver, { debug: options.debug });
87
93
  }
88
94
  });
89
95
 
@@ -1,7 +1,25 @@
1
1
  const PREFIX = "[nuxt-claude-devtools]";
2
+ let _debugEnabled = null;
3
+ function isDebugEnabled() {
4
+ if (_debugEnabled !== null) {
5
+ return _debugEnabled;
6
+ }
7
+ try {
8
+ const { useRuntimeConfig } = require("nitropack/runtime");
9
+ const config = useRuntimeConfig();
10
+ _debugEnabled = config.public?.claudeDevtools?.debug === true;
11
+ return _debugEnabled;
12
+ } catch {
13
+ _debugEnabled = process.env.CLAUDE_DEVTOOLS_DEBUG === "true";
14
+ return _debugEnabled;
15
+ }
16
+ }
2
17
  export function createLogger(subsystem, options = {}) {
3
18
  const tag = `${PREFIX} [${subsystem}]`;
4
19
  return function log(message, data) {
20
+ if (!isDebugEnabled()) {
21
+ return;
22
+ }
5
23
  const ts = options.timestamp ? ` [${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
6
24
  if (data !== void 0) {
7
25
  console.log(`${tag}${ts} ${message}`, data);
@@ -0,0 +1,31 @@
1
+ export interface Agent {
2
+ name: string;
3
+ description: string;
4
+ prompt: string;
5
+ rawContent: string;
6
+ tools?: string[];
7
+ disallowedTools?: string[];
8
+ model?: string;
9
+ permissionMode?: 'default' | 'acceptEdits' | 'dontAsk' | 'bypassPermissions' | 'plan';
10
+ skills?: string[];
11
+ updatedAt: string;
12
+ }
13
+ export declare class AgentsManager {
14
+ private agentsDir;
15
+ constructor(projectPath: string);
16
+ private parseFrontmatter;
17
+ private buildFrontmatter;
18
+ getAgents(): Agent[];
19
+ getAgent(name: string): Agent | null;
20
+ saveAgent(agent: {
21
+ name: string;
22
+ description: string;
23
+ prompt: string;
24
+ tools?: string[];
25
+ disallowedTools?: string[];
26
+ model?: string;
27
+ permissionMode?: Agent['permissionMode'];
28
+ skills?: string[];
29
+ }): Agent;
30
+ deleteAgent(name: string): boolean;
31
+ }
@@ -0,0 +1,193 @@
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import { createLogger } from "../logger.js";
4
+ const log = createLogger("agents", { timestamp: true });
5
+ export class AgentsManager {
6
+ agentsDir;
7
+ constructor(projectPath) {
8
+ this.agentsDir = join(projectPath, ".claude", "agents");
9
+ if (!existsSync(this.agentsDir)) {
10
+ mkdirSync(this.agentsDir, { recursive: true });
11
+ log("Created agents directory", { path: this.agentsDir });
12
+ }
13
+ }
14
+ // Parse YAML frontmatter from markdown content
15
+ parseFrontmatter(content) {
16
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
17
+ const match = content.match(frontmatterRegex);
18
+ if (!match) {
19
+ return { frontmatter: {}, body: content.trim() };
20
+ }
21
+ const [, yaml, body] = match;
22
+ const frontmatter = {};
23
+ let inSkillsArray = false;
24
+ const skillsList = [];
25
+ for (const line of yaml.split("\n")) {
26
+ if (inSkillsArray) {
27
+ const trimmed = line.trim();
28
+ if (trimmed.startsWith("- ")) {
29
+ skillsList.push(trimmed.slice(2).trim());
30
+ continue;
31
+ } else if (trimmed && !trimmed.startsWith("-")) {
32
+ inSkillsArray = false;
33
+ } else {
34
+ continue;
35
+ }
36
+ }
37
+ const colonIndex = line.indexOf(":");
38
+ if (colonIndex === -1) continue;
39
+ const key = line.slice(0, colonIndex).trim();
40
+ const value = line.slice(colonIndex + 1).trim();
41
+ switch (key) {
42
+ case "name":
43
+ frontmatter.name = value;
44
+ break;
45
+ case "description":
46
+ frontmatter.description = value;
47
+ break;
48
+ case "tools":
49
+ frontmatter.tools = value;
50
+ break;
51
+ case "disallowedTools":
52
+ frontmatter.disallowedTools = value;
53
+ break;
54
+ case "model":
55
+ frontmatter.model = value;
56
+ break;
57
+ case "permissionMode":
58
+ frontmatter.permissionMode = value;
59
+ break;
60
+ case "skills":
61
+ if (value) {
62
+ frontmatter.skills = value.split(",").map((s) => s.trim()).filter((s) => s);
63
+ } else {
64
+ inSkillsArray = true;
65
+ }
66
+ break;
67
+ }
68
+ }
69
+ if (skillsList.length > 0) {
70
+ frontmatter.skills = skillsList;
71
+ }
72
+ return { frontmatter, body: body.trim() };
73
+ }
74
+ // Build frontmatter string
75
+ buildFrontmatter(agent) {
76
+ const lines = ["---"];
77
+ if (agent.name) {
78
+ lines.push(`name: ${agent.name}`);
79
+ }
80
+ if (agent.description) {
81
+ lines.push(`description: ${agent.description}`);
82
+ }
83
+ if (agent.tools && agent.tools.length > 0) {
84
+ lines.push(`tools: ${agent.tools.join(", ")}`);
85
+ }
86
+ if (agent.disallowedTools && agent.disallowedTools.length > 0) {
87
+ lines.push(`disallowedTools: ${agent.disallowedTools.join(", ")}`);
88
+ }
89
+ if (agent.model) {
90
+ lines.push(`model: ${agent.model}`);
91
+ }
92
+ if (agent.permissionMode) {
93
+ lines.push(`permissionMode: ${agent.permissionMode}`);
94
+ }
95
+ if (agent.skills && agent.skills.length > 0) {
96
+ lines.push("skills:");
97
+ for (const skill of agent.skills) {
98
+ lines.push(` - ${skill}`);
99
+ }
100
+ }
101
+ lines.push("---");
102
+ return lines.join("\n");
103
+ }
104
+ // Get all agents
105
+ getAgents() {
106
+ const agents = [];
107
+ if (!existsSync(this.agentsDir)) return agents;
108
+ const entries = readdirSync(this.agentsDir);
109
+ for (const entry of entries) {
110
+ if (!entry.endsWith(".md")) continue;
111
+ const fullPath = join(this.agentsDir, entry);
112
+ const stat = statSync(fullPath);
113
+ if (stat.isDirectory()) continue;
114
+ const rawContent = readFileSync(fullPath, "utf-8");
115
+ const { frontmatter, body } = this.parseFrontmatter(rawContent);
116
+ agents.push({
117
+ name: frontmatter.name || basename(entry, ".md"),
118
+ description: frontmatter.description || "",
119
+ prompt: body,
120
+ rawContent,
121
+ tools: frontmatter.tools ? frontmatter.tools.split(",").map((s) => s.trim()) : void 0,
122
+ disallowedTools: frontmatter.disallowedTools ? frontmatter.disallowedTools.split(",").map((s) => s.trim()) : void 0,
123
+ model: frontmatter.model,
124
+ permissionMode: frontmatter.permissionMode,
125
+ skills: frontmatter.skills,
126
+ updatedAt: stat.mtime.toISOString()
127
+ });
128
+ }
129
+ return agents.sort((a, b) => a.name.localeCompare(b.name));
130
+ }
131
+ // Get single agent
132
+ getAgent(name) {
133
+ const fileName = name.endsWith(".md") ? name : `${name}.md`;
134
+ const fullPath = join(this.agentsDir, fileName);
135
+ if (!existsSync(fullPath)) return null;
136
+ const stat = statSync(fullPath);
137
+ const rawContent = readFileSync(fullPath, "utf-8");
138
+ const { frontmatter, body } = this.parseFrontmatter(rawContent);
139
+ return {
140
+ name: frontmatter.name || basename(fileName, ".md"),
141
+ description: frontmatter.description || "",
142
+ prompt: body,
143
+ rawContent,
144
+ tools: frontmatter.tools ? frontmatter.tools.split(",").map((s) => s.trim()) : void 0,
145
+ disallowedTools: frontmatter.disallowedTools ? frontmatter.disallowedTools.split(",").map((s) => s.trim()) : void 0,
146
+ model: frontmatter.model,
147
+ permissionMode: frontmatter.permissionMode,
148
+ skills: frontmatter.skills,
149
+ updatedAt: stat.mtime.toISOString()
150
+ };
151
+ }
152
+ // Create or update agent
153
+ saveAgent(agent) {
154
+ const safeName = agent.name.replace(/[^\w-]/g, "-").toLowerCase();
155
+ const fileName = `${safeName}.md`;
156
+ const fullPath = join(this.agentsDir, fileName);
157
+ const frontmatter = this.buildFrontmatter({
158
+ name: safeName,
159
+ description: agent.description,
160
+ tools: agent.tools,
161
+ disallowedTools: agent.disallowedTools,
162
+ model: agent.model,
163
+ permissionMode: agent.permissionMode,
164
+ skills: agent.skills
165
+ });
166
+ const rawContent = `${frontmatter}
167
+
168
+ ${agent.prompt}`;
169
+ writeFileSync(fullPath, rawContent, "utf-8");
170
+ log("Saved agent", { name: safeName, path: fullPath });
171
+ return {
172
+ name: safeName,
173
+ description: agent.description,
174
+ prompt: agent.prompt,
175
+ rawContent,
176
+ tools: agent.tools,
177
+ disallowedTools: agent.disallowedTools,
178
+ model: agent.model,
179
+ permissionMode: agent.permissionMode,
180
+ skills: agent.skills,
181
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
182
+ };
183
+ }
184
+ // Delete agent
185
+ deleteAgent(name) {
186
+ const fileName = name.endsWith(".md") ? name : `${name}.md`;
187
+ const fullPath = join(this.agentsDir, fileName);
188
+ if (!existsSync(fullPath)) return false;
189
+ unlinkSync(fullPath);
190
+ log("Deleted agent", { name });
191
+ return true;
192
+ }
193
+ }
@@ -11,9 +11,24 @@ export declare class ClaudeSession {
11
11
  private io;
12
12
  private isProcessing;
13
13
  private continueSession;
14
+ private historyManager;
15
+ private docsManager;
16
+ private commandsManager;
17
+ private agentsManager;
18
+ private skillsManager;
19
+ private claudeSessionId;
20
+ private parseBuffer;
21
+ private currentContentBlocks;
22
+ private currentMessageId;
23
+ private currentModel;
24
+ private accumulatedText;
14
25
  constructor(config: ClaudeSessionConfig);
15
26
  attachSocketIO(io: SocketServer): void;
16
27
  destroy(): void;
28
+ private resetStreamState;
29
+ private buildSystemPrompt;
30
+ private parseStreamChunk;
31
+ private processStreamEvent;
17
32
  private sendMessage;
18
33
  private getMcpServers;
19
34
  private addMcpServer;