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