drtrace 0.2.0 → 0.4.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 (53) hide show
  1. package/README.md +74 -4
  2. package/agents/CONTRIBUTING.md +296 -0
  3. package/agents/README.md +174 -0
  4. package/agents/daemon-method-selection.md +370 -0
  5. package/agents/integration-guides/cpp-best-practices.md +218 -0
  6. package/agents/integration-guides/cpp-ros-integration.md +88 -0
  7. package/agents/log-analysis.md +218 -0
  8. package/agents/log-help.md +226 -0
  9. package/agents/log-init.md +933 -0
  10. package/agents/log-it.md +1126 -0
  11. package/bin/init.js +4 -4
  12. package/dist/bin/init.js +31 -0
  13. package/dist/browser.d.ts +28 -0
  14. package/dist/browser.js +91 -0
  15. package/dist/config-schema.d.ts +2 -2
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +2 -2
  18. package/dist/init.d.ts +44 -2
  19. package/dist/init.js +460 -30
  20. package/dist/logger.d.ts +7 -0
  21. package/dist/logger.js +30 -4
  22. package/dist/node.d.ts +13 -0
  23. package/dist/node.js +67 -0
  24. package/dist/resources/agents/CONTRIBUTING.md +296 -0
  25. package/dist/resources/agents/README.md +174 -0
  26. package/dist/resources/agents/daemon-method-selection.md +370 -0
  27. package/dist/resources/agents/integration-guides/cpp-best-practices.md +218 -0
  28. package/dist/resources/agents/integration-guides/cpp-ros-integration.md +88 -0
  29. package/dist/resources/agents/log-analysis.md +218 -0
  30. package/dist/resources/agents/log-help.md +226 -0
  31. package/dist/resources/agents/log-init.md +933 -0
  32. package/dist/resources/agents/log-it.md +1126 -0
  33. package/dist/resources/cpp/drtrace_sink.hpp +1249 -0
  34. package/dist/transport.js +5 -1
  35. package/dist/types.d.ts +8 -2
  36. package/package.json +28 -4
  37. package/.eslintrc.js +0 -20
  38. package/jest.config.js +0 -11
  39. package/src/client.ts +0 -68
  40. package/src/config-schema.ts +0 -115
  41. package/src/config.ts +0 -326
  42. package/src/index.ts +0 -3
  43. package/src/init.ts +0 -451
  44. package/src/logger.ts +0 -56
  45. package/src/queue.ts +0 -105
  46. package/src/transport.ts +0 -60
  47. package/src/types.ts +0 -20
  48. package/tests/client.test.ts +0 -66
  49. package/tests/config-schema.test.ts +0 -198
  50. package/tests/config.test.ts +0 -456
  51. package/tests/queue.test.ts +0 -72
  52. package/tests/transport.test.ts +0 -52
  53. package/tsconfig.json +0 -18
package/dist/init.js CHANGED
@@ -44,10 +44,13 @@ exports.ProjectInitializer = void 0;
44
44
  exports.runInitProject = runInitProject;
45
45
  const fs = __importStar(require("fs"));
46
46
  const path = __importStar(require("path"));
47
+ const child_process_1 = require("child_process");
47
48
  const prompts_1 = __importDefault(require("prompts"));
48
49
  const config_schema_1 = require("./config-schema");
49
50
  class ProjectInitializer {
50
51
  constructor(projectRoot = process.cwd()) {
52
+ // Track copied agent files for summary display
53
+ this.copiedAgentFiles = [];
51
54
  this.projectRoot = projectRoot;
52
55
  this.drtraceDir = path.join(projectRoot, "_drtrace");
53
56
  this.configPath = path.join(this.drtraceDir, "config.json");
@@ -58,13 +61,18 @@ class ProjectInitializer {
58
61
  async runInteractive() {
59
62
  console.log("\nšŸš€ DrTrace Project Initialization\n");
60
63
  console.log("=".repeat(50));
64
+ // Check for existing config FIRST (before collecting project info)
65
+ if (!(await this.handleExistingConfig())) {
66
+ console.log("\nāŒ Initialization cancelled.");
67
+ return false;
68
+ }
61
69
  // Collect project information
62
70
  console.log("\nšŸ“‹ Project Information:");
63
71
  const projectName = await this.promptText("Project name", "my-app");
64
72
  const applicationId = await this.promptText("Application ID", projectName.toLowerCase().replace(/\s+/g, "-"));
65
73
  // Language selection
66
74
  console.log("\nšŸ”§ Technology Stack:");
67
- const language = await this.promptChoice("Select language/runtime:", ["python", "javascript", "both"], "javascript");
75
+ const language = await this.promptChoice("Select language/runtime:", ["python", "javascript", "cpp", "both"], "javascript");
68
76
  // Daemon configuration
69
77
  console.log("\nšŸ“” DrTrace Daemon Configuration:");
70
78
  const daemonUrl = await this.promptText("Daemon URL", "http://localhost:8001");
@@ -80,11 +88,6 @@ class ProjectInitializer {
80
88
  if (agentEnabled) {
81
89
  agentFramework = await this.promptChoice("Select agent framework:", ["bmad", "langchain", "other"], "bmad");
82
90
  }
83
- // Check for existing config
84
- if (!this.handleExistingConfig()) {
85
- console.log("\nāŒ Initialization cancelled.");
86
- return false;
87
- }
88
91
  // Create directory structure
89
92
  this.createDirectoryStructure();
90
93
  // Generate and save main config
@@ -106,6 +109,12 @@ class ProjectInitializer {
106
109
  if (agentEnabled) {
107
110
  this.copyAgentSpec();
108
111
  }
112
+ // Copy framework-specific guides for C++ projects
113
+ if (language === "cpp" || language === "both") {
114
+ this.copyFrameworkGuides();
115
+ // Copy C++ header file for C++ projects
116
+ this.copyCppHeader();
117
+ }
109
118
  // Generate .env.example
110
119
  this.generateEnvExample(config);
111
120
  // Generate README
@@ -165,23 +174,47 @@ class ProjectInitializer {
165
174
  return response.value || [];
166
175
  }
167
176
  /**
168
- * Handle existing config
177
+ * Handle existing config - prompt user before overwriting
178
+ *
179
+ * Returns true if initialization should proceed, false if user declined.
169
180
  */
170
- handleExistingConfig() {
181
+ async handleExistingConfig() {
171
182
  if (!fs.existsSync(this.configPath)) {
172
- return true;
183
+ return true; // No existing config, proceed
173
184
  }
174
185
  console.log(`\nāš ļø Configuration already exists at ${this.configPath}`);
175
- // In interactive mode, we would prompt here
176
- // For now, we'll require confirmation via prompts
177
- return true;
186
+ // Prompt user if they want to overwrite
187
+ const overwriteResponse = await (0, prompts_1.default)({
188
+ type: "confirm",
189
+ name: "value",
190
+ message: "Overwrite existing configuration?",
191
+ initial: false, // Default to No (safe)
192
+ });
193
+ if (!overwriteResponse.value) {
194
+ return false; // User declined, stop initialization
195
+ }
196
+ // Optional: Offer backup
197
+ const backupResponse = await (0, prompts_1.default)({
198
+ type: "confirm",
199
+ name: "value",
200
+ message: "Create backup of existing config?",
201
+ initial: true, // Default to Yes (safe)
202
+ });
203
+ if (backupResponse.value) {
204
+ const backupPath = this.configPath + ".bak";
205
+ fs.copyFileSync(this.configPath, backupPath);
206
+ console.log(`āœ“ Backup created at ${backupPath}`);
207
+ }
208
+ return true; // User confirmed, proceed with overwrite
178
209
  }
179
210
  /**
180
211
  * Create _drtrace directory structure
181
212
  */
182
213
  createDirectoryStructure() {
183
214
  const agentsDir = path.join(this.drtraceDir, "agents");
215
+ const integrationGuidesDir = path.join(this.drtraceDir, "agents", "integration-guides");
184
216
  fs.mkdirSync(agentsDir, { recursive: true });
217
+ fs.mkdirSync(integrationGuidesDir, { recursive: true });
185
218
  console.log(`āœ“ Created directory: ${this.drtraceDir}`);
186
219
  }
187
220
  /**
@@ -197,44 +230,400 @@ class ProjectInitializer {
197
230
  }
198
231
  }
199
232
  /**
200
- * Copy agent spec to _drtrace/agents/
233
+ * Copy all agent files from packaged resources to _drtrace/agents/
234
+ * Copies everything from agents/ directory including:
235
+ * - Agent spec files (*.md)
236
+ * - Integration guides (integration-guides/*.md)
237
+ * - Any other files (README.md, CONTRIBUTING.md, etc.)
201
238
  */
202
239
  copyAgentSpec() {
203
240
  try {
204
- const agentPath = path.join(this.drtraceDir, "agents", "log-analysis.md");
205
- const defaultSpec = this.getDefaultAgentSpec();
206
- fs.writeFileSync(agentPath, defaultSpec);
207
- console.log(`āœ“ Copied agent spec: ${agentPath}`);
241
+ // Try multiple locations for agents directory
242
+ const possibleAgentsDirs = [
243
+ // Installed package location - dist/resources/agents (production)
244
+ path.join(this.projectRoot, "node_modules", "drtrace", "dist", "resources", "agents"),
245
+ // Installed package location - agents (legacy, may be empty)
246
+ path.join(this.projectRoot, "node_modules", "drtrace", "agents"),
247
+ // Development mode (monorepo)
248
+ path.join(process.cwd(), "agents"),
249
+ // Relative to package
250
+ path.resolve(__dirname, "../../agents"),
251
+ // Relative to dist
252
+ path.resolve(__dirname, "../agents"),
253
+ ];
254
+ let agentsDir = null;
255
+ for (const dir of possibleAgentsDirs) {
256
+ if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
257
+ agentsDir = dir;
258
+ break;
259
+ }
260
+ }
261
+ if (!agentsDir) {
262
+ console.warn("āš ļø Could not find agents directory");
263
+ return;
264
+ }
265
+ // Copy all files recursively and track copied files
266
+ const copiedFiles = this.copyAgentsRecursive(agentsDir, path.join(this.drtraceDir, "agents"));
267
+ this.copiedAgentFiles.push(...copiedFiles);
208
268
  }
209
269
  catch (error) {
210
- console.warn(`āš ļø Could not copy agent spec: ${error}`);
270
+ console.warn(`āš ļø Could not copy agent files: ${error}`);
211
271
  }
212
272
  }
273
+ /**
274
+ * Recursively copy all files from sourceDir to targetDir
275
+ * Returns list of relative file paths copied (for summary display)
276
+ */
277
+ copyAgentsRecursive(sourceDir, targetDir, basePath = "") {
278
+ if (!fs.existsSync(targetDir)) {
279
+ fs.mkdirSync(targetDir, { recursive: true });
280
+ }
281
+ const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
282
+ const copiedFiles = [];
283
+ for (const entry of entries) {
284
+ const srcPath = path.join(sourceDir, entry.name);
285
+ const destPath = path.join(targetDir, entry.name);
286
+ const relativePath = basePath ? path.join(basePath, entry.name) : entry.name;
287
+ if (entry.isDirectory()) {
288
+ // Recursively copy directories
289
+ const subCopied = this.copyAgentsRecursive(srcPath, destPath, relativePath);
290
+ copiedFiles.push(...subCopied);
291
+ }
292
+ else {
293
+ // Copy file (no renaming needed - files are already named correctly)
294
+ fs.copyFileSync(srcPath, destPath);
295
+ copiedFiles.push(relativePath);
296
+ console.log(`āœ“ Copied ${relativePath}`);
297
+ }
298
+ }
299
+ // Print summary only at top level
300
+ if (!basePath && copiedFiles.length > 0) {
301
+ console.log(`āœ“ Successfully copied ${copiedFiles.length} file(s) from agents/`);
302
+ }
303
+ return copiedFiles;
304
+ }
305
+ /**
306
+ * Copy framework-specific integration guides to _drtrace/agents/integration-guides/
307
+ * Dynamically discovers all .md files in agents/integration-guides/ directory
308
+ * Guides are stored in agents folder so agents can access them on client side
309
+ */
310
+ copyFrameworkGuides() {
311
+ const integrationGuidesDir = path.join(this.drtraceDir, "agents", "integration-guides");
312
+ fs.mkdirSync(integrationGuidesDir, { recursive: true });
313
+ // Dynamically discover framework guides from agents/integration-guides/ directory
314
+ const rootGuidesDir = path.join(process.cwd(), "agents", "integration-guides");
315
+ let frameworkGuides = [];
316
+ // Try root agents/integration-guides/ first (development mode)
317
+ if (fs.existsSync(rootGuidesDir)) {
318
+ try {
319
+ const files = fs.readdirSync(rootGuidesDir);
320
+ frameworkGuides = files
321
+ .filter((file) => file.endsWith(".md"))
322
+ .map((file) => file.replace(/\.md$/, ""));
323
+ }
324
+ catch (error) {
325
+ // If directory exists but can't read it, warn and continue
326
+ console.warn(`āš ļø Could not read integration guides directory: ${error}`);
327
+ }
328
+ }
329
+ // If no guides found in development mode, try bundled resources (production mode)
330
+ if (frameworkGuides.length === 0) {
331
+ try {
332
+ // Try to load from bundled resources (production mode)
333
+ // Path: node_modules/drtrace/dist/resources/agents/integration-guides/
334
+ // Note: In production, __dirname points to dist/ directory
335
+ const bundledResourcesPath = path.join(__dirname, "resources", "agents", "integration-guides");
336
+ if (fs.existsSync(bundledResourcesPath)) {
337
+ const files = fs.readdirSync(bundledResourcesPath);
338
+ frameworkGuides = files
339
+ .filter((file) => file.endsWith(".md"))
340
+ .map((file) => file.replace(/\.md$/, ""));
341
+ }
342
+ }
343
+ catch (error) {
344
+ // If bundled resources not available, continue gracefully
345
+ // This is expected in development mode when resources aren't bundled yet
346
+ }
347
+ }
348
+ // Copy each discovered guide
349
+ for (const guideName of frameworkGuides) {
350
+ try {
351
+ const guideFilename = `${guideName}.md`;
352
+ const guidePath = path.join(integrationGuidesDir, guideFilename);
353
+ // Try root agents/integration-guides/ first (development mode)
354
+ const rootGuidePath = path.join(rootGuidesDir, guideFilename);
355
+ let content;
356
+ if (fs.existsSync(rootGuidePath)) {
357
+ content = fs.readFileSync(rootGuidePath, "utf-8");
358
+ }
359
+ else {
360
+ // Try to load from bundled resources (production mode)
361
+ try {
362
+ const bundledGuidePath = path.join(__dirname, "resources", "agents", "integration-guides", guideFilename);
363
+ if (fs.existsSync(bundledGuidePath)) {
364
+ content = fs.readFileSync(bundledGuidePath, "utf-8");
365
+ }
366
+ else {
367
+ // Skip if guide not found
368
+ continue;
369
+ }
370
+ }
371
+ catch (error) {
372
+ // Skip if guide not found
373
+ continue;
374
+ }
375
+ }
376
+ fs.writeFileSync(guidePath, content);
377
+ console.log(`āœ“ Copied framework guide: ${guidePath}`);
378
+ }
379
+ catch (error) {
380
+ console.warn(`āš ļø Could not copy ${guideName} framework guide: ${error}`);
381
+ }
382
+ }
383
+ }
384
+ /**
385
+ * Copy C++ header file to third_party/drtrace/ for C++ projects.
386
+ *
387
+ * This enables header-only integration:
388
+ * - Header is copied to third_party/drtrace/drtrace_sink.hpp
389
+ * - Users include it via #include "third_party/drtrace/drtrace_sink.hpp"
390
+ * - Note: third_party/drtrace/ should be committed to git (unlike _drtrace/ which is gitignored)
391
+ */
392
+ copyCppHeader() {
393
+ const sourcePath = this.findCppHeaderSource();
394
+ if (!sourcePath || !fs.existsSync(sourcePath)) {
395
+ console.warn("āš ļø Could not find drtrace_sink.hpp - C++ header-only integration " +
396
+ "will not be available.");
397
+ return;
398
+ }
399
+ // Destination: third_party/drtrace/drtrace_sink.hpp (committed to git)
400
+ const destDir = path.join(this.projectRoot, "third_party", "drtrace");
401
+ fs.mkdirSync(destDir, { recursive: true });
402
+ const destPath = path.join(destDir, "drtrace_sink.hpp");
403
+ try {
404
+ fs.copyFileSync(sourcePath, destPath);
405
+ console.log(`āœ“ Copied C++ header: ${destPath}`);
406
+ console.log(" Note: third_party/drtrace/ should be committed to git");
407
+ }
408
+ catch (error) {
409
+ console.warn(`āš ļø Failed to copy C++ header from ${sourcePath} to ${destPath}: ${error}`);
410
+ }
411
+ }
412
+ /**
413
+ * Find drtrace_sink.hpp source file for header-only C++ integration.
414
+ *
415
+ * Search order:
416
+ * 1. npm package location: dist/resources/cpp/drtrace_sink.hpp (production mode)
417
+ * 2. Monorepo development layout: packages/cpp/drtrace-client/src/drtrace_sink.hpp
418
+ * 3. pip package location: site-packages/drtrace_service/.../packages/cpp/drtrace-client/src/drtrace_sink.hpp (if Python available)
419
+ *
420
+ * @returns Path to header file if found, null otherwise
421
+ */
422
+ findCppHeaderSource() {
423
+ // 1. Check npm package location (production mode)
424
+ // Path: node_modules/drtrace/dist/resources/cpp/drtrace_sink.hpp
425
+ // In production, __dirname points to dist/ directory
426
+ const npmPackagePath = path.join(__dirname, "resources", "cpp", "drtrace_sink.hpp");
427
+ if (fs.existsSync(npmPackagePath)) {
428
+ return npmPackagePath;
429
+ }
430
+ // 2. Check monorepo location (development mode)
431
+ // Search upward from project root (max 6 levels)
432
+ let searchRoot = process.cwd();
433
+ for (let i = 0; i < 6; i++) {
434
+ const monorepoPath = path.join(searchRoot, "packages", "cpp", "drtrace-client", "src", "drtrace_sink.hpp");
435
+ if (fs.existsSync(monorepoPath)) {
436
+ return monorepoPath;
437
+ }
438
+ const parent = path.dirname(searchRoot);
439
+ if (parent === searchRoot) {
440
+ break; // Reached filesystem root
441
+ }
442
+ searchRoot = parent;
443
+ }
444
+ // 3. Check pip package location (if Python available)
445
+ // Try to use Python to find the package location
446
+ try {
447
+ const pythonCmd = `python3 -c "import drtrace_service; import os; print(os.path.dirname(drtrace_service.__file__))"`;
448
+ const packageDir = (0, child_process_1.execSync)(pythonCmd, { encoding: "utf-8" }).trim();
449
+ const pipPackagePath = path.join(packageDir, "packages", "cpp", "drtrace-client", "src", "drtrace_sink.hpp");
450
+ if (fs.existsSync(pipPackagePath)) {
451
+ return pipPackagePath;
452
+ }
453
+ }
454
+ catch (error) {
455
+ // Python not available or package not installed - continue
456
+ }
457
+ return null;
458
+ }
213
459
  /**
214
460
  * Get default agent spec from shared agents/ or bundled resources
215
461
  *
216
462
  * Search order:
217
463
  * 1. Root repo agents/ directory (development)
218
464
  * 2. Bundled default agent from node_modules
465
+ *
466
+ * @param agentName - Name of the agent: "log-analysis", "log-it", "log-init", or "log-help"
219
467
  */
220
- getDefaultAgentSpec() {
221
- // Try root agents/ first (development mode)
222
- const rootAgentPath = path.join(this.projectRoot, "..", "..", "agents", "log-analysis.default.md");
468
+ getDefaultAgentSpec(agentName = "log-analysis") {
469
+ // Try multiple possible locations for agents folder
470
+ // Search order optimized: installed package first (most common), then repo root (development)
471
+ const possiblePaths = [];
472
+ // 1. Try node_modules/drtrace/agents/ directly from project root (most common case)
473
+ const nodeModulesPath = path.join(this.projectRoot, "node_modules", "drtrace", "agents", `${agentName}.md`);
474
+ possiblePaths.push(nodeModulesPath);
475
+ // 2. Try to find from installed package location (if installed via npm)
223
476
  try {
224
- if (fs.existsSync(rootAgentPath)) {
225
- return fs.readFileSync(rootAgentPath, "utf-8");
477
+ // Try to resolve the main entry point first, then find package.json
478
+ const mainPath = require.resolve("drtrace");
479
+ const packageDir = path.dirname(mainPath);
480
+ // Go up to find package.json (main might be in dist/ or root)
481
+ let currentDir = packageDir;
482
+ for (let i = 0; i < 3; i++) {
483
+ const pkgJsonPath = path.join(currentDir, "package.json");
484
+ if (fs.existsSync(pkgJsonPath)) {
485
+ possiblePaths.push(path.join(currentDir, "agents", `${agentName}.md`));
486
+ break;
487
+ }
488
+ currentDir = path.dirname(currentDir);
226
489
  }
227
490
  }
228
491
  catch (error) {
229
- // Fall through to bundled resource
492
+ // Package not found, skip this path
493
+ }
494
+ // 3. From project root (when package is in monorepo or installed locally)
495
+ possiblePaths.push(path.join(this.projectRoot, "..", "..", "..", "agents", `${agentName}.md`));
496
+ // 4. Try absolute path from known repo structure
497
+ possiblePaths.push(path.resolve(this.projectRoot, "../../../agents", `${agentName}.md`));
498
+ for (const agentPath of possiblePaths) {
499
+ try {
500
+ if (fs.existsSync(agentPath)) {
501
+ return fs.readFileSync(agentPath, "utf-8");
502
+ }
503
+ }
504
+ catch (error) {
505
+ // Continue to next path
506
+ continue;
507
+ }
230
508
  }
231
509
  // Fallback to bundled default agent
232
- return this.getBundledAgentSpec();
510
+ return this.getBundledAgentSpec(agentName);
233
511
  }
234
512
  /**
235
513
  * Get bundled agent spec (fallback when root agents/ not available)
514
+ *
515
+ * @param agentName - Name of the agent: "log-analysis", "log-it", "log-init", or "log-help"
236
516
  */
237
- getBundledAgentSpec() {
517
+ getBundledAgentSpec(agentName = "log-analysis") {
518
+ if (agentName === "log-it") {
519
+ // Return minimal log-it agent spec
520
+ return `---
521
+ name: "log-it"
522
+ description: "Strategic Logging Assistant"
523
+ ---
524
+
525
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
526
+
527
+ \`\`\`xml
528
+ <agent id="log-it.agent.yaml" name="drtrace" title="Strategic Logging Assistant" icon="šŸ“">
529
+ <activation critical="MANDATORY">
530
+ <step n="1">Load persona from this current agent file (already in context)</step>
531
+ <step n="2">Remember: You are a Strategic Logging Assistant specializing in efficient, privacy-conscious logging</step>
532
+ <step n="3">NEVER suggest logging code without first seeing actual code context from the user</step>
533
+ <step n="4">When user provides code, detect language automatically and apply appropriate patterns</step>
534
+ <step n="5">Validate EVERY suggested log statement against all 5 criteria:
535
+ 1. **Efficiency**: Not in tight loops, uses lazy formatting, appropriate log level
536
+ 2. **Necessity**: Provides actionable insight, explains WHY not just THAT, prevents spam
537
+ 3. **No Sensitive Data**: Never logs passwords/tokens/PII, flags patterns, suggests masking
538
+ 4. **Code Context**: Strategic placement (entry/exit, external calls, errors, decisions)
539
+ 5. **Completeness**: Includes debug-worthy context (trace IDs, inputs/outputs, error details)
540
+ </step>
541
+ <step n="6">Always provide line numbers, log level reasoning, and copy-paste ready code</step>
542
+ <step n="7">Show greeting, then display numbered list of ALL menu items from menu section</step>
543
+ <step n="8">STOP and WAIT for user input - do NOT execute menu items automatically</step>
544
+ <step n="9">On user input: Process as natural language query or execute menu item if number/cmd provided</step>
545
+ </activation>
546
+
547
+ <persona>
548
+ <role>Strategic Logging Assistant</role>
549
+ <identity>Expert at adding strategic, efficient, and privacy-conscious logging to codebases</identity>
550
+ <communication_style>Clear and concise. Provides actionable logging suggestions with reasoning.</communication_style>
551
+ </persona>
552
+ \`\`\`
553
+
554
+ ## Strategic Logging Guide
555
+
556
+ This agent helps you add effective logging to your codebase.
557
+
558
+ ### How to Use
559
+
560
+ 1. Share your code file or snippet
561
+ 2. Describe what you want to log or debug
562
+ 3. Get strategic logging suggestions with reasoning
563
+ `;
564
+ }
565
+ if (agentName === "log-init") {
566
+ // Return minimal log-init agent spec
567
+ return `---
568
+ name: "log-init"
569
+ description: "DrTrace Setup Assistant"
570
+ ---
571
+
572
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
573
+
574
+ \`\`\`xml
575
+ <agent id="log-init.agent.yaml" name="drtrace" title="DrTrace Setup Assistant" icon="šŸ”§">
576
+ <activation critical="MANDATORY">
577
+ <step n="1">Load persona from this current agent file (already in context)</step>
578
+ <step n="2">Remember: You are a Setup Specialist for DrTrace integration</step>
579
+ <step n="3">NEVER suggest setup without first reading and analyzing actual project files</step>
580
+ <step n="4">Show greeting, then display numbered list of ALL menu items from menu section</step>
581
+ <step n="5">STOP and WAIT for user input - do NOT execute menu items automatically</step>
582
+ </activation>
583
+
584
+ <persona>
585
+ <role>Setup Specialist</role>
586
+ <identity>Expert at analyzing project structures and suggesting intelligent DrTrace integration</identity>
587
+ <communication_style>Clear and educational. Reads and analyzes project files before suggesting setup.</communication_style>
588
+ </persona>
589
+ \`\`\`
590
+
591
+ ## Setup Guide
592
+
593
+ This agent helps you set up DrTrace in your project by analyzing your codebase and providing language-specific integration suggestions.
594
+ `;
595
+ }
596
+ if (agentName === "log-help") {
597
+ // Return minimal log-help agent spec
598
+ return `---
599
+ name: "log-help"
600
+ description: "DrTrace Setup Guide"
601
+ ---
602
+
603
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
604
+
605
+ \`\`\`xml
606
+ <agent id="log-help.agent.yaml" name="drtrace" title="DrTrace Setup Guide" icon="šŸ“˜">
607
+ <activation critical="MANDATORY">
608
+ <step n="1">Load persona from this current agent file (already in context)</step>
609
+ <step n="2">Remember: You are a Setup Guide Assistant</step>
610
+ <step n="3">Show greeting, then display numbered list of ALL menu items from menu section</step>
611
+ <step n="4">STOP and WAIT for user input - do NOT execute menu items automatically</step>
612
+ </activation>
613
+
614
+ <persona>
615
+ <role>Setup Guide Assistant</role>
616
+ <identity>Expert at providing step-by-step guidance for DrTrace setup</identity>
617
+ <communication_style>Patient and educational. Provides clear, actionable steps.</communication_style>
618
+ </persona>
619
+ \`\`\`
620
+
621
+ ## Setup Guide
622
+
623
+ This agent provides step-by-step guidance for setting up DrTrace in your project, tracking your progress and helping when you get stuck.
624
+ `;
625
+ }
626
+ // Default log-analysis agent spec
238
627
  return `---
239
628
  name: "log-analysis"
240
629
  description: "Log Analysis Agent"
@@ -340,10 +729,44 @@ import { ConfigSchema } from 'drtrace';
340
729
  const config = ConfigSchema.load('./_drtrace/config.json');
341
730
  \`\`\`
342
731
 
732
+ ## Starting the DrTrace Daemon
733
+
734
+ The DrTrace daemon must be running for your application to send logs. You have two options:
735
+
736
+ ### Option A: Docker Compose (Recommended)
737
+
738
+ The easiest way to start both the database and daemon:
739
+
740
+ \`\`\`bash
741
+ # From the DrTrace repository root
742
+ docker-compose up -d
743
+
744
+ # Verify it's running
745
+ curl http://localhost:8001/status
746
+ \`\`\`
747
+
748
+ ### Option B: Native Python Daemon
749
+
750
+ If you have Python and PostgreSQL installed:
751
+
752
+ \`\`\`bash
753
+ # Set database URL (if using PostgreSQL)
754
+ export DRTRACE_DATABASE_URL="postgresql://postgres:postgres@localhost:5432/drtrace"
755
+
756
+ # Start the daemon
757
+ uvicorn drtrace_service.api:app --host localhost --port 8001
758
+
759
+ # In another terminal, verify it's running
760
+ python -m drtrace_service status
761
+ \`\`\`
762
+
763
+ **Note**: The daemon must be running before your application can send logs. Keep the daemon terminal open while developing.
764
+
343
765
  ## Further Reading
344
766
 
345
767
  - See \`docs/\` for complete documentation
346
768
  - Check \`agents/\` for agent specifications
769
+ - Full quickstart guide: https://github.com/your-repo/docs/quickstart.md
347
770
  `;
348
771
  fs.writeFileSync(readmeFile, content);
349
772
  console.log(`āœ“ Generated: ${readmeFile}`);
@@ -362,14 +785,21 @@ const config = ConfigSchema.load('./_drtrace/config.json');
362
785
  }
363
786
  console.log(` • ${path.join(this.drtraceDir, ".env.example")}`);
364
787
  console.log(` • ${path.join(this.drtraceDir, "README.md")}`);
365
- if (config.agent?.enabled) {
366
- console.log(` • ${path.join(this.drtraceDir, "agents", "log-analysis.md")}`);
788
+ // List all copied agent files (includes integration-guides/)
789
+ if (this.copiedAgentFiles.length > 0) {
790
+ console.log("\nšŸ“‹ Agent Files:");
791
+ for (const agentFile of this.copiedAgentFiles.sort()) {
792
+ console.log(` • ${path.join(this.drtraceDir, "agents", agentFile)}`);
793
+ }
367
794
  }
368
795
  console.log("\nšŸ“– Next Steps:");
369
796
  console.log(` 1. Review ${this.configPath}`);
370
797
  console.log(` 2. Create .env: cp ${path.join(this.drtraceDir, ".env.example")} .env`);
371
- console.log(` 3. Start the daemon: drtrace daemon start`);
372
- console.log(` 4. Read ${path.join(this.drtraceDir, "README.md")} for more details`);
798
+ console.log(` 3. Start the daemon:`);
799
+ console.log(` Option A (Docker - Recommended): docker-compose up -d`);
800
+ console.log(` Option B (Native): uvicorn drtrace_service.api:app --host localhost --port 8001`);
801
+ console.log(` 4. Verify daemon: python -m drtrace_service status`);
802
+ console.log(` 5. Read ${path.join(this.drtraceDir, "README.md")} for more details`);
373
803
  console.log("\n" + "=".repeat(50) + "\n");
374
804
  }
375
805
  }
package/dist/logger.d.ts CHANGED
@@ -3,13 +3,20 @@ import { LogQueue } from './queue';
3
3
  export declare class DrTraceLogger {
4
4
  private queue;
5
5
  private applicationId;
6
+ private moduleName;
6
7
  private logLevel;
7
8
  private originalConsole?;
8
9
  constructor(opts: {
9
10
  queue: LogQueue;
10
11
  applicationId: string;
12
+ moduleName?: string;
11
13
  logLevel: LogLevel;
12
14
  });
15
+ /**
16
+ * Serialize a value to a string suitable for logging.
17
+ * Handles objects, arrays, errors, and primitives correctly.
18
+ */
19
+ private serialize;
13
20
  attachToConsole(): void;
14
21
  detachFromConsole(): void;
15
22
  log(level: LogLevel, message: string, context?: Record<string, unknown>): void;