@shogo-ai/core 1.4.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.
- package/LICENSE +21 -0
- package/README.md +34 -0
- package/dist/chat-message.cjs +44 -0
- package/dist/chat-message.d.cts +20 -0
- package/dist/chat-message.d.ts +20 -0
- package/dist/chat-message.js +9 -0
- package/dist/chunk-24AL3V6R.js +57 -0
- package/dist/chunk-4J7NH2WJ.js +19 -0
- package/dist/chunk-ELMG6OXT.js +236 -0
- package/dist/chunk-IDGVRGAL.js +103 -0
- package/dist/chunk-KTDDFWXM.js +39 -0
- package/dist/chunk-VTD7O7YC.js +31 -0
- package/dist/index.cjs +510 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +45 -0
- package/dist/instrumentation.cjs +129 -0
- package/dist/instrumentation.d.cts +43 -0
- package/dist/instrumentation.d.ts +43 -0
- package/dist/instrumentation.js +11 -0
- package/dist/logger.cjs +81 -0
- package/dist/logger.d.cts +32 -0
- package/dist/logger.d.ts +32 -0
- package/dist/logger.js +7 -0
- package/dist/macos-junk.cjs +56 -0
- package/dist/macos-junk.d.cts +20 -0
- package/dist/macos-junk.d.ts +20 -0
- package/dist/macos-junk.js +9 -0
- package/dist/stream-buffer.cjs +261 -0
- package/dist/stream-buffer.d.cts +103 -0
- package/dist/stream-buffer.d.ts +103 -0
- package/dist/stream-buffer.js +9 -0
- package/dist/tech-stack-registry.cjs +67 -0
- package/dist/tech-stack-registry.d.cts +88 -0
- package/dist/tech-stack-registry.d.ts +88 -0
- package/dist/tech-stack-registry.js +15 -0
- package/package.json +118 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
StreamBufferStore: () => StreamBufferStore,
|
|
24
|
+
TECH_STACK_REGISTRY: () => TECH_STACK_REGISTRY,
|
|
25
|
+
createBufferingTransform: () => createBufferingTransform,
|
|
26
|
+
createLogger: () => createLogger,
|
|
27
|
+
extractUserText: () => extractUserText,
|
|
28
|
+
findLastUserMessage: () => findLastUserMessage,
|
|
29
|
+
getStackEntry: () => getStackEntry,
|
|
30
|
+
initInstrumentation: () => initInstrumentation,
|
|
31
|
+
isMacOSJunkName: () => isMacOSJunkName,
|
|
32
|
+
isMacOSJunkPath: () => isMacOSJunkPath,
|
|
33
|
+
isMobileTechStack: () => isMobileTechStack,
|
|
34
|
+
shutdownInstrumentation: () => shutdownInstrumentation,
|
|
35
|
+
stackSeedsItself: () => stackSeedsItself,
|
|
36
|
+
traceOperation: () => traceOperation,
|
|
37
|
+
usesMetroBundler: () => usesMetroBundler
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
40
|
+
|
|
41
|
+
// src/logger.ts
|
|
42
|
+
var LOG_LEVELS = {
|
|
43
|
+
debug: 0,
|
|
44
|
+
info: 1,
|
|
45
|
+
warn: 2,
|
|
46
|
+
error: 3
|
|
47
|
+
};
|
|
48
|
+
var isProduction = process.env.NODE_ENV === "production" || process.env.NODE_ENV === "staging";
|
|
49
|
+
var minLevel = LOG_LEVELS[process.env.LOG_LEVEL || "info"] ?? 1;
|
|
50
|
+
function shouldLog(level) {
|
|
51
|
+
return LOG_LEVELS[level] >= minLevel;
|
|
52
|
+
}
|
|
53
|
+
function formatEntry(entry) {
|
|
54
|
+
if (isProduction) {
|
|
55
|
+
return JSON.stringify(entry);
|
|
56
|
+
}
|
|
57
|
+
const { level: _level, msg, service, timestamp: _timestamp, ...extra } = entry;
|
|
58
|
+
const extraStr = Object.keys(extra).length > 0 ? " " + JSON.stringify(extra) : "";
|
|
59
|
+
return `[${service}] ${msg}${extraStr}`;
|
|
60
|
+
}
|
|
61
|
+
function createLogger(service, defaultExtra) {
|
|
62
|
+
function log(level, msg, extra) {
|
|
63
|
+
if (!shouldLog(level)) return;
|
|
64
|
+
const entry = {
|
|
65
|
+
level,
|
|
66
|
+
msg,
|
|
67
|
+
service,
|
|
68
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
69
|
+
...defaultExtra,
|
|
70
|
+
...extra
|
|
71
|
+
};
|
|
72
|
+
const formatted = formatEntry(entry);
|
|
73
|
+
switch (level) {
|
|
74
|
+
case "error":
|
|
75
|
+
console.error(formatted);
|
|
76
|
+
break;
|
|
77
|
+
case "warn":
|
|
78
|
+
console.warn(formatted);
|
|
79
|
+
break;
|
|
80
|
+
default:
|
|
81
|
+
console.log(formatted);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
debug: (msg, extra) => log("debug", msg, extra),
|
|
87
|
+
info: (msg, extra) => log("info", msg, extra),
|
|
88
|
+
warn: (msg, extra) => log("warn", msg, extra),
|
|
89
|
+
error: (msg, extra) => log("error", msg, extra),
|
|
90
|
+
child: (extra) => createLogger(service, { ...defaultExtra, ...extra })
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/instrumentation.ts
|
|
95
|
+
var import_api = require("@opentelemetry/api");
|
|
96
|
+
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
97
|
+
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
98
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
99
|
+
var import_resources = require("@opentelemetry/resources");
|
|
100
|
+
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
101
|
+
var sdk = null;
|
|
102
|
+
function initInstrumentation(config) {
|
|
103
|
+
const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
104
|
+
if (!endpoint) {
|
|
105
|
+
console.log(`[OTEL] Tracing disabled for ${config.serviceName} (OTEL_EXPORTER_OTLP_ENDPOINT not set)`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const diagLevel = process.env.OTEL_LOG_LEVEL === "debug" ? import_api.DiagLogLevel.DEBUG : process.env.OTEL_LOG_LEVEL === "info" ? import_api.DiagLogLevel.INFO : import_api.DiagLogLevel.WARN;
|
|
109
|
+
import_api.diag.setLogger(new import_api.DiagConsoleLogger(), diagLevel);
|
|
110
|
+
const headers = {};
|
|
111
|
+
if (process.env.SIGNOZ_INGESTION_KEY) {
|
|
112
|
+
headers["signoz-ingestion-key"] = process.env.SIGNOZ_INGESTION_KEY;
|
|
113
|
+
}
|
|
114
|
+
const serviceName = process.env.OTEL_SERVICE_NAME || config.serviceName;
|
|
115
|
+
console.log(`[OTEL] Configuring ${serviceName} \u2192 ${endpoint}/v1/traces`);
|
|
116
|
+
let traceExporter;
|
|
117
|
+
try {
|
|
118
|
+
traceExporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
119
|
+
url: `${endpoint}/v1/traces`,
|
|
120
|
+
headers
|
|
121
|
+
});
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error(`[OTEL] Failed to create exporter: ${err.message}`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const isProduction2 = process.env.NODE_ENV === "production" || process.env.NODE_ENV === "staging";
|
|
127
|
+
const spanProcessor = isProduction2 ? new import_sdk_trace_base.BatchSpanProcessor(traceExporter) : new import_sdk_trace_base.SimpleSpanProcessor(traceExporter);
|
|
128
|
+
sdk = new import_sdk_node.NodeSDK({
|
|
129
|
+
resource: (0, import_resources.resourceFromAttributes)({
|
|
130
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: serviceName,
|
|
131
|
+
[import_semantic_conventions.ATTR_SERVICE_VERSION]: config.serviceVersion || "0.1.0",
|
|
132
|
+
"deployment.environment.name": process.env.NODE_ENV || "development"
|
|
133
|
+
}),
|
|
134
|
+
spanProcessors: [spanProcessor],
|
|
135
|
+
instrumentations: []
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
sdk.start();
|
|
139
|
+
console.log(`[OTEL] Tracing enabled for ${serviceName}`);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
console.error(`[OTEL] SDK failed to start: ${err.message}`);
|
|
142
|
+
sdk = null;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const tracer = import_api.trace.getTracer(serviceName);
|
|
147
|
+
const testSpan = tracer.startSpan("otel.startup-test", {
|
|
148
|
+
attributes: {
|
|
149
|
+
"test.type": "startup-verification",
|
|
150
|
+
"service.name": serviceName,
|
|
151
|
+
// `process.versions.bun` is present under Bun (always undefined
|
|
152
|
+
// under plain Node) — avoids referencing the `Bun` global so
|
|
153
|
+
// this file typechecks without `@types/bun` in tsconfig.
|
|
154
|
+
"runtime": process.versions.bun ? "bun" : "node"
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
testSpan.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
158
|
+
testSpan.end();
|
|
159
|
+
console.log(`[OTEL] Startup test span emitted for ${serviceName}`);
|
|
160
|
+
} catch (err) {
|
|
161
|
+
console.error(`[OTEL] Failed to emit test span: ${err.message}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function shutdownInstrumentation() {
|
|
165
|
+
if (sdk) {
|
|
166
|
+
try {
|
|
167
|
+
await sdk.shutdown();
|
|
168
|
+
console.log("[OTEL] Tracing shut down");
|
|
169
|
+
} catch (err) {
|
|
170
|
+
console.error("[OTEL] Error shutting down:", err.message);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function traceOperation(tracerName, spanName, attributes, fn) {
|
|
175
|
+
const tracer = import_api.trace.getTracer(tracerName);
|
|
176
|
+
return tracer.startActiveSpan(spanName, { attributes }, async (span) => {
|
|
177
|
+
try {
|
|
178
|
+
const result = await fn(span);
|
|
179
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
180
|
+
return result;
|
|
181
|
+
} catch (err) {
|
|
182
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: err.message });
|
|
183
|
+
span.recordException(err);
|
|
184
|
+
throw err;
|
|
185
|
+
} finally {
|
|
186
|
+
span.end();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// src/stream-buffer.ts
|
|
192
|
+
var CLEANUP_INTERVAL_MS = 6e4;
|
|
193
|
+
var MAX_BUFFER_AGE_MS = 30 * 6e4;
|
|
194
|
+
var COMPLETED_GRACE_MS = 3e4;
|
|
195
|
+
var StreamBufferStore = class {
|
|
196
|
+
constructor() {
|
|
197
|
+
this.buffers = /* @__PURE__ */ new Map();
|
|
198
|
+
this.cleanupTimer = null;
|
|
199
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
|
|
200
|
+
const handle = this.cleanupTimer;
|
|
201
|
+
if (handle && typeof handle.unref === "function") {
|
|
202
|
+
handle.unref();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Create (or replace) a buffer for the given key. Any existing active
|
|
207
|
+
* buffer is completed and discarded. Returns a writer bound to this
|
|
208
|
+
* specific buffer instance, including the new `turnId`.
|
|
209
|
+
*/
|
|
210
|
+
create(key, opts) {
|
|
211
|
+
const existing = this.buffers.get(key);
|
|
212
|
+
if (existing && existing.status === "active") {
|
|
213
|
+
this.completeBuffer(existing, "replaced");
|
|
214
|
+
}
|
|
215
|
+
const now = Date.now();
|
|
216
|
+
const turnId = opts?.turnId || generateTurnId();
|
|
217
|
+
const buf = {
|
|
218
|
+
turnId,
|
|
219
|
+
frames: [],
|
|
220
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
221
|
+
status: "active",
|
|
222
|
+
terminal: null,
|
|
223
|
+
createdAt: now,
|
|
224
|
+
completedAt: null,
|
|
225
|
+
lastEventAt: now,
|
|
226
|
+
nextSeq: 1
|
|
227
|
+
};
|
|
228
|
+
this.buffers.set(key, buf);
|
|
229
|
+
return {
|
|
230
|
+
get turnId() {
|
|
231
|
+
return buf.turnId;
|
|
232
|
+
},
|
|
233
|
+
get lastSeq() {
|
|
234
|
+
return buf.nextSeq - 1;
|
|
235
|
+
},
|
|
236
|
+
append: (chunk) => {
|
|
237
|
+
if (buf.status !== "active") return -1;
|
|
238
|
+
const seq = buf.nextSeq++;
|
|
239
|
+
buf.frames.push({ seq, chunk });
|
|
240
|
+
buf.lastEventAt = Date.now();
|
|
241
|
+
for (const ctrl of buf.subscribers) {
|
|
242
|
+
try {
|
|
243
|
+
ctrl.enqueue(chunk);
|
|
244
|
+
} catch {
|
|
245
|
+
buf.subscribers.delete(ctrl);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return seq;
|
|
249
|
+
},
|
|
250
|
+
complete: (reason) => {
|
|
251
|
+
this.completeBuffer(buf, reason);
|
|
252
|
+
},
|
|
253
|
+
fail: (error) => {
|
|
254
|
+
this.failBuffer(buf, error);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Append a chunk by key (loose, untyped writer). Returns the seq assigned,
|
|
260
|
+
* or -1 if the buffer is unknown/inactive.
|
|
261
|
+
*/
|
|
262
|
+
append(key, chunk) {
|
|
263
|
+
const buf = this.buffers.get(key);
|
|
264
|
+
if (!buf || buf.status !== "active") return -1;
|
|
265
|
+
const seq = buf.nextSeq++;
|
|
266
|
+
buf.frames.push({ seq, chunk });
|
|
267
|
+
buf.lastEventAt = Date.now();
|
|
268
|
+
for (const ctrl of buf.subscribers) {
|
|
269
|
+
try {
|
|
270
|
+
ctrl.enqueue(chunk);
|
|
271
|
+
} catch {
|
|
272
|
+
buf.subscribers.delete(ctrl);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return seq;
|
|
276
|
+
}
|
|
277
|
+
/** Mark a buffer as completed by key. Optional terminal reason. */
|
|
278
|
+
complete(key, reason) {
|
|
279
|
+
const buf = this.buffers.get(key);
|
|
280
|
+
if (!buf) return;
|
|
281
|
+
this.completeBuffer(buf, reason);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Abort a stream: complete subscribers and remove the buffer entirely.
|
|
285
|
+
* Future resume/replay requests for this key will return null (→ 204).
|
|
286
|
+
*/
|
|
287
|
+
abort(key) {
|
|
288
|
+
const buf = this.buffers.get(key);
|
|
289
|
+
if (!buf) return;
|
|
290
|
+
this.completeBuffer(buf, "aborted");
|
|
291
|
+
buf.status = "aborted";
|
|
292
|
+
this.buffers.delete(key);
|
|
293
|
+
}
|
|
294
|
+
has(key) {
|
|
295
|
+
return this.buffers.has(key);
|
|
296
|
+
}
|
|
297
|
+
/** Read-only metadata about a buffered turn. Useful for resume responses. */
|
|
298
|
+
snapshot(key) {
|
|
299
|
+
const buf = this.buffers.get(key);
|
|
300
|
+
if (!buf) return null;
|
|
301
|
+
return {
|
|
302
|
+
turnId: buf.turnId,
|
|
303
|
+
status: buf.status,
|
|
304
|
+
lastSeq: buf.nextSeq - 1,
|
|
305
|
+
terminal: buf.terminal,
|
|
306
|
+
createdAt: buf.createdAt,
|
|
307
|
+
completedAt: buf.completedAt,
|
|
308
|
+
lastEventAt: buf.lastEventAt
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Create a ReadableStream that first replays all buffered chunks past
|
|
313
|
+
* `opts.fromSeq` (default: 0 → replay everything), then subscribes for
|
|
314
|
+
* any further live chunks until the stream completes.
|
|
315
|
+
*
|
|
316
|
+
* Returns null if no buffer exists for the key.
|
|
317
|
+
*/
|
|
318
|
+
createReplayStream(key, opts = {}) {
|
|
319
|
+
const buf = this.buffers.get(key);
|
|
320
|
+
if (!buf) return null;
|
|
321
|
+
const fromSeq = Math.max(0, opts.fromSeq ?? 0);
|
|
322
|
+
let subscribedController = null;
|
|
323
|
+
return new ReadableStream({
|
|
324
|
+
start(controller) {
|
|
325
|
+
for (const frame of buf.frames) {
|
|
326
|
+
if (frame.seq <= fromSeq) continue;
|
|
327
|
+
try {
|
|
328
|
+
controller.enqueue(frame.chunk);
|
|
329
|
+
} catch {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (buf.status !== "active") {
|
|
334
|
+
try {
|
|
335
|
+
controller.close();
|
|
336
|
+
} catch {
|
|
337
|
+
}
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
subscribedController = controller;
|
|
341
|
+
buf.subscribers.add(controller);
|
|
342
|
+
},
|
|
343
|
+
cancel() {
|
|
344
|
+
if (subscribedController) {
|
|
345
|
+
buf.subscribers.delete(subscribedController);
|
|
346
|
+
subscribedController = null;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
cleanup() {
|
|
352
|
+
const now = Date.now();
|
|
353
|
+
for (const [key, buf] of this.buffers) {
|
|
354
|
+
if (buf.status !== "active" && buf.completedAt && now - buf.completedAt > COMPLETED_GRACE_MS) {
|
|
355
|
+
this.buffers.delete(key);
|
|
356
|
+
} else if (now - buf.createdAt > MAX_BUFFER_AGE_MS && buf.subscribers.size === 0) {
|
|
357
|
+
this.completeBuffer(buf, "expired");
|
|
358
|
+
this.buffers.delete(key);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
dispose() {
|
|
363
|
+
if (this.cleanupTimer) {
|
|
364
|
+
clearInterval(this.cleanupTimer);
|
|
365
|
+
this.cleanupTimer = null;
|
|
366
|
+
}
|
|
367
|
+
for (const buf of this.buffers.values()) {
|
|
368
|
+
this.completeBuffer(buf, "disposed");
|
|
369
|
+
}
|
|
370
|
+
this.buffers.clear();
|
|
371
|
+
}
|
|
372
|
+
completeBuffer(buf, reason) {
|
|
373
|
+
if (buf.status !== "active") return;
|
|
374
|
+
buf.status = "completed";
|
|
375
|
+
buf.terminal = { reason };
|
|
376
|
+
buf.completedAt = Date.now();
|
|
377
|
+
buf.lastEventAt = buf.completedAt;
|
|
378
|
+
for (const ctrl of buf.subscribers) {
|
|
379
|
+
try {
|
|
380
|
+
ctrl.close();
|
|
381
|
+
} catch {
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
buf.subscribers.clear();
|
|
385
|
+
}
|
|
386
|
+
failBuffer(buf, error) {
|
|
387
|
+
if (buf.status !== "active") return;
|
|
388
|
+
buf.status = "failed";
|
|
389
|
+
buf.terminal = { error };
|
|
390
|
+
buf.completedAt = Date.now();
|
|
391
|
+
buf.lastEventAt = buf.completedAt;
|
|
392
|
+
for (const ctrl of buf.subscribers) {
|
|
393
|
+
try {
|
|
394
|
+
ctrl.close();
|
|
395
|
+
} catch {
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
buf.subscribers.clear();
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
function generateTurnId() {
|
|
402
|
+
try {
|
|
403
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
404
|
+
return globalThis.crypto.randomUUID();
|
|
405
|
+
}
|
|
406
|
+
} catch {
|
|
407
|
+
}
|
|
408
|
+
return `turn_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
409
|
+
}
|
|
410
|
+
function createBufferingTransform(store, key) {
|
|
411
|
+
return new TransformStream({
|
|
412
|
+
transform(chunk, controller) {
|
|
413
|
+
store.append(key, chunk);
|
|
414
|
+
controller.enqueue(chunk);
|
|
415
|
+
},
|
|
416
|
+
flush() {
|
|
417
|
+
store.complete(key);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/chat-message.ts
|
|
423
|
+
function findLastUserMessage(messages) {
|
|
424
|
+
return [...messages].reverse().find((m) => m.role === "user") ?? null;
|
|
425
|
+
}
|
|
426
|
+
function extractUserText(message) {
|
|
427
|
+
if (typeof message.content === "string") {
|
|
428
|
+
return message.content;
|
|
429
|
+
}
|
|
430
|
+
if (Array.isArray(message.parts)) {
|
|
431
|
+
return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
432
|
+
}
|
|
433
|
+
return String(message.content ?? "");
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/macos-junk.ts
|
|
437
|
+
var MACOS_JUNK_BASENAMES = /* @__PURE__ */ new Set([
|
|
438
|
+
".DS_Store",
|
|
439
|
+
".AppleDouble",
|
|
440
|
+
".LSOverride",
|
|
441
|
+
".Spotlight-V100",
|
|
442
|
+
".Trashes",
|
|
443
|
+
".fseventsd",
|
|
444
|
+
".TemporaryItems",
|
|
445
|
+
".VolumeIcon.icns",
|
|
446
|
+
".com.apple.timemachine.donotpresent",
|
|
447
|
+
"__MACOSX"
|
|
448
|
+
]);
|
|
449
|
+
var ICON_CR = "Icon\r";
|
|
450
|
+
function isMacOSJunkName(name) {
|
|
451
|
+
if (!name) return false;
|
|
452
|
+
if (name.startsWith("._")) return true;
|
|
453
|
+
if (MACOS_JUNK_BASENAMES.has(name)) return true;
|
|
454
|
+
if (name === ICON_CR) return true;
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
function isMacOSJunkPath(relPath) {
|
|
458
|
+
if (!relPath) return false;
|
|
459
|
+
return relPath.split("/").some(isMacOSJunkName);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/tech-stack-registry.ts
|
|
463
|
+
var TECH_STACK_REGISTRY = {
|
|
464
|
+
// Web (Vite-based) — share a bundled Vite template, so apps/api seeds them.
|
|
465
|
+
"react-app": { id: "react-app", target: "web" },
|
|
466
|
+
"threejs-game": { id: "threejs-game", target: "web" },
|
|
467
|
+
"phaser-game": { id: "phaser-game", target: "web" },
|
|
468
|
+
// Mobile (Metro/Expo) — agent-runtime owns the seed.
|
|
469
|
+
"expo-app": { id: "expo-app", target: "mobile", metro: true, seedsOwnTemplate: true },
|
|
470
|
+
"expo-three": { id: "expo-three", target: "mobile", metro: true, seedsOwnTemplate: true },
|
|
471
|
+
"react-native": { id: "react-native", target: "mobile", metro: true, seedsOwnTemplate: true },
|
|
472
|
+
// Data / scripting
|
|
473
|
+
"python-data": { id: "python-data", target: "data", seedsOwnTemplate: true },
|
|
474
|
+
// Native (full game engines)
|
|
475
|
+
"unity-game": { id: "unity-game", target: "native", seedsOwnTemplate: true },
|
|
476
|
+
// Bare / no-stack
|
|
477
|
+
none: { id: "none", target: "none", seedsOwnTemplate: true }
|
|
478
|
+
};
|
|
479
|
+
function getStackEntry(techStackId) {
|
|
480
|
+
if (!techStackId) return null;
|
|
481
|
+
return TECH_STACK_REGISTRY[techStackId] ?? null;
|
|
482
|
+
}
|
|
483
|
+
function isMobileTechStack(techStackId) {
|
|
484
|
+
return getStackEntry(techStackId)?.target === "mobile";
|
|
485
|
+
}
|
|
486
|
+
function usesMetroBundler(techStackId) {
|
|
487
|
+
return getStackEntry(techStackId)?.metro === true;
|
|
488
|
+
}
|
|
489
|
+
function stackSeedsItself(techStackId) {
|
|
490
|
+
return getStackEntry(techStackId)?.seedsOwnTemplate === true;
|
|
491
|
+
}
|
|
492
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
493
|
+
0 && (module.exports = {
|
|
494
|
+
StreamBufferStore,
|
|
495
|
+
TECH_STACK_REGISTRY,
|
|
496
|
+
createBufferingTransform,
|
|
497
|
+
createLogger,
|
|
498
|
+
extractUserText,
|
|
499
|
+
findLastUserMessage,
|
|
500
|
+
getStackEntry,
|
|
501
|
+
initInstrumentation,
|
|
502
|
+
isMacOSJunkName,
|
|
503
|
+
isMacOSJunkPath,
|
|
504
|
+
isMobileTechStack,
|
|
505
|
+
shutdownInstrumentation,
|
|
506
|
+
stackSeedsItself,
|
|
507
|
+
traceOperation,
|
|
508
|
+
usesMetroBundler
|
|
509
|
+
});
|
|
510
|
+
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { LogLevel, Logger, createLogger } from './logger.cjs';
|
|
2
|
+
export { InstrumentationConfig, initInstrumentation, shutdownInstrumentation, traceOperation } from './instrumentation.cjs';
|
|
3
|
+
export { ReplayOptions, StreamBufferStore, StreamBufferWriter, TurnSnapshot, TurnStatus, TurnTerminal, createBufferingTransform } from './stream-buffer.cjs';
|
|
4
|
+
export { extractUserText, findLastUserMessage } from './chat-message.cjs';
|
|
5
|
+
export { isMacOSJunkName, isMacOSJunkPath } from './macos-junk.cjs';
|
|
6
|
+
export { StackRegistryEntry, StackTarget, TECH_STACK_REGISTRY, getStackEntry, isMobileTechStack, stackSeedsItself, usesMetroBundler } from './tech-stack-registry.cjs';
|
|
7
|
+
import '@opentelemetry/api';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { LogLevel, Logger, createLogger } from './logger.js';
|
|
2
|
+
export { InstrumentationConfig, initInstrumentation, shutdownInstrumentation, traceOperation } from './instrumentation.js';
|
|
3
|
+
export { ReplayOptions, StreamBufferStore, StreamBufferWriter, TurnSnapshot, TurnStatus, TurnTerminal, createBufferingTransform } from './stream-buffer.js';
|
|
4
|
+
export { extractUserText, findLastUserMessage } from './chat-message.js';
|
|
5
|
+
export { isMacOSJunkName, isMacOSJunkPath } from './macos-junk.js';
|
|
6
|
+
export { StackRegistryEntry, StackTarget, TECH_STACK_REGISTRY, getStackEntry, isMobileTechStack, stackSeedsItself, usesMetroBundler } from './tech-stack-registry.js';
|
|
7
|
+
import '@opentelemetry/api';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractUserText,
|
|
3
|
+
findLastUserMessage
|
|
4
|
+
} from "./chunk-4J7NH2WJ.js";
|
|
5
|
+
import {
|
|
6
|
+
initInstrumentation,
|
|
7
|
+
shutdownInstrumentation,
|
|
8
|
+
traceOperation
|
|
9
|
+
} from "./chunk-IDGVRGAL.js";
|
|
10
|
+
import {
|
|
11
|
+
createLogger
|
|
12
|
+
} from "./chunk-24AL3V6R.js";
|
|
13
|
+
import {
|
|
14
|
+
isMacOSJunkName,
|
|
15
|
+
isMacOSJunkPath
|
|
16
|
+
} from "./chunk-VTD7O7YC.js";
|
|
17
|
+
import {
|
|
18
|
+
StreamBufferStore,
|
|
19
|
+
createBufferingTransform
|
|
20
|
+
} from "./chunk-ELMG6OXT.js";
|
|
21
|
+
import {
|
|
22
|
+
TECH_STACK_REGISTRY,
|
|
23
|
+
getStackEntry,
|
|
24
|
+
isMobileTechStack,
|
|
25
|
+
stackSeedsItself,
|
|
26
|
+
usesMetroBundler
|
|
27
|
+
} from "./chunk-KTDDFWXM.js";
|
|
28
|
+
export {
|
|
29
|
+
StreamBufferStore,
|
|
30
|
+
TECH_STACK_REGISTRY,
|
|
31
|
+
createBufferingTransform,
|
|
32
|
+
createLogger,
|
|
33
|
+
extractUserText,
|
|
34
|
+
findLastUserMessage,
|
|
35
|
+
getStackEntry,
|
|
36
|
+
initInstrumentation,
|
|
37
|
+
isMacOSJunkName,
|
|
38
|
+
isMacOSJunkPath,
|
|
39
|
+
isMobileTechStack,
|
|
40
|
+
shutdownInstrumentation,
|
|
41
|
+
stackSeedsItself,
|
|
42
|
+
traceOperation,
|
|
43
|
+
usesMetroBundler
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/instrumentation.ts
|
|
21
|
+
var instrumentation_exports = {};
|
|
22
|
+
__export(instrumentation_exports, {
|
|
23
|
+
initInstrumentation: () => initInstrumentation,
|
|
24
|
+
shutdownInstrumentation: () => shutdownInstrumentation,
|
|
25
|
+
traceOperation: () => traceOperation
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(instrumentation_exports);
|
|
28
|
+
var import_api = require("@opentelemetry/api");
|
|
29
|
+
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
30
|
+
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
31
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
32
|
+
var import_resources = require("@opentelemetry/resources");
|
|
33
|
+
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
34
|
+
var sdk = null;
|
|
35
|
+
function initInstrumentation(config) {
|
|
36
|
+
const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
37
|
+
if (!endpoint) {
|
|
38
|
+
console.log(`[OTEL] Tracing disabled for ${config.serviceName} (OTEL_EXPORTER_OTLP_ENDPOINT not set)`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const diagLevel = process.env.OTEL_LOG_LEVEL === "debug" ? import_api.DiagLogLevel.DEBUG : process.env.OTEL_LOG_LEVEL === "info" ? import_api.DiagLogLevel.INFO : import_api.DiagLogLevel.WARN;
|
|
42
|
+
import_api.diag.setLogger(new import_api.DiagConsoleLogger(), diagLevel);
|
|
43
|
+
const headers = {};
|
|
44
|
+
if (process.env.SIGNOZ_INGESTION_KEY) {
|
|
45
|
+
headers["signoz-ingestion-key"] = process.env.SIGNOZ_INGESTION_KEY;
|
|
46
|
+
}
|
|
47
|
+
const serviceName = process.env.OTEL_SERVICE_NAME || config.serviceName;
|
|
48
|
+
console.log(`[OTEL] Configuring ${serviceName} \u2192 ${endpoint}/v1/traces`);
|
|
49
|
+
let traceExporter;
|
|
50
|
+
try {
|
|
51
|
+
traceExporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
52
|
+
url: `${endpoint}/v1/traces`,
|
|
53
|
+
headers
|
|
54
|
+
});
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.error(`[OTEL] Failed to create exporter: ${err.message}`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const isProduction = process.env.NODE_ENV === "production" || process.env.NODE_ENV === "staging";
|
|
60
|
+
const spanProcessor = isProduction ? new import_sdk_trace_base.BatchSpanProcessor(traceExporter) : new import_sdk_trace_base.SimpleSpanProcessor(traceExporter);
|
|
61
|
+
sdk = new import_sdk_node.NodeSDK({
|
|
62
|
+
resource: (0, import_resources.resourceFromAttributes)({
|
|
63
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: serviceName,
|
|
64
|
+
[import_semantic_conventions.ATTR_SERVICE_VERSION]: config.serviceVersion || "0.1.0",
|
|
65
|
+
"deployment.environment.name": process.env.NODE_ENV || "development"
|
|
66
|
+
}),
|
|
67
|
+
spanProcessors: [spanProcessor],
|
|
68
|
+
instrumentations: []
|
|
69
|
+
});
|
|
70
|
+
try {
|
|
71
|
+
sdk.start();
|
|
72
|
+
console.log(`[OTEL] Tracing enabled for ${serviceName}`);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.error(`[OTEL] SDK failed to start: ${err.message}`);
|
|
75
|
+
sdk = null;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const tracer = import_api.trace.getTracer(serviceName);
|
|
80
|
+
const testSpan = tracer.startSpan("otel.startup-test", {
|
|
81
|
+
attributes: {
|
|
82
|
+
"test.type": "startup-verification",
|
|
83
|
+
"service.name": serviceName,
|
|
84
|
+
// `process.versions.bun` is present under Bun (always undefined
|
|
85
|
+
// under plain Node) — avoids referencing the `Bun` global so
|
|
86
|
+
// this file typechecks without `@types/bun` in tsconfig.
|
|
87
|
+
"runtime": process.versions.bun ? "bun" : "node"
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
testSpan.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
91
|
+
testSpan.end();
|
|
92
|
+
console.log(`[OTEL] Startup test span emitted for ${serviceName}`);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.error(`[OTEL] Failed to emit test span: ${err.message}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function shutdownInstrumentation() {
|
|
98
|
+
if (sdk) {
|
|
99
|
+
try {
|
|
100
|
+
await sdk.shutdown();
|
|
101
|
+
console.log("[OTEL] Tracing shut down");
|
|
102
|
+
} catch (err) {
|
|
103
|
+
console.error("[OTEL] Error shutting down:", err.message);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function traceOperation(tracerName, spanName, attributes, fn) {
|
|
108
|
+
const tracer = import_api.trace.getTracer(tracerName);
|
|
109
|
+
return tracer.startActiveSpan(spanName, { attributes }, async (span) => {
|
|
110
|
+
try {
|
|
111
|
+
const result = await fn(span);
|
|
112
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
113
|
+
return result;
|
|
114
|
+
} catch (err) {
|
|
115
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: err.message });
|
|
116
|
+
span.recordException(err);
|
|
117
|
+
throw err;
|
|
118
|
+
} finally {
|
|
119
|
+
span.end();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
124
|
+
0 && (module.exports = {
|
|
125
|
+
initInstrumentation,
|
|
126
|
+
shutdownInstrumentation,
|
|
127
|
+
traceOperation
|
|
128
|
+
});
|
|
129
|
+
//# sourceMappingURL=instrumentation.cjs.map
|