@maestro-js/agent-skills 1.0.0-alpha.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.
@@ -0,0 +1,240 @@
1
+ ---
2
+ name: tracing
3
+ description: "Distributed tracing package built on OpenTelemetry with pluggable providers (Sentry, Maestro). Use when working with @maestro-js/tracing. Key capabilities: wrap functions for automatic span tracking, create active spans with duration measurement, proxy entire objects for tracing, serialize/deserialize trace context across process boundaries (dehydrate/hydrate), add custom log transports for span events, integrate Sentry as a tracing provider."
4
+ ---
5
+
6
+ # @maestro-js/tracing
7
+
8
+ Distributed tracing built on OpenTelemetry. Tracks function calls, durations, and parent/child relationships across the request lifecycle with pluggable providers (Sentry or the built-in Maestro tracer).
9
+
10
+ ## Quick Setup
11
+
12
+ ```ts
13
+ import { Tracing } from '@maestro-js/tracing'
14
+
15
+ // Use the default Maestro tracer (works out of the box)
16
+ const result = Tracing.startActiveSpan('my-operation', () => {
17
+ return doWork()
18
+ })
19
+
20
+ // Or set Sentry as the provider
21
+ import * as Sentry from '@sentry/node'
22
+ Tracing.setProvider(Tracing.providers.sentry(Sentry))
23
+ ```
24
+
25
+ ## Providers
26
+
27
+ ### Maestro (default)
28
+
29
+ The `MaestroTracerProvider` is set as the global OpenTelemetry tracer provider automatically on import. It wraps every span to capture attributes, start/end times, and parent span IDs, then logs them through the built-in `Log` transport system.
30
+
31
+ No configuration required -- it works immediately.
32
+
33
+ ### Sentry
34
+
35
+ Pass a Sentry SDK instance to configure Sentry as the tracing backend. The factory sets up the `SentrySampler`, `SentrySpanProcessor`, `SentryPropagator`, and `SentryContextManager`.
36
+
37
+ ```ts
38
+ import * as Sentry from '@sentry/node'
39
+ import { Tracing } from '@maestro-js/tracing'
40
+
41
+ Sentry.init({ dsn: '...', tracesSampleRate: 1.0 })
42
+ Tracing.setProvider(Tracing.providers.sentry(Sentry))
43
+ ```
44
+
45
+ The Sentry provider expects an object with:
46
+ - `getClient()` -- returns the Sentry client
47
+ - `SentryContextManager` -- the context manager constructor
48
+ - `validateOpenTelemetrySetup()` -- validates the OTEL integration
49
+
50
+ ## API Reference
51
+
52
+ ### `Tracing.startActiveSpan(name, fn)`
53
+
54
+ Start a span that becomes the active span for the duration of `fn`. Automatically ends the span when `fn` returns or when the returned Promise resolves/rejects.
55
+
56
+ ```ts
57
+ // Simple string name
58
+ Tracing.startActiveSpan('fetch-user', () => {
59
+ return db.query('SELECT * FROM users WHERE id = ?', [userId])
60
+ })
61
+
62
+ // With SpanOptions
63
+ Tracing.startActiveSpan({ name: 'fetch-user', attributes: { userId } }, () => {
64
+ return db.query('SELECT * FROM users WHERE id = ?', [userId])
65
+ })
66
+ ```
67
+
68
+ ### `Tracing.wrap(name, fn)`
69
+
70
+ Return a new function that automatically creates a span on every invocation. The wrapped function preserves the original function's properties.
71
+
72
+ ```ts
73
+ const tracedFetch = Tracing.wrap('fetch-data', fetchData)
74
+ await tracedFetch(url) // each call creates a span
75
+ ```
76
+
77
+ ### `Tracing.isWrapped(fn)`
78
+
79
+ Check whether a function has already been wrapped by the current tracer.
80
+
81
+ ```ts
82
+ if (!Tracing.isWrapped(myFn)) {
83
+ myFn = Tracing.wrap('myFn', myFn)
84
+ }
85
+ ```
86
+
87
+ ### `Tracing.proxy(obj, options?)`
88
+
89
+ Wrap an entire object so every function call on it is traced. Nested objects are proxied recursively with dotted tracer names. Use `options.ignore` to skip specific properties.
90
+
91
+ ```ts
92
+ const tracedService = Tracing.proxy(userService)
93
+ await tracedService.findById(123) // creates span "findById"
94
+
95
+ // Ignore specific methods
96
+ const tracedService = Tracing.proxy(userService, {
97
+ ignore: ({ name }) => name === 'toString'
98
+ })
99
+ ```
100
+
101
+ The `ignore` option accepts a single predicate or an array of predicates with signature `(options: { name: string; tracer: string | null }) => boolean`.
102
+
103
+ ### `Tracing.getTracer(name)`
104
+
105
+ Get a named tracer for a specific package or module. Returns an object with `wrap`, `proxy`, `startActiveSpan`, and `isWrapped` scoped to that tracer name.
106
+
107
+ ```ts
108
+ const { wrap, startActiveSpan, proxy } = Tracing.getTracer('my-package')
109
+ ```
110
+
111
+ The default export (`Tracing.wrap`, `Tracing.startActiveSpan`, etc.) uses the `'maestro'` tracer.
112
+
113
+ ### `Tracing.getActiveSpan()`
114
+
115
+ Return the currently active OpenTelemetry span, or `undefined` if none.
116
+
117
+ ```ts
118
+ const span = Tracing.getActiveSpan()
119
+ span?.setAttribute('user.id', userId)
120
+ ```
121
+
122
+ ### `Tracing.addTransport(transport)`
123
+
124
+ Add a log transport that receives a `TraceLogMessage` for every completed span.
125
+
126
+ ```ts
127
+ Tracing.addTransport({
128
+ info(message: Tracing.LogMessage) {
129
+ console.log(`[${message.name}] ${message.endTime - message.startTime}ms`)
130
+ }
131
+ })
132
+ ```
133
+
134
+ `TraceLogMessage` shape:
135
+ - `name` -- span name
136
+ - `id` -- span ID
137
+ - `parentId` -- parent span ID or `null`
138
+ - `startTime` / `endTime` -- `performance.now()` timestamps
139
+ - `instrumentation` -- instrumentation library name or `null`
140
+ - `attributes` -- key-value span attributes
141
+
142
+ ### `Tracing.dehydrate()`
143
+
144
+ Serialize the current trace context for transmission across process boundaries (e.g., into a queue job payload). Returns `null` if no active span.
145
+
146
+ ```ts
147
+ const serialized = Tracing.dehydrate()
148
+ // { traceId, spanId, traceFlags, traceState }
149
+ ```
150
+
151
+ ### `Tracing.hydrate(trace, callback)`
152
+
153
+ Restore a serialized trace context and execute `callback` within it. The hydrated span is marked as remote, establishing the parent/child relationship across processes.
154
+
155
+ ```ts
156
+ Tracing.hydrate(serializedTrace, () => {
157
+ // This runs within the original trace context
158
+ Tracing.startActiveSpan('process-job', () => {
159
+ return processJob(payload)
160
+ })
161
+ })
162
+ ```
163
+
164
+ ### `Tracing.setProvider(provider)`
165
+
166
+ Set the underlying OpenTelemetry `TracerProvider` delegate. The `MaestroTracerProvider` wraps this delegate to add logging and instrumentation.
167
+
168
+ ```ts
169
+ Tracing.setProvider(Tracing.providers.sentry(Sentry))
170
+ ```
171
+
172
+ ## Common Patterns
173
+
174
+ ### Trace a queue job across processes
175
+
176
+ ```ts
177
+ // Producer: serialize trace context into the job payload
178
+ Tracing.startActiveSpan('enqueue-email', () => {
179
+ const trace = Tracing.dehydrate()
180
+ Queue.dispatch('send-email', { to, subject, body, trace })
181
+ })
182
+
183
+ // Consumer: restore trace context when processing the job
184
+ function handleSendEmail(payload) {
185
+ Tracing.hydrate(payload.trace, () => {
186
+ Tracing.startActiveSpan('send-email', () => {
187
+ return mail.send(payload)
188
+ })
189
+ })
190
+ }
191
+ ```
192
+
193
+ ### Trace an entire service object
194
+
195
+ ```ts
196
+ const rawService = {
197
+ async getUser(id: number) { /* ... */ },
198
+ async updateUser(id: number, data: any) { /* ... */ },
199
+ helpers: {
200
+ formatName(user: any) { /* ... */ }
201
+ }
202
+ }
203
+ // All methods (including nested helpers.formatName) get spans
204
+ const service = Tracing.proxy(rawService)
205
+ ```
206
+
207
+ ### Create a package-scoped tracer
208
+
209
+ ```ts
210
+ const { wrap, startActiveSpan } = Tracing.getTracer('billing')
211
+
212
+ export const createInvoice = wrap('createInvoice', async (order: Order) => {
213
+ return startActiveSpan('validate', () => validateOrder(order))
214
+ })
215
+ ```
216
+
217
+ ## Cross-Package Integration
218
+
219
+ - **@maestro-js/log** -- `MaestroTracerProvider` uses `Log.create()` internally; span completion events are emitted through the log transport system
220
+ - **@maestro-js/context** -- spans preserve `AsyncLocalStorage` context; `Context.runWith` is used to restore the correct store when logging span events
221
+ - **@maestro-js/queue** -- use `dehydrate`/`hydrate` to propagate trace context through queue job payloads
222
+
223
+ ## Types
224
+
225
+ ```ts
226
+ declare namespace Tracing {
227
+ type Attributes = TracingAttributes
228
+ type LogMessage = TraceLogMessage
229
+ type Provider = api.TracerProvider
230
+ type DehydratedTrace = SerializedTrace
231
+ }
232
+ ```
233
+
234
+ ## Package Info
235
+
236
+ - **Package**: `@maestro-js/tracing`
237
+ - **Dependencies**: `@opentelemetry/api`, `@opentelemetry/sdk-trace-node`, `@sentry/opentelemetry`, `@maestro-js/log`, `@maestro-js/context`
238
+ - **No tests currently** (`echo 'No tests yet'`)
239
+ - Build: `pnpm --filter @maestro-js/tracing build`
240
+ - Typecheck: `pnpm --filter @maestro-js/tracing typecheck`
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@maestro-js/agent-skills",
3
+ "description": "Agent skills for the @maestro-js framework.",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "default": "./dist/index.js"
9
+ }
10
+ },
11
+ "devDependencies": {
12
+ "@types/node": "^22.19.11"
13
+ },
14
+ "version": "1.0.0-alpha.0",
15
+ "publishConfig": {
16
+ "access": "restricted"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "license": "UNLICENSED",
22
+ "engines": {
23
+ "node": ">=22.18.0"
24
+ },
25
+ "repository": "https://github.com/Marcato-Partners/maestro-js",
26
+ "scripts": {
27
+ "generate-skills": "node scripts/generate-package-skills.ts",
28
+ "generate-choosing-npm-package-skill": "node scripts/generate-choosing-npm-package-skill.ts",
29
+ "generate-maestro-cli-skill": "node scripts/generate-maestro-cli-skill.ts",
30
+ "build": "node scripts/generate-package-skills.ts && node scripts/generate-choosing-npm-package-skill.ts && node scripts/generate-maestro-cli-skill.ts",
31
+ "typecheck": "tsc --noEmit"
32
+ }
33
+ }