-
Notifications
You must be signed in to change notification settings - Fork 2.6k
WIP: Laminar tracing groundwork (pending clarification) #8325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Introduce LaminarService (lightweight, no-op if disabled)\n- Start span in Task.submitUserMessage() and end in attemptCompletionTool()\n- Add types shim at src/types/lmnr.d.ts to avoid missing module types\n- Tests pass (cd src && npx vitest run)\n- Lint passes (pnpm run lint)\n\nNote: groundwork for porting cline/cline#5862; pending clarification on full scope.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-review: judging my own code — impartiality module returned 404.
| * Safe no-op when disabled; still returns an id for balanced calls. | ||
| */ | ||
| public startSpan(name: string, attributes: Attributes = {}): string { | ||
| const id = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: Not a true no-op when disabled. startSpan/endSpan record spans and debugSpan logs even if initialize() never enables tracing. Gate behavior behind enabled (bail early in startSpan/endSpan; guard debug/debugSpan) to avoid console noise and memory overhead.
| // Try to dynamically load the SDK if enabled | ||
| if (this.enabled) { | ||
| try { | ||
| const mod = await import("@lmnr-ai/lmnr") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Dynamic import likely needs default handling. If the SDK exports default, future calls like this.sdk.init may fail. Normalize the module:
| const mod = await import("@lmnr-ai/lmnr") | |
| const mod = await import("@lmnr-ai/lmnr"); | |
| this.sdk = (mod as any).default ?? mod; |
|
|
||
| // End current task.step span if active | ||
| try { | ||
| if ((cline as any).laminarSpanId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Accessing a private field via (cline as any).laminarSpanId bypasses types and couples modules. Prefer a Task instance method to end the active span (or encapsulate span lifecycle within Task).
|
|
||
| // Start a tracing span for this user turn | ||
| try { | ||
| this.laminarSpanId = laminar.startSpan("task.step", { taskId: this.taskId }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Span starts here but ends in attemptCompletionTool. If control flow exits early or errors differently, spans can remain open. Consider centralizing lifecycle in Task (e.g., try/finally) or using a Task event hook to end the span reliably.
|
|
||
| // Simple in-memory span store and active stack | ||
| private spans = new Map<string, InternalSpan>() | ||
| private activeStack: string[] = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: activeStack is process-global; concurrent tasks may interleave and corrupt parent/child relationships. Use AsyncLocalStorage for per-async-context stacks or maintain stacks keyed by sessionId/taskId.
| private debug(msg: string) { | ||
| // Keep logs minimal to avoid noise | ||
| try { | ||
| console.log(msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: console.log in debug() adds noise and may violate lint rules. Prefer console.debug or a central logger, and gate logs behind an opt-in debug flag and/or enabled.
| @@ -0,0 +1,4 @@ | |||
| declare module "@lmnr-ai/lmnr" { | |||
| const mod: any | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Type shim assumes a default export; if the SDK migrates to named exports this could mislead consumers. Consider exporting both default and named to keep flexibility.
This PR introduces a minimal LaminarService wrapper and wires basic task.step span start/end around user messages and attempt_completion.\n\nChanges:\n- Added LaminarService (safe no-op wrapper with future SDK hook) at src/services/laminar/LaminarService.ts\n- Start span in Task.submitUserMessage() and end in attemptCompletionTool()\n- Add type shim src/types/lmnr.d.ts to avoid missing module type error\n- Tests pass: cd src && npx vitest run\n- Lint passes: pnpm run lint\n\nThis is groundwork pending clarification for full port of cline/cline#5862.