@codmir/sdk 0.1.1

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,186 @@
1
+ import {
2
+ addBreadcrumb,
3
+ captureException,
4
+ captureMessage,
5
+ close,
6
+ flush,
7
+ getClient,
8
+ init,
9
+ setTags,
10
+ setUser
11
+ } from "../chunk-T7OAAOG2.js";
12
+ import "../chunk-MLKGABMK.js";
13
+
14
+ // src/browser/index.ts
15
+ var isInitialized = false;
16
+ function init2(config = {}) {
17
+ if (typeof window === "undefined") {
18
+ console.warn("[@codmir/sdk/browser] Cannot initialize in non-browser environment");
19
+ return;
20
+ }
21
+ if (isInitialized) return;
22
+ const {
23
+ captureGlobalErrors = true,
24
+ captureUnhandledRejections = true,
25
+ captureConsoleErrors = false,
26
+ trackClicks = true,
27
+ trackInputs = false,
28
+ trackRequests = true,
29
+ ...coreConfig
30
+ } = config;
31
+ init(coreConfig);
32
+ isInitialized = true;
33
+ if (captureGlobalErrors) {
34
+ window.addEventListener("error", (event) => {
35
+ captureException(event.error || event.message, {
36
+ handled: false,
37
+ mechanism: "onerror",
38
+ filename: event.filename,
39
+ lineno: event.lineno,
40
+ colno: event.colno
41
+ });
42
+ });
43
+ }
44
+ if (captureUnhandledRejections) {
45
+ window.addEventListener("unhandledrejection", (event) => {
46
+ captureException(event.reason, {
47
+ handled: false,
48
+ mechanism: "onunhandledrejection"
49
+ });
50
+ });
51
+ }
52
+ if (captureConsoleErrors) {
53
+ const originalError = console.error;
54
+ console.error = (...args) => {
55
+ captureMessage(args.map(String).join(" "), "error");
56
+ originalError.apply(console, args);
57
+ };
58
+ }
59
+ if (trackClicks) {
60
+ document.addEventListener("click", (event) => {
61
+ const target = event.target;
62
+ if (!target) return;
63
+ const breadcrumb = {
64
+ category: "ui.click",
65
+ message: getElementDescription(target),
66
+ data: {
67
+ tag: target.tagName.toLowerCase(),
68
+ id: target.id || void 0,
69
+ class: target.className || void 0
70
+ }
71
+ };
72
+ addBreadcrumb(breadcrumb);
73
+ });
74
+ }
75
+ if (trackInputs) {
76
+ document.addEventListener("input", (event) => {
77
+ const target = event.target;
78
+ if (!target) return;
79
+ const breadcrumb = {
80
+ category: "ui.input",
81
+ message: getElementDescription(target),
82
+ data: {
83
+ tag: target.tagName.toLowerCase(),
84
+ type: target.type || "text"
85
+ // Never log actual values
86
+ }
87
+ };
88
+ addBreadcrumb(breadcrumb);
89
+ });
90
+ }
91
+ if (trackRequests) {
92
+ setupRequestTracking();
93
+ }
94
+ }
95
+ function getElementDescription(el) {
96
+ let description = el.tagName.toLowerCase();
97
+ if (el.id) {
98
+ description += `#${el.id}`;
99
+ } else if (el.className) {
100
+ description += `.${el.className.split(" ")[0]}`;
101
+ }
102
+ if (el.tagName === "BUTTON" || el.tagName === "A") {
103
+ const text = el.textContent?.trim().slice(0, 50);
104
+ if (text) {
105
+ description += ` "${text}"`;
106
+ }
107
+ }
108
+ return description;
109
+ }
110
+ function setupRequestTracking() {
111
+ const originalFetch = window.fetch;
112
+ window.fetch = async function(input, init3) {
113
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
114
+ const method = init3?.method || "GET";
115
+ const startTime = Date.now();
116
+ try {
117
+ const response = await originalFetch.call(window, input, init3);
118
+ addBreadcrumb({
119
+ category: "fetch",
120
+ message: `${method} ${url}`,
121
+ data: {
122
+ method,
123
+ url,
124
+ status: response.status,
125
+ duration: Date.now() - startTime
126
+ },
127
+ level: response.ok ? "info" : "error"
128
+ });
129
+ return response;
130
+ } catch (error) {
131
+ addBreadcrumb({
132
+ category: "fetch",
133
+ message: `${method} ${url}`,
134
+ data: {
135
+ method,
136
+ url,
137
+ error: error instanceof Error ? error.message : "Network error",
138
+ duration: Date.now() - startTime
139
+ },
140
+ level: "error"
141
+ });
142
+ throw error;
143
+ }
144
+ };
145
+ const originalXHROpen = XMLHttpRequest.prototype.open;
146
+ const originalXHRSend = XMLHttpRequest.prototype.send;
147
+ XMLHttpRequest.prototype.open = function(method, url) {
148
+ this.__codmir = { method, url: url.toString(), startTime: 0 };
149
+ return originalXHROpen.apply(this, arguments);
150
+ };
151
+ XMLHttpRequest.prototype.send = function(body) {
152
+ const data = this.__codmir;
153
+ if (data) {
154
+ data.startTime = Date.now();
155
+ this.addEventListener("loadend", () => {
156
+ addBreadcrumb({
157
+ category: "xhr",
158
+ message: `${data.method} ${data.url}`,
159
+ data: {
160
+ method: data.method,
161
+ url: data.url,
162
+ status: this.status,
163
+ duration: Date.now() - data.startTime
164
+ },
165
+ level: this.status >= 400 ? "error" : "info"
166
+ });
167
+ });
168
+ }
169
+ return originalXHRSend.call(this, body);
170
+ };
171
+ }
172
+ function isOverseerInitialized() {
173
+ return isInitialized && getClient() !== null;
174
+ }
175
+ export {
176
+ addBreadcrumb,
177
+ captureException,
178
+ captureMessage,
179
+ close,
180
+ flush,
181
+ getClient,
182
+ init2 as init,
183
+ isOverseerInitialized,
184
+ setTags,
185
+ setUser
186
+ };
@@ -0,0 +1,43 @@
1
+ // src/types.ts
2
+ import { z } from "zod";
3
+ var CodmirApiError = class extends Error {
4
+ constructor(code, message, statusCode, details) {
5
+ super(message);
6
+ this.code = code;
7
+ this.statusCode = statusCode;
8
+ this.details = details;
9
+ this.name = "CodmirApiError";
10
+ }
11
+ };
12
+ var CreateTicketSchema = z.object({
13
+ title: z.string().min(1).max(200),
14
+ description: z.string().optional(),
15
+ status: z.enum(["open", "in_progress", "review", "done", "closed"]).optional(),
16
+ priority: z.enum(["low", "medium", "high", "critical"]).optional(),
17
+ type: z.enum(["bug", "feature", "task", "improvement", "epic"]).optional(),
18
+ projectId: z.string().uuid(),
19
+ assigneeId: z.string().uuid().optional(),
20
+ labels: z.array(z.string()).optional(),
21
+ dueDate: z.string().datetime().optional()
22
+ });
23
+ var CreateAgentTaskSchema = z.object({
24
+ type: z.enum([
25
+ "code_review",
26
+ "bug_fix",
27
+ "feature_implementation",
28
+ "refactor",
29
+ "documentation",
30
+ "test_generation",
31
+ "analysis",
32
+ "custom"
33
+ ]),
34
+ prompt: z.string().min(1),
35
+ context: z.record(z.unknown()).optional(),
36
+ projectId: z.string().uuid().optional()
37
+ });
38
+
39
+ export {
40
+ CodmirApiError,
41
+ CreateTicketSchema,
42
+ CreateAgentTaskSchema
43
+ };
@@ -0,0 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export {
8
+ __export
9
+ };
@@ -0,0 +1,235 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-MLKGABMK.js";
4
+
5
+ // src/overseer/index.ts
6
+ var overseer_exports = {};
7
+ __export(overseer_exports, {
8
+ OverseerClient: () => OverseerClient,
9
+ addBreadcrumb: () => addBreadcrumb,
10
+ captureException: () => captureException,
11
+ captureMessage: () => captureMessage,
12
+ close: () => close,
13
+ flush: () => flush,
14
+ getClient: () => getClient,
15
+ init: () => init,
16
+ setTag: () => setTag,
17
+ setTags: () => setTags,
18
+ setUser: () => setUser
19
+ });
20
+ import { nanoid } from "nanoid";
21
+ var OverseerClient = class {
22
+ config;
23
+ user = null;
24
+ tags = {};
25
+ breadcrumbs = [];
26
+ eventQueue = [];
27
+ flushTimer = null;
28
+ isInitialized = false;
29
+ constructor(config = {}) {
30
+ this.config = {
31
+ dsn: config.dsn || "",
32
+ environment: config.environment || "development",
33
+ release: config.release || "unknown",
34
+ enabled: config.enabled ?? true,
35
+ debug: config.debug ?? false,
36
+ sampleRate: config.sampleRate ?? 1,
37
+ tracesSampleRate: config.tracesSampleRate ?? 0,
38
+ replaysSessionSampleRate: config.replaysSessionSampleRate ?? 0,
39
+ replaysOnErrorSampleRate: config.replaysOnErrorSampleRate ?? 1,
40
+ beforeSend: config.beforeSend || ((e) => e),
41
+ initialUser: config.initialUser,
42
+ initialTags: config.initialTags || {}
43
+ };
44
+ if (this.config.initialUser) {
45
+ this.user = this.config.initialUser;
46
+ }
47
+ if (this.config.initialTags) {
48
+ this.tags = { ...this.config.initialTags };
49
+ }
50
+ }
51
+ init() {
52
+ if (this.isInitialized) return;
53
+ this.isInitialized = true;
54
+ if (this.config.debug) {
55
+ console.log("[Overseer] Initialized", {
56
+ dsn: this.config.dsn,
57
+ environment: this.config.environment
58
+ });
59
+ }
60
+ }
61
+ captureException(error, context) {
62
+ if (!this.config.enabled) return "";
63
+ if (!this.shouldSample(this.config.sampleRate)) return "";
64
+ const eventId = nanoid();
65
+ const err = error instanceof Error ? error : new Error(String(error));
66
+ const event = {
67
+ id: eventId,
68
+ type: "error",
69
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
70
+ level: "error",
71
+ message: err.message,
72
+ exception: {
73
+ type: err.name,
74
+ value: err.message,
75
+ stacktrace: this.parseStackTrace(err.stack),
76
+ mechanism: { type: "generic", handled: true }
77
+ },
78
+ user: this.user || void 0,
79
+ tags: { ...this.tags },
80
+ extra: context,
81
+ breadcrumbs: [...this.breadcrumbs],
82
+ environment: this.config.environment,
83
+ release: this.config.release,
84
+ sdk: { name: "@codmir/sdk", version: "1.0.0" }
85
+ };
86
+ this.sendEvent(event);
87
+ return eventId;
88
+ }
89
+ captureMessage(message, level = "info") {
90
+ if (!this.config.enabled) return "";
91
+ if (!this.shouldSample(this.config.sampleRate)) return "";
92
+ const eventId = nanoid();
93
+ const event = {
94
+ id: eventId,
95
+ type: "message",
96
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
97
+ level,
98
+ message,
99
+ user: this.user || void 0,
100
+ tags: { ...this.tags },
101
+ breadcrumbs: [...this.breadcrumbs],
102
+ environment: this.config.environment,
103
+ release: this.config.release,
104
+ sdk: { name: "@codmir/sdk", version: "1.0.0" }
105
+ };
106
+ this.sendEvent(event);
107
+ return eventId;
108
+ }
109
+ setUser(user) {
110
+ this.user = user;
111
+ }
112
+ setTag(key, value) {
113
+ this.tags[key] = value;
114
+ }
115
+ setTags(tags) {
116
+ this.tags = { ...this.tags, ...tags };
117
+ }
118
+ setExtra(key, value) {
119
+ }
120
+ addBreadcrumb(breadcrumb) {
121
+ this.breadcrumbs.push({
122
+ ...breadcrumb,
123
+ timestamp: breadcrumb.timestamp || (/* @__PURE__ */ new Date()).toISOString()
124
+ });
125
+ if (this.breadcrumbs.length > 100) {
126
+ this.breadcrumbs = this.breadcrumbs.slice(-100);
127
+ }
128
+ }
129
+ async flush(timeout) {
130
+ if (this.eventQueue.length === 0) return true;
131
+ const events = [...this.eventQueue];
132
+ this.eventQueue = [];
133
+ try {
134
+ await this.sendBatch(events);
135
+ return true;
136
+ } catch {
137
+ this.eventQueue.unshift(...events);
138
+ return false;
139
+ }
140
+ }
141
+ close() {
142
+ if (this.flushTimer) {
143
+ clearTimeout(this.flushTimer);
144
+ }
145
+ this.flush();
146
+ }
147
+ // Private methods
148
+ shouldSample(rate) {
149
+ return Math.random() < rate;
150
+ }
151
+ parseStackTrace(stack) {
152
+ if (!stack) return [];
153
+ return stack.split("\n").slice(1).map((line) => {
154
+ const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
155
+ if (match) {
156
+ return {
157
+ function: match[1],
158
+ filename: match[2],
159
+ lineno: parseInt(match[3], 10),
160
+ colno: parseInt(match[4], 10),
161
+ in_app: !match[2].includes("node_modules")
162
+ };
163
+ }
164
+ return { function: line.trim() };
165
+ }).filter((f) => f.function);
166
+ }
167
+ sendEvent(event) {
168
+ const processed = this.config.beforeSend(event);
169
+ if (!processed) return;
170
+ this.eventQueue.push(processed);
171
+ if (this.flushTimer) clearTimeout(this.flushTimer);
172
+ this.flushTimer = setTimeout(() => this.flush(), 1e3);
173
+ }
174
+ async sendBatch(events) {
175
+ if (!this.config.dsn) {
176
+ if (this.config.debug) {
177
+ console.log("[Overseer] No DSN configured, events:", events);
178
+ }
179
+ return;
180
+ }
181
+ const endpoint = this.config.dsn.endsWith("/ingest") ? this.config.dsn : `${this.config.dsn}/ingest`;
182
+ await fetch(endpoint, {
183
+ method: "POST",
184
+ headers: { "Content-Type": "application/json" },
185
+ body: JSON.stringify({ events })
186
+ });
187
+ }
188
+ };
189
+ var client = null;
190
+ function init(config = {}) {
191
+ client = new OverseerClient(config);
192
+ client.init();
193
+ }
194
+ function getClient() {
195
+ return client;
196
+ }
197
+ function captureException(error, context) {
198
+ return client?.captureException(error, context) || "";
199
+ }
200
+ function captureMessage(message, level) {
201
+ return client?.captureMessage(message, level) || "";
202
+ }
203
+ function setUser(user) {
204
+ client?.setUser(user);
205
+ }
206
+ function setTag(key, value) {
207
+ client?.setTag(key, value);
208
+ }
209
+ function setTags(tags) {
210
+ client?.setTags(tags);
211
+ }
212
+ function addBreadcrumb(breadcrumb) {
213
+ client?.addBreadcrumb(breadcrumb);
214
+ }
215
+ function flush(timeout) {
216
+ return client?.flush(timeout) || Promise.resolve(true);
217
+ }
218
+ function close() {
219
+ client?.close();
220
+ }
221
+
222
+ export {
223
+ OverseerClient,
224
+ init,
225
+ getClient,
226
+ captureException,
227
+ captureMessage,
228
+ setUser,
229
+ setTag,
230
+ setTags,
231
+ addBreadcrumb,
232
+ flush,
233
+ close,
234
+ overseer_exports
235
+ };