libretto 0.1.5 → 0.2.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.
Files changed (183) hide show
  1. package/README.md +213 -17
  2. package/bin/libretto.mjs +18 -0
  3. package/dist/cli/cli.js +201 -0
  4. package/dist/cli/commands/ai.js +21 -0
  5. package/dist/cli/commands/browser.js +56 -0
  6. package/dist/cli/commands/execution.js +407 -0
  7. package/dist/cli/commands/logs.js +65 -0
  8. package/dist/cli/commands/snapshot.js +99 -0
  9. package/dist/cli/core/ai-config.js +149 -0
  10. package/dist/cli/core/browser.js +687 -0
  11. package/dist/cli/core/context.js +113 -0
  12. package/dist/cli/core/pause-signals.js +29 -0
  13. package/dist/cli/core/session.js +183 -0
  14. package/dist/cli/core/snapshot-analyzer.js +492 -0
  15. package/dist/cli/core/telemetry.js +350 -0
  16. package/dist/cli/index.js +13 -0
  17. package/dist/cli/workers/run-integration-runtime.js +204 -0
  18. package/dist/cli/workers/run-integration-worker-protocol.js +0 -0
  19. package/dist/cli/workers/run-integration-worker.js +83 -0
  20. package/dist/index.cjs +127 -0
  21. package/dist/index.d.cts +22 -0
  22. package/dist/index.d.ts +22 -0
  23. package/dist/index.js +110 -0
  24. package/dist/runtime/download/download.cjs +70 -0
  25. package/dist/runtime/download/download.d.cts +35 -0
  26. package/dist/runtime/download/download.d.ts +35 -0
  27. package/dist/runtime/download/download.js +45 -0
  28. package/dist/runtime/download/index.cjs +30 -0
  29. package/dist/runtime/download/index.d.cts +3 -0
  30. package/dist/runtime/download/index.d.ts +3 -0
  31. package/dist/runtime/download/index.js +8 -0
  32. package/dist/runtime/extract/extract.cjs +87 -0
  33. package/dist/runtime/extract/extract.d.cts +23 -0
  34. package/dist/runtime/extract/extract.d.ts +23 -0
  35. package/dist/runtime/extract/extract.js +63 -0
  36. package/dist/runtime/extract/index.cjs +28 -0
  37. package/dist/runtime/extract/index.d.cts +5 -0
  38. package/dist/runtime/extract/index.d.ts +5 -0
  39. package/dist/runtime/extract/index.js +4 -0
  40. package/dist/runtime/network/index.cjs +28 -0
  41. package/dist/runtime/network/index.d.cts +4 -0
  42. package/dist/runtime/network/index.d.ts +4 -0
  43. package/dist/runtime/network/index.js +6 -0
  44. package/dist/runtime/network/network.cjs +91 -0
  45. package/dist/runtime/network/network.d.cts +28 -0
  46. package/dist/runtime/network/network.d.ts +28 -0
  47. package/dist/runtime/network/network.js +67 -0
  48. package/dist/runtime/recovery/agent.cjs +218 -0
  49. package/dist/runtime/recovery/agent.d.cts +13 -0
  50. package/dist/runtime/recovery/agent.d.ts +13 -0
  51. package/dist/runtime/recovery/agent.js +194 -0
  52. package/dist/runtime/recovery/errors.cjs +122 -0
  53. package/dist/runtime/recovery/errors.d.cts +31 -0
  54. package/dist/runtime/recovery/errors.d.ts +31 -0
  55. package/dist/runtime/recovery/errors.js +98 -0
  56. package/dist/runtime/recovery/index.cjs +34 -0
  57. package/dist/runtime/recovery/index.d.cts +7 -0
  58. package/dist/runtime/recovery/index.d.ts +7 -0
  59. package/dist/runtime/recovery/index.js +10 -0
  60. package/dist/runtime/recovery/recovery.cjs +53 -0
  61. package/dist/runtime/recovery/recovery.d.cts +12 -0
  62. package/dist/runtime/recovery/recovery.d.ts +12 -0
  63. package/dist/runtime/recovery/recovery.js +29 -0
  64. package/dist/runtime/step/index.cjs +31 -0
  65. package/dist/runtime/step/index.d.cts +7 -0
  66. package/dist/runtime/step/index.d.ts +7 -0
  67. package/dist/runtime/step/index.js +6 -0
  68. package/dist/runtime/step/runner.cjs +208 -0
  69. package/dist/runtime/step/runner.d.cts +16 -0
  70. package/dist/runtime/step/runner.d.ts +16 -0
  71. package/dist/runtime/step/runner.js +187 -0
  72. package/dist/runtime/step/step.cjs +67 -0
  73. package/dist/runtime/step/step.d.cts +23 -0
  74. package/dist/runtime/step/step.d.ts +23 -0
  75. package/dist/runtime/step/step.js +43 -0
  76. package/dist/runtime/step/types.cjs +16 -0
  77. package/dist/runtime/step/types.d.cts +72 -0
  78. package/dist/runtime/step/types.d.ts +72 -0
  79. package/dist/runtime/step/types.js +0 -0
  80. package/dist/shared/config/config.cjs +44 -0
  81. package/dist/shared/config/config.d.cts +10 -0
  82. package/dist/shared/config/config.d.ts +10 -0
  83. package/dist/shared/config/config.js +18 -0
  84. package/dist/shared/config/index.cjs +32 -0
  85. package/dist/shared/config/index.d.cts +1 -0
  86. package/dist/shared/config/index.d.ts +1 -0
  87. package/dist/shared/config/index.js +10 -0
  88. package/dist/shared/debug/index.cjs +32 -0
  89. package/dist/shared/debug/index.d.cts +2 -0
  90. package/dist/shared/debug/index.d.ts +2 -0
  91. package/dist/shared/debug/index.js +10 -0
  92. package/dist/shared/debug/pause.cjs +56 -0
  93. package/dist/shared/debug/pause.d.cts +23 -0
  94. package/dist/shared/debug/pause.d.ts +23 -0
  95. package/dist/shared/debug/pause.js +30 -0
  96. package/dist/shared/instrumentation/errors.cjs +81 -0
  97. package/dist/shared/instrumentation/errors.d.cts +12 -0
  98. package/dist/shared/instrumentation/errors.d.ts +12 -0
  99. package/dist/shared/instrumentation/errors.js +57 -0
  100. package/dist/shared/instrumentation/index.cjs +35 -0
  101. package/dist/shared/instrumentation/index.d.cts +6 -0
  102. package/dist/shared/instrumentation/index.d.ts +6 -0
  103. package/dist/shared/instrumentation/index.js +12 -0
  104. package/dist/shared/instrumentation/instrument.cjs +206 -0
  105. package/dist/shared/instrumentation/instrument.d.cts +32 -0
  106. package/dist/shared/instrumentation/instrument.d.ts +32 -0
  107. package/dist/shared/instrumentation/instrument.js +190 -0
  108. package/dist/shared/llm/client.cjs +139 -0
  109. package/dist/shared/llm/client.d.cts +6 -0
  110. package/dist/shared/llm/client.d.ts +6 -0
  111. package/dist/shared/llm/client.js +115 -0
  112. package/dist/shared/llm/index.cjs +28 -0
  113. package/dist/shared/llm/index.d.cts +3 -0
  114. package/dist/shared/llm/index.d.ts +3 -0
  115. package/dist/shared/llm/index.js +4 -0
  116. package/dist/shared/llm/types.cjs +16 -0
  117. package/dist/shared/llm/types.d.cts +34 -0
  118. package/dist/shared/llm/types.d.ts +34 -0
  119. package/dist/shared/llm/types.js +0 -0
  120. package/dist/shared/logger/index.cjs +35 -0
  121. package/dist/shared/logger/index.d.cts +2 -0
  122. package/dist/shared/logger/index.d.ts +2 -0
  123. package/dist/shared/logger/index.js +12 -0
  124. package/dist/shared/logger/logger.cjs +200 -0
  125. package/dist/shared/logger/logger.d.cts +70 -0
  126. package/dist/shared/logger/logger.d.ts +70 -0
  127. package/dist/shared/logger/logger.js +176 -0
  128. package/dist/shared/logger/sinks.cjs +160 -0
  129. package/dist/shared/logger/sinks.d.cts +9 -0
  130. package/dist/shared/logger/sinks.d.ts +9 -0
  131. package/dist/shared/logger/sinks.js +124 -0
  132. package/dist/shared/paths/paths.cjs +104 -0
  133. package/dist/shared/paths/paths.d.cts +10 -0
  134. package/dist/shared/paths/paths.d.ts +10 -0
  135. package/dist/shared/paths/paths.js +73 -0
  136. package/dist/shared/run/api.cjs +35 -0
  137. package/dist/shared/run/api.d.cts +3 -0
  138. package/dist/shared/run/api.d.ts +3 -0
  139. package/dist/shared/run/api.js +12 -0
  140. package/dist/shared/run/browser.cjs +98 -0
  141. package/dist/shared/run/browser.d.cts +22 -0
  142. package/dist/shared/run/browser.d.ts +22 -0
  143. package/dist/shared/run/browser.js +74 -0
  144. package/dist/shared/state/index.cjs +38 -0
  145. package/dist/shared/state/index.d.cts +2 -0
  146. package/dist/shared/state/index.d.ts +2 -0
  147. package/dist/shared/state/index.js +16 -0
  148. package/dist/shared/state/session-state.cjs +85 -0
  149. package/dist/shared/state/session-state.d.cts +34 -0
  150. package/dist/shared/state/session-state.d.ts +34 -0
  151. package/dist/shared/state/session-state.js +56 -0
  152. package/dist/shared/visualization/ghost-cursor.cjs +174 -0
  153. package/dist/shared/visualization/ghost-cursor.d.cts +37 -0
  154. package/dist/shared/visualization/ghost-cursor.d.ts +37 -0
  155. package/dist/shared/visualization/ghost-cursor.js +145 -0
  156. package/dist/shared/visualization/highlight.cjs +134 -0
  157. package/dist/shared/visualization/highlight.d.cts +22 -0
  158. package/dist/shared/visualization/highlight.d.ts +22 -0
  159. package/dist/shared/visualization/highlight.js +108 -0
  160. package/dist/shared/visualization/index.cjs +45 -0
  161. package/dist/shared/visualization/index.d.cts +3 -0
  162. package/dist/shared/visualization/index.d.ts +3 -0
  163. package/dist/shared/visualization/index.js +24 -0
  164. package/dist/shared/workflow/workflow.cjs +47 -0
  165. package/dist/shared/workflow/workflow.d.cts +33 -0
  166. package/dist/shared/workflow/workflow.d.ts +33 -0
  167. package/dist/shared/workflow/workflow.js +21 -0
  168. package/package.json +123 -26
  169. package/.npmignore +0 -2
  170. package/bin/libretto +0 -31
  171. package/lib/connect.js +0 -34
  172. package/lib/export.js +0 -224
  173. package/lib/import.js +0 -166
  174. package/lib/index.js +0 -8
  175. package/lib/log.js +0 -9
  176. package/lib/validate.js +0 -20
  177. package/makefile +0 -8
  178. package/src/connect.coffee +0 -25
  179. package/src/export.coffee +0 -222
  180. package/src/import.coffee +0 -166
  181. package/src/index.coffee +0 -3
  182. package/src/log.coffee +0 -3
  183. package/src/validate.coffee +0 -10
@@ -0,0 +1,115 @@
1
+ import { createVertex } from "@ai-sdk/google-vertex";
2
+ import { createAnthropic } from "@ai-sdk/anthropic";
3
+ import { createOpenAI } from "@ai-sdk/openai";
4
+ import { generateObject } from "ai";
5
+ function parseModel(model) {
6
+ const slashIndex = model.indexOf("/");
7
+ if (slashIndex === -1) {
8
+ throw new Error(
9
+ `Invalid model string "${model}". Expected format: "provider/model-id" (e.g. "google/gemini-3-flash-preview").`
10
+ );
11
+ }
12
+ const provider = model.slice(0, slashIndex);
13
+ const modelId = model.slice(slashIndex + 1);
14
+ if (!["google", "anthropic", "openai"].includes(provider)) {
15
+ throw new Error(
16
+ `Unsupported provider "${provider}". Supported providers: google, anthropic, openai.`
17
+ );
18
+ }
19
+ return { provider, modelId };
20
+ }
21
+ function getProviderModel(provider, modelId) {
22
+ switch (provider) {
23
+ case "google": {
24
+ const project = process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
25
+ if (!project) {
26
+ throw new Error(
27
+ "Missing GCP project for Vertex AI. Set GOOGLE_CLOUD_PROJECT environment variable and ensure application default credentials are configured (gcloud auth application-default login)."
28
+ );
29
+ }
30
+ const vertex = createVertex({
31
+ project,
32
+ location: process.env.GOOGLE_CLOUD_LOCATION || "global"
33
+ });
34
+ return vertex(modelId);
35
+ }
36
+ case "anthropic": {
37
+ const apiKey = process.env.ANTHROPIC_API_KEY;
38
+ if (!apiKey) {
39
+ throw new Error(
40
+ "Missing API key for Anthropic. Set ANTHROPIC_API_KEY environment variable."
41
+ );
42
+ }
43
+ const anthropic = createAnthropic({ apiKey });
44
+ return anthropic(modelId);
45
+ }
46
+ case "openai": {
47
+ const apiKey = process.env.OPENAI_API_KEY;
48
+ if (!apiKey) {
49
+ throw new Error(
50
+ "Missing API key for OpenAI. Set OPENAI_API_KEY environment variable."
51
+ );
52
+ }
53
+ const openai = createOpenAI({ apiKey });
54
+ return openai(modelId);
55
+ }
56
+ }
57
+ }
58
+ function convertUserContentParts(parts) {
59
+ return parts.map((part) => {
60
+ if (part.type === "text") {
61
+ return { type: "text", text: part.text };
62
+ }
63
+ return { type: "image", image: part.image };
64
+ });
65
+ }
66
+ function convertAssistantContentParts(parts) {
67
+ return parts.filter((part) => part.type === "text").map((part) => ({ type: "text", text: part.text }));
68
+ }
69
+ function convertMessages(messages) {
70
+ return messages.map((msg) => {
71
+ if (msg.role === "user") {
72
+ if (typeof msg.content === "string") {
73
+ return { role: "user", content: msg.content };
74
+ }
75
+ return {
76
+ role: "user",
77
+ content: convertUserContentParts(msg.content)
78
+ };
79
+ }
80
+ if (typeof msg.content === "string") {
81
+ return { role: "assistant", content: msg.content };
82
+ }
83
+ return {
84
+ role: "assistant",
85
+ content: convertAssistantContentParts(msg.content)
86
+ };
87
+ });
88
+ }
89
+ function createLLMClient(model) {
90
+ const { provider, modelId } = parseModel(model);
91
+ const aiModel = getProviderModel(provider, modelId);
92
+ return {
93
+ async generateObject(opts) {
94
+ const result = await generateObject({
95
+ model: aiModel,
96
+ prompt: opts.prompt,
97
+ schema: opts.schema,
98
+ temperature: opts.temperature ?? 0
99
+ });
100
+ return result.object;
101
+ },
102
+ async generateObjectFromMessages(opts) {
103
+ const result = await generateObject({
104
+ model: aiModel,
105
+ messages: convertMessages(opts.messages),
106
+ schema: opts.schema,
107
+ temperature: opts.temperature ?? 0
108
+ });
109
+ return result.object;
110
+ }
111
+ };
112
+ }
113
+ export {
114
+ createLLMClient
115
+ };
@@ -0,0 +1,28 @@
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
+ var llm_exports = {};
20
+ __export(llm_exports, {
21
+ createLLMClient: () => import_client.createLLMClient
22
+ });
23
+ module.exports = __toCommonJS(llm_exports);
24
+ var import_client = require("./client.js");
25
+ // Annotate the CommonJS export names for ESM import in node:
26
+ 0 && (module.exports = {
27
+ createLLMClient
28
+ });
@@ -0,0 +1,3 @@
1
+ export { LLMClient, Message, MessageContentPart } from './types.cjs';
2
+ export { createLLMClient } from './client.cjs';
3
+ import 'zod';
@@ -0,0 +1,3 @@
1
+ export { LLMClient, Message, MessageContentPart } from './types.js';
2
+ export { createLLMClient } from './client.js';
3
+ import 'zod';
@@ -0,0 +1,4 @@
1
+ import { createLLMClient } from "./client.js";
2
+ export {
3
+ createLLMClient
4
+ };
@@ -0,0 +1,16 @@
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 __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var types_exports = {};
16
+ module.exports = __toCommonJS(types_exports);
@@ -0,0 +1,34 @@
1
+ import { ZodType, infer } from 'zod';
2
+
3
+ type MessageContentPart = {
4
+ type: "text";
5
+ text: string;
6
+ } | {
7
+ type: "image";
8
+ image: string;
9
+ };
10
+ type Message = {
11
+ role: "user" | "assistant";
12
+ content: string | MessageContentPart[];
13
+ };
14
+ /**
15
+ * Pluggable LLM client interface.
16
+ *
17
+ * Users provide their own implementation backed by any LLM provider
18
+ * (OpenAI, Anthropic, etc.). Libretto uses this interface for AI extraction,
19
+ * recovery agents, and error detection.
20
+ */
21
+ interface LLMClient {
22
+ generateObject<T extends ZodType>(opts: {
23
+ prompt: string;
24
+ schema: T;
25
+ temperature?: number;
26
+ }): Promise<infer<T>>;
27
+ generateObjectFromMessages<T extends ZodType>(opts: {
28
+ messages: Message[];
29
+ schema: T;
30
+ temperature?: number;
31
+ }): Promise<infer<T>>;
32
+ }
33
+
34
+ export type { LLMClient, Message, MessageContentPart };
@@ -0,0 +1,34 @@
1
+ import { ZodType, infer } from 'zod';
2
+
3
+ type MessageContentPart = {
4
+ type: "text";
5
+ text: string;
6
+ } | {
7
+ type: "image";
8
+ image: string;
9
+ };
10
+ type Message = {
11
+ role: "user" | "assistant";
12
+ content: string | MessageContentPart[];
13
+ };
14
+ /**
15
+ * Pluggable LLM client interface.
16
+ *
17
+ * Users provide their own implementation backed by any LLM provider
18
+ * (OpenAI, Anthropic, etc.). Libretto uses this interface for AI extraction,
19
+ * recovery agents, and error detection.
20
+ */
21
+ interface LLMClient {
22
+ generateObject<T extends ZodType>(opts: {
23
+ prompt: string;
24
+ schema: T;
25
+ temperature?: number;
26
+ }): Promise<infer<T>>;
27
+ generateObjectFromMessages<T extends ZodType>(opts: {
28
+ messages: Message[];
29
+ schema: T;
30
+ temperature?: number;
31
+ }): Promise<infer<T>>;
32
+ }
33
+
34
+ export type { LLMClient, Message, MessageContentPart };
File without changes
@@ -0,0 +1,35 @@
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
+ var logger_exports = {};
20
+ __export(logger_exports, {
21
+ Logger: () => import_logger.Logger,
22
+ createFileLogSink: () => import_sinks.createFileLogSink,
23
+ jsonlConsoleSink: () => import_sinks.jsonlConsoleSink,
24
+ prettyConsoleSink: () => import_sinks.prettyConsoleSink
25
+ });
26
+ module.exports = __toCommonJS(logger_exports);
27
+ var import_logger = require("./logger.js");
28
+ var import_sinks = require("./sinks.js");
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ Logger,
32
+ createFileLogSink,
33
+ jsonlConsoleSink,
34
+ prettyConsoleSink
35
+ });
@@ -0,0 +1,2 @@
1
+ export { LogOptions, Logger, LoggerApi, LoggerSink } from './logger.cjs';
2
+ export { createFileLogSink, jsonlConsoleSink, prettyConsoleSink } from './sinks.cjs';
@@ -0,0 +1,2 @@
1
+ export { LogOptions, Logger, LoggerApi, LoggerSink } from './logger.js';
2
+ export { createFileLogSink, jsonlConsoleSink, prettyConsoleSink } from './sinks.js';
@@ -0,0 +1,12 @@
1
+ import { Logger } from "./logger.js";
2
+ import {
3
+ createFileLogSink,
4
+ prettyConsoleSink,
5
+ jsonlConsoleSink
6
+ } from "./sinks.js";
7
+ export {
8
+ Logger,
9
+ createFileLogSink,
10
+ jsonlConsoleSink,
11
+ prettyConsoleSink
12
+ };
@@ -0,0 +1,200 @@
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
+ var logger_exports = {};
20
+ __export(logger_exports, {
21
+ Logger: () => Logger
22
+ });
23
+ module.exports = __toCommonJS(logger_exports);
24
+ function generateId() {
25
+ return Math.random().toString(36).substring(2, 15);
26
+ }
27
+ const sinkLifecycleState = /* @__PURE__ */ new WeakMap();
28
+ function getSinkLifecycleState(sink) {
29
+ const existingState = sinkLifecycleState.get(sink);
30
+ if (existingState) {
31
+ return existingState;
32
+ }
33
+ const initialState = { closed: false };
34
+ sinkLifecycleState.set(sink, initialState);
35
+ return initialState;
36
+ }
37
+ function isSinkClosedOrClosing(sink) {
38
+ const state = sinkLifecycleState.get(sink);
39
+ return Boolean(state?.closed || state?.closing);
40
+ }
41
+ async function closeSinkOnce(sink) {
42
+ if (!sink.close) {
43
+ return;
44
+ }
45
+ const state = getSinkLifecycleState(sink);
46
+ if (state.closed) {
47
+ return;
48
+ }
49
+ if (state.closing) {
50
+ return state.closing;
51
+ }
52
+ state.closing = (async () => {
53
+ try {
54
+ await sink.close?.();
55
+ } catch {
56
+ } finally {
57
+ state.closed = true;
58
+ state.closing = void 0;
59
+ }
60
+ })();
61
+ return state.closing;
62
+ }
63
+ function isObject(value) {
64
+ return typeof value === "object" && value !== null;
65
+ }
66
+ function removeUndefined(data) {
67
+ if (typeof data === "object" && data !== null) {
68
+ return Object.fromEntries(
69
+ Object.entries(data).filter(([_, value]) => value !== void 0)
70
+ );
71
+ }
72
+ return data;
73
+ }
74
+ class Logger {
75
+ constructor(scopes = [], sinks = [], scopeData = {}) {
76
+ this.scopes = scopes;
77
+ this.sinks = sinks;
78
+ this.scopeData = scopeData;
79
+ this.prefix = scopes.join(".");
80
+ }
81
+ prefix;
82
+ entry(entry) {
83
+ this.sinks.forEach((sink) => {
84
+ if (isSinkClosedOrClosing(sink)) {
85
+ return;
86
+ }
87
+ sink.write({
88
+ id: generateId(),
89
+ scope: this.prefix,
90
+ level: entry.level,
91
+ event: entry.event,
92
+ data: removeUndefined({ ...this.scopeData, ...entry.data }),
93
+ options: entry.options
94
+ });
95
+ });
96
+ }
97
+ log(event, data, options) {
98
+ this.entry({ level: "log", event, data, options });
99
+ }
100
+ error(event, dataOrError, options) {
101
+ const data = dataOrError instanceof Error ? {
102
+ error: {
103
+ type: dataOrError.constructor.name,
104
+ message: dataOrError.message,
105
+ stack: dataOrError.stack || null
106
+ }
107
+ } : isObject(dataOrError) && dataOrError.error instanceof Error ? {
108
+ ...dataOrError,
109
+ error: {
110
+ type: dataOrError.error.constructor.name,
111
+ message: dataOrError.error.message,
112
+ stack: dataOrError.error.stack || null
113
+ }
114
+ } : isObject(dataOrError) ? dataOrError : dataOrError !== void 0 ? { error: dataOrError } : void 0;
115
+ this.entry({
116
+ level: "error",
117
+ event,
118
+ data,
119
+ options
120
+ });
121
+ if (dataOrError instanceof Error) {
122
+ return dataOrError;
123
+ }
124
+ if (isObject(dataOrError) && dataOrError.error instanceof Error) {
125
+ return dataOrError.error;
126
+ }
127
+ let message = event;
128
+ if (data !== void 0) {
129
+ try {
130
+ message += "\n" + JSON.stringify(data, void 0, 2);
131
+ } catch {
132
+ message += "\n[Unserializable error data]";
133
+ }
134
+ }
135
+ return new Error(message);
136
+ }
137
+ warn(event, dataOrError, options) {
138
+ const data = dataOrError instanceof Error ? {
139
+ error: {
140
+ type: dataOrError.constructor.name,
141
+ message: dataOrError.message,
142
+ stack: dataOrError.stack || null
143
+ }
144
+ } : isObject(dataOrError) && dataOrError.error instanceof Error ? {
145
+ ...dataOrError,
146
+ error: {
147
+ type: dataOrError.error.constructor.name,
148
+ message: dataOrError.error.message,
149
+ stack: dataOrError.error.stack || null
150
+ }
151
+ } : isObject(dataOrError) ? dataOrError : dataOrError !== void 0 ? { error: dataOrError } : void 0;
152
+ this.entry({
153
+ level: "warn",
154
+ event,
155
+ data,
156
+ options
157
+ });
158
+ }
159
+ info(event, data, options) {
160
+ this.entry({ level: "info", event, data, options });
161
+ }
162
+ withScope(scope, context = {}) {
163
+ return new Logger([...this.scopes, scope], this.sinks, {
164
+ ...this.scopeData,
165
+ ...context
166
+ });
167
+ }
168
+ withContext(context) {
169
+ return new Logger(this.scopes, this.sinks, {
170
+ ...this.scopeData,
171
+ ...context
172
+ });
173
+ }
174
+ withSink(sink) {
175
+ return new Logger(this.scopes, [...this.sinks, sink]);
176
+ }
177
+ async flush() {
178
+ for (let i = this.sinks.length - 1; i >= 0; i--) {
179
+ const sink = this.sinks[i];
180
+ if (!sink) continue;
181
+ if (isSinkClosedOrClosing(sink)) continue;
182
+ try {
183
+ await sink.flush?.();
184
+ } catch {
185
+ }
186
+ }
187
+ }
188
+ async close() {
189
+ await this.flush();
190
+ for (let i = this.sinks.length - 1; i >= 0; i--) {
191
+ const sink = this.sinks[i];
192
+ if (!sink) continue;
193
+ await closeSinkOnce(sink);
194
+ }
195
+ }
196
+ }
197
+ // Annotate the CommonJS export names for ESM import in node:
198
+ 0 && (module.exports = {
199
+ Logger
200
+ });
@@ -0,0 +1,70 @@
1
+ type LogOptions = {
2
+ timestamp?: Date;
3
+ };
4
+ type LoggerApi = {
5
+ log: (event: string, data?: Record<string, any>, options?: LogOptions) => void;
6
+ /**
7
+ * Logs an error and returns an Error object that can be thrown
8
+ *
9
+ * either pass in an Error directly as data or as { error: Error, ...other_data }
10
+ */
11
+ error: (event: string, data?: Error | ({
12
+ error: Error;
13
+ } & Record<string, any>) | unknown, options?: LogOptions) => Error;
14
+ warn: (event: string, data?: Error | ({
15
+ error: Error;
16
+ } & Record<string, any>) | unknown, options?: LogOptions) => void;
17
+ info: (event: string, data?: Record<string, any>, options?: LogOptions) => void;
18
+ /**
19
+ * Context passed in will be attached to all entries in this scope.
20
+ */
21
+ withScope: (scope: string, context?: Record<string, any>) => LoggerApi;
22
+ /**
23
+ * Context passed in will be attached to all entries.
24
+ */
25
+ withContext: (context: Record<string, any>) => LoggerApi;
26
+ /**
27
+ * Flushes all sinks in reverse order (most recently added first).
28
+ */
29
+ flush: () => Promise<void>;
30
+ };
31
+ type LoggerSink = {
32
+ write: (args: {
33
+ id: string;
34
+ scope: string;
35
+ level: "log" | "error" | "warn" | "info";
36
+ event: string;
37
+ data: Record<string, any>;
38
+ options?: LogOptions;
39
+ }) => void;
40
+ flush?: () => Promise<void>;
41
+ close?: () => Promise<void>;
42
+ };
43
+ declare class Logger implements LoggerApi {
44
+ private readonly scopes;
45
+ private readonly sinks;
46
+ private readonly scopeData;
47
+ private readonly prefix;
48
+ constructor(scopes?: string[], sinks?: LoggerSink[], scopeData?: Record<string, any>);
49
+ entry(entry: {
50
+ level: "log" | "error" | "warn" | "info";
51
+ event: string;
52
+ data?: Record<string, any>;
53
+ options?: LogOptions;
54
+ }): void;
55
+ log(event: string, data?: Record<string, any>, options?: LogOptions): void;
56
+ error(event: string, dataOrError?: Error | ({
57
+ error: Error;
58
+ } & Record<string, any>) | unknown, options?: LogOptions): Error;
59
+ warn(event: string, dataOrError?: Error | ({
60
+ error: Error;
61
+ } & Record<string, any>) | unknown, options?: LogOptions): void;
62
+ info(event: string, data?: Record<string, any>, options?: LogOptions): void;
63
+ withScope(scope: string, context?: Record<string, any>): LoggerApi;
64
+ withContext(context: Record<string, any>): LoggerApi;
65
+ withSink(sink: LoggerSink): Logger;
66
+ flush(): Promise<void>;
67
+ close(): Promise<void>;
68
+ }
69
+
70
+ export { type LogOptions, Logger, type LoggerApi, type LoggerSink };
@@ -0,0 +1,70 @@
1
+ type LogOptions = {
2
+ timestamp?: Date;
3
+ };
4
+ type LoggerApi = {
5
+ log: (event: string, data?: Record<string, any>, options?: LogOptions) => void;
6
+ /**
7
+ * Logs an error and returns an Error object that can be thrown
8
+ *
9
+ * either pass in an Error directly as data or as { error: Error, ...other_data }
10
+ */
11
+ error: (event: string, data?: Error | ({
12
+ error: Error;
13
+ } & Record<string, any>) | unknown, options?: LogOptions) => Error;
14
+ warn: (event: string, data?: Error | ({
15
+ error: Error;
16
+ } & Record<string, any>) | unknown, options?: LogOptions) => void;
17
+ info: (event: string, data?: Record<string, any>, options?: LogOptions) => void;
18
+ /**
19
+ * Context passed in will be attached to all entries in this scope.
20
+ */
21
+ withScope: (scope: string, context?: Record<string, any>) => LoggerApi;
22
+ /**
23
+ * Context passed in will be attached to all entries.
24
+ */
25
+ withContext: (context: Record<string, any>) => LoggerApi;
26
+ /**
27
+ * Flushes all sinks in reverse order (most recently added first).
28
+ */
29
+ flush: () => Promise<void>;
30
+ };
31
+ type LoggerSink = {
32
+ write: (args: {
33
+ id: string;
34
+ scope: string;
35
+ level: "log" | "error" | "warn" | "info";
36
+ event: string;
37
+ data: Record<string, any>;
38
+ options?: LogOptions;
39
+ }) => void;
40
+ flush?: () => Promise<void>;
41
+ close?: () => Promise<void>;
42
+ };
43
+ declare class Logger implements LoggerApi {
44
+ private readonly scopes;
45
+ private readonly sinks;
46
+ private readonly scopeData;
47
+ private readonly prefix;
48
+ constructor(scopes?: string[], sinks?: LoggerSink[], scopeData?: Record<string, any>);
49
+ entry(entry: {
50
+ level: "log" | "error" | "warn" | "info";
51
+ event: string;
52
+ data?: Record<string, any>;
53
+ options?: LogOptions;
54
+ }): void;
55
+ log(event: string, data?: Record<string, any>, options?: LogOptions): void;
56
+ error(event: string, dataOrError?: Error | ({
57
+ error: Error;
58
+ } & Record<string, any>) | unknown, options?: LogOptions): Error;
59
+ warn(event: string, dataOrError?: Error | ({
60
+ error: Error;
61
+ } & Record<string, any>) | unknown, options?: LogOptions): void;
62
+ info(event: string, data?: Record<string, any>, options?: LogOptions): void;
63
+ withScope(scope: string, context?: Record<string, any>): LoggerApi;
64
+ withContext(context: Record<string, any>): LoggerApi;
65
+ withSink(sink: LoggerSink): Logger;
66
+ flush(): Promise<void>;
67
+ close(): Promise<void>;
68
+ }
69
+
70
+ export { type LogOptions, Logger, type LoggerApi, type LoggerSink };