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.
- package/README.md +74 -4
- package/agents/CONTRIBUTING.md +296 -0
- package/agents/README.md +174 -0
- package/agents/daemon-method-selection.md +370 -0
- package/agents/integration-guides/cpp-best-practices.md +218 -0
- package/agents/integration-guides/cpp-ros-integration.md +88 -0
- package/agents/log-analysis.md +218 -0
- package/agents/log-help.md +226 -0
- package/agents/log-init.md +933 -0
- package/agents/log-it.md +1126 -0
- package/bin/init.js +4 -4
- package/dist/bin/init.js +31 -0
- package/dist/browser.d.ts +28 -0
- package/dist/browser.js +91 -0
- package/dist/config-schema.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/init.d.ts +44 -2
- package/dist/init.js +460 -30
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +30 -4
- package/dist/node.d.ts +13 -0
- package/dist/node.js +67 -0
- package/dist/resources/agents/CONTRIBUTING.md +296 -0
- package/dist/resources/agents/README.md +174 -0
- package/dist/resources/agents/daemon-method-selection.md +370 -0
- package/dist/resources/agents/integration-guides/cpp-best-practices.md +218 -0
- package/dist/resources/agents/integration-guides/cpp-ros-integration.md +88 -0
- package/dist/resources/agents/log-analysis.md +218 -0
- package/dist/resources/agents/log-help.md +226 -0
- package/dist/resources/agents/log-init.md +933 -0
- package/dist/resources/agents/log-it.md +1126 -0
- package/dist/resources/cpp/drtrace_sink.hpp +1249 -0
- package/dist/transport.js +5 -1
- package/dist/types.d.ts +8 -2
- package/package.json +28 -4
- package/.eslintrc.js +0 -20
- package/jest.config.js +0 -11
- package/src/client.ts +0 -68
- package/src/config-schema.ts +0 -115
- package/src/config.ts +0 -326
- package/src/index.ts +0 -3
- package/src/init.ts +0 -451
- package/src/logger.ts +0 -56
- package/src/queue.ts +0 -105
- package/src/transport.ts +0 -60
- package/src/types.ts +0 -20
- package/tests/client.test.ts +0 -66
- package/tests/config-schema.test.ts +0 -198
- package/tests/config.test.ts +0 -456
- package/tests/queue.test.ts +0 -72
- package/tests/transport.test.ts +0 -52
- 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
|
-
//
|
|
176
|
-
|
|
177
|
-
|
|
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
|
|
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
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
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
|
|
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
|
|
222
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
366
|
-
|
|
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
|
|
372
|
-
console.log(`
|
|
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;
|