@marshmallo/marlo 0.1.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 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/buffered-sender.ts","../src/client.ts","../src/digest.ts","../src/ids.ts","../src/registry.ts","../src/context.ts"],"sourcesContent":["export { init, shutdown, getClient, isEnabled, MarloClient } from './client';\nexport { task, TaskContext } from './context';\nexport { registerAgent, registerAgent as agent, getAgent } from './registry';\nexport { generateId } from './ids';\nexport { jsonDigest } from './digest';\nexport type {\n Scope,\n AgentDefinition,\n Event,\n LearningState,\n ToolDefinition,\n McpDefinition,\n ModelConfig,\n TokenUsage,\n LlmCallParams,\n} from './types';\n","import type { Event } from './types';\n\nconst DEFAULT_BATCH_SIZE = 50;\nconst DEFAULT_FLUSH_INTERVAL_MS = 1000;\nconst DEFAULT_RETRIES = 3;\nconst DEFAULT_RETRY_BACKOFF_MS = 500;\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nfunction warn(message: string): void {\n console.warn(`[marlo] ${message}`);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport interface BufferedEventSenderConfig {\n eventsUrl: string;\n apiKey: string;\n batchSize?: number;\n flushIntervalMs?: number;\n maxRetries?: number;\n retryBackoffMs?: number;\n}\n\nexport class BufferedEventSender {\n private readonly eventsUrl: string;\n private readonly headers: Record<string, string>;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private readonly maxRetries: number;\n private readonly retryBackoffMs: number;\n private queue: Event[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private isShutdown = false;\n\n constructor(config: BufferedEventSenderConfig) {\n this.eventsUrl = config.eventsUrl;\n this.headers = { Authorization: `Bearer ${config.apiKey}` };\n this.batchSize = Math.max(1, config.batchSize ?? DEFAULT_BATCH_SIZE);\n this.flushIntervalMs = Math.max(\n 100,\n config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS\n );\n this.maxRetries = Math.max(1, config.maxRetries ?? DEFAULT_RETRIES);\n this.retryBackoffMs = Math.max(\n 100,\n config.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS\n );\n\n this.flushTimer = setInterval(() => {\n this.flushAsync().catch(() => {});\n }, this.flushIntervalMs);\n }\n\n enqueue(events: Event[]): void {\n if (!events.length || this.isShutdown) {\n return;\n }\n this.queue.push(...events);\n if (this.queue.length >= this.batchSize) {\n this.flushAsync().catch(() => {});\n }\n }\n\n async flush(): Promise<void> {\n await this.flushAsync();\n }\n\n async shutdown(): Promise<void> {\n this.isShutdown = true;\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flushAsync();\n }\n\n private async flushAsync(): Promise<void> {\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0, this.batchSize);\n const success = await this.sendWithRetry(batch);\n if (!success) {\n this.queue.unshift(...batch);\n return;\n }\n }\n }\n\n private async sendWithRetry(batch: Event[]): Promise<boolean> {\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\n if (await this.sendBatch(batch)) {\n return true;\n }\n await sleep(this.retryBackoffMs * 2 ** attempt);\n }\n return false;\n }\n\n private async sendBatch(batch: Event[]): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);\n\n const response = await fetch(this.eventsUrl, {\n method: 'POST',\n headers: {\n ...this.headers,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(batch),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.status >= 200 && response.status < 300) {\n return true;\n }\n warn(`Event send returned ${response.status}`);\n return false;\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n warn('Event send timed out');\n } else {\n warn(`Event send failed: ${error.message}`);\n }\n } else {\n warn('Event send failed');\n }\n return false;\n }\n }\n}\n","import { BufferedEventSender } from './buffered-sender';\nimport type { Event, LearningState, Scope } from './types';\n\nconst DEFAULT_ENDPOINT = 'https://marlo.marshmallo.ai';\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nfunction warn(message: string): void {\n console.warn(`[marlo] ${message}`);\n}\n\nfunction info(message: string): void {\n console.info(`[marlo] ${message}`);\n}\n\nlet _client: MarloClient | null = null;\nlet _enabled = false;\n\nexport class MarloClient {\n private readonly apiKey: string;\n private readonly endpoint: string;\n private readonly _scope: Scope;\n private readonly sender: BufferedEventSender;\n\n constructor(apiKey: string, endpoint: string, scope: Scope) {\n this.apiKey = apiKey;\n this.endpoint = endpoint.replace(/\\/+$/, '');\n this._scope = scope;\n this.sender = new BufferedEventSender({\n eventsUrl: `${this.endpoint}/events`,\n apiKey,\n });\n }\n\n get scope(): Scope {\n return this._scope;\n }\n\n sendEvents(events: Event[]): void {\n this.sender.enqueue(events);\n }\n\n async flush(): Promise<void> {\n await this.sender.flush();\n }\n\n async shutdown(): Promise<void> {\n await this.sender.shutdown();\n }\n\n async fetchLearnings(learningKey: string): Promise<LearningState | null> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);\n\n const response = await fetch(`${this.endpoint}/learnings`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ learning_key: learningKey }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.status < 200 || response.status >= 300) {\n return null;\n }\n\n const data = await response.json();\n return data.learning_state ?? null;\n } catch (error) {\n if (error instanceof Error) {\n warn(`Fetch learnings failed: ${error.message}`);\n } else {\n warn('Fetch learnings failed');\n }\n return null;\n }\n }\n}\n\nexport async function init(\n apiKey: string,\n endpoint: string = DEFAULT_ENDPOINT\n): Promise<void> {\n const normalizedEndpoint = endpoint.replace(/\\/+$/, '');\n const scopeUrl = `${normalizedEndpoint}/scope`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);\n\n const response = await fetch(scopeUrl, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.status !== 200) {\n warn(`Marlo init failed: scope request returned ${response.status}`);\n _enabled = false;\n return;\n }\n\n const payload = await response.json();\n const scopeData = payload.scope ?? {};\n const projectId = scopeData.project_id;\n const orgId = scopeData.org_id;\n const userId = scopeData.user_id;\n\n if (\n typeof projectId !== 'string' ||\n !projectId.trim() ||\n typeof orgId !== 'string' ||\n !orgId.trim() ||\n typeof userId !== 'string' ||\n !userId.trim()\n ) {\n warn('Marlo init failed: invalid scope response');\n _enabled = false;\n return;\n }\n\n const scope: Scope = {\n project_id: projectId.trim(),\n org_id: orgId.trim(),\n user_id: userId.trim(),\n };\n\n _client = new MarloClient(apiKey, normalizedEndpoint, scope);\n _enabled = true;\n info(`Marlo SDK initialized for project ${projectId}`);\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n warn('Marlo init failed: timeout');\n } else if (\n error.message.includes('ECONNREFUSED') ||\n error.message.includes('fetch failed')\n ) {\n warn('Marlo init failed: connection error');\n } else {\n warn(`Marlo init failed: ${error.message}`);\n }\n } else {\n warn('Marlo init failed');\n }\n _enabled = false;\n }\n}\n\nexport function getClient(): MarloClient | null {\n return _client;\n}\n\nexport function isEnabled(): boolean {\n return _enabled;\n}\n\nexport async function shutdown(): Promise<void> {\n if (_client) {\n await _client.shutdown();\n _client = null;\n }\n _enabled = false;\n}\n","import { createHash } from 'crypto';\n\nfunction sortObject(value: unknown): unknown {\n if (value === null || value === undefined) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(sortObject);\n }\n if (typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(value as Record<string, unknown>).sort();\n for (const key of keys) {\n sorted[key] = sortObject((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n\nexport function jsonDigest(payload: unknown): string {\n const sorted = sortObject(payload);\n const encoded = JSON.stringify(sorted);\n return createHash('sha256').update(encoded, 'utf-8').digest('hex');\n}\n","const ID_EPOCH_MS = 1700000000000;\nconst WORKER_ID_BITS = 10;\nconst SEQUENCE_BITS = 12;\nconst MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;\nconst MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1;\nconst WORKER_ID_SHIFT = SEQUENCE_BITS;\nconst TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;\n\nfunction parseWorkerId(): number {\n const raw = (process.env.MARLO_WORKER_ID ?? '0').trim();\n if (!raw) {\n return 0;\n }\n const workerId = parseInt(raw, 10);\n if (isNaN(workerId) || workerId < 0 || workerId > MAX_WORKER_ID) {\n return 0;\n }\n return workerId;\n}\n\nconst WORKER_ID = parseWorkerId();\n\nclass IdGenerator {\n private lastTs = 0;\n private sequence = 0;\n\n nextId(): number {\n let ts = Date.now();\n\n if (ts < this.lastTs) {\n ts = this.waitUntil(this.lastTs);\n }\n\n if (ts === this.lastTs) {\n this.sequence = (this.sequence + 1) & MAX_SEQUENCE;\n if (this.sequence === 0) {\n ts = this.waitUntil(this.lastTs + 1);\n }\n } else {\n this.sequence = 0;\n }\n\n this.lastTs = ts;\n return (\n ((ts - ID_EPOCH_MS) << TIMESTAMP_SHIFT) |\n (WORKER_ID << WORKER_ID_SHIFT) |\n this.sequence\n );\n }\n\n private waitUntil(targetMs: number): number {\n let ts = Date.now();\n while (ts < targetMs) {\n ts = Date.now();\n }\n return ts;\n }\n}\n\nconst idGenerator = new IdGenerator();\n\nexport function generateId(): number {\n return idGenerator.nextId();\n}\n","import { jsonDigest } from './digest';\nimport type {\n AgentDefinition,\n ToolDefinition,\n McpDefinition,\n ModelConfig,\n} from './types';\n\nclass AgentRegistry {\n private agents: Map<string, AgentDefinition> = new Map();\n\n register(definition: AgentDefinition): void {\n const existing = this.agents.get(definition.name);\n if (!existing) {\n this.agents.set(definition.name, definition);\n } else if (existing.definition_hash !== definition.definition_hash) {\n definition.sent = false;\n this.agents.set(definition.name, definition);\n } else {\n definition.sent = existing.sent;\n this.agents.set(definition.name, definition);\n }\n }\n\n get(name: string): AgentDefinition | null {\n return this.agents.get(name) ?? null;\n }\n\n markSent(name: string): void {\n const agent = this.agents.get(name);\n if (agent) {\n agent.sent = true;\n }\n }\n\n needsResend(name: string): boolean {\n const agent = this.agents.get(name);\n return agent !== null && agent !== undefined && !agent.sent;\n }\n}\n\nlet registry: AgentRegistry | null = null;\n\nfunction getRegistry(): AgentRegistry {\n if (!registry) {\n registry = new AgentRegistry();\n }\n return registry;\n}\n\nexport function registerAgent(\n name: string,\n systemPrompt: string,\n tools: ToolDefinition[],\n mcp?: McpDefinition[] | null,\n modelConfig?: ModelConfig | null\n): string {\n const definitionHash = jsonDigest({\n name,\n system_prompt: systemPrompt,\n tool_definitions: tools,\n mcp_definitions: mcp ?? null,\n model_config: modelConfig ?? null,\n });\n\n const definition: AgentDefinition = {\n name,\n system_prompt: systemPrompt,\n tools,\n mcp: mcp ?? null,\n model_config: modelConfig ?? null,\n definition_hash: definitionHash,\n sent: false,\n };\n\n getRegistry().register(definition);\n return definitionHash;\n}\n\nexport function getAgent(name: string): AgentDefinition | null {\n return getRegistry().get(name);\n}\n\nexport function markAgentSent(name: string): void {\n getRegistry().markSent(name);\n}\n\nexport function needsResend(name: string): boolean {\n return getRegistry().needsResend(name);\n}\n","import { getClient, isEnabled } from './client';\nimport { jsonDigest } from './digest';\nimport { generateId } from './ids';\nimport { getAgent, markAgentSent, needsResend } from './registry';\nimport type { Event, LearningState, LlmCallParams } from './types';\n\nfunction warn(message: string): void {\n console.warn(`[marlo] ${message}`);\n}\n\nfunction generateInvocationId(): string {\n return crypto.randomUUID();\n}\n\nfunction computeSessionId(projectId: string, threadId: string): number {\n const digest = jsonDigest(`${projectId}:${threadId}`);\n return parseInt(digest.slice(0, 16), 16);\n}\n\nexport function task(\n threadId: string,\n agent: string,\n threadName?: string\n): TaskContext {\n return new TaskContext(threadId, agent, threadName);\n}\n\nexport class TaskContext {\n private readonly threadId: string;\n private readonly agentName: string;\n private readonly threadName: string | undefined;\n private readonly parent: TaskContext | undefined;\n private taskId: number | null = null;\n private sessionId: number | null = null;\n private invocationId: string | null = null;\n private inputText: string | null = null;\n private outputText: string | null = null;\n private errorMessage: string | null = null;\n private events: Event[] = [];\n\n constructor(\n threadId: string,\n agent: string,\n threadName?: string,\n parent?: TaskContext\n ) {\n this.threadId = threadId;\n this.agentName = agent;\n this.threadName = threadName;\n this.parent = parent;\n }\n\n start(): this {\n try {\n const client = getClient();\n const projectId = client?.scope.project_id ?? '';\n this.sessionId = computeSessionId(projectId, this.threadId);\n this.taskId = generateId();\n this.invocationId = generateInvocationId();\n\n if (needsResend(this.agentName)) {\n const agentDef = getAgent(this.agentName);\n if (agentDef) {\n this.emit('agent_definition', {\n name: agentDef.name,\n system_prompt: agentDef.system_prompt,\n tool_definitions: agentDef.tools,\n mcp_definitions: agentDef.mcp,\n model_config: agentDef.model_config,\n definition_hash: agentDef.definition_hash,\n });\n markAgentSent(this.agentName);\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext start failed: ${error.message}`);\n } else {\n warn('TaskContext start failed');\n }\n }\n return this;\n }\n\n end(hasError?: boolean): void {\n try {\n const status =\n hasError || this.errorMessage !== null ? 'error' : 'success';\n const payload: Record<string, unknown> = { status };\n if (this.outputText !== null) {\n payload.final_answer = this.outputText;\n }\n if (this.errorMessage !== null) {\n payload.error = this.errorMessage;\n }\n this.emit('task_end', payload);\n this.flush();\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext end failed: ${error.message}`);\n } else {\n warn('TaskContext end failed');\n }\n }\n }\n\n input(text: string): void {\n try {\n this.inputText = text;\n const metadata: Record<string, unknown> = { thread_id: this.threadId };\n if (this.threadName !== undefined) {\n metadata.thread_name = this.threadName;\n }\n this.emit('task_start', { task: text, metadata });\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext input failed: ${error.message}`);\n } else {\n warn('TaskContext input failed');\n }\n }\n }\n\n output(text: string): void {\n try {\n this.outputText = text;\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext output failed: ${error.message}`);\n } else {\n warn('TaskContext output failed');\n }\n }\n }\n\n tool(\n name: string,\n input: Record<string, unknown>,\n output: unknown,\n error?: string\n ): void {\n try {\n const payload: Record<string, unknown> = {\n tool_name: name,\n input,\n output,\n };\n if (error !== undefined) {\n payload.error = error;\n }\n this.emit('tool_call', payload);\n } catch (err) {\n if (err instanceof Error) {\n warn(`TaskContext tool failed: ${err.message}`);\n } else {\n warn('TaskContext tool failed');\n }\n }\n }\n\n reasoning(text: string): void {\n try {\n this.emit('log', { reasoning: text });\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext reasoning failed: ${error.message}`);\n } else {\n warn('TaskContext reasoning failed');\n }\n }\n }\n\n llm(params: LlmCallParams): void {\n try {\n if (params.messages === undefined) {\n warn('llm() called without messages');\n }\n if (params.response === undefined) {\n warn('llm() called without response');\n }\n\n const payload: Record<string, unknown> = {\n model: params.model,\n usage: params.usage,\n };\n if (params.messages !== undefined) {\n payload.messages = params.messages;\n }\n if (params.response !== undefined) {\n payload.response = params.response;\n }\n this.emit('llm_call', payload);\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext llm failed: ${error.message}`);\n } else {\n warn('TaskContext llm failed');\n }\n }\n }\n\n error(message: string): void {\n try {\n this.errorMessage = message;\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext error failed: ${error.message}`);\n } else {\n warn('TaskContext error failed');\n }\n }\n }\n\n child(agent: string): TaskContext {\n return new TaskContext(this.threadId, agent, this.threadName, this);\n }\n\n async getLearnings(): Promise<LearningState | null> {\n try {\n const client = getClient();\n if (!client) {\n return null;\n }\n return await client.fetchLearnings(this.agentName);\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext getLearnings failed: ${error.message}`);\n } else {\n warn('TaskContext getLearnings failed');\n }\n return null;\n }\n }\n\n private emit(eventType: string, payload: Record<string, unknown>): void {\n const agentDef = getAgent(this.agentName);\n const agentId = agentDef?.name ?? this.agentName;\n const parentAgentId = this.parent?.agentName ?? null;\n\n const event: Event = {\n run_id: this.sessionId,\n agent_id: agentId,\n parent_agent_id: parentAgentId,\n invocation_id: this.invocationId,\n task_id: this.taskId,\n event_type: eventType,\n payload,\n };\n this.events.push(event);\n }\n\n private flush(): void {\n const client = getClient();\n if (!client || !isEnabled()) {\n this.events = [];\n return;\n }\n try {\n client.sendEvents(this.events);\n client.flush();\n } catch (error) {\n if (error instanceof Error) {\n warn(`TaskContext flush failed: ${error.message}`);\n } else {\n warn('TaskContext flush failed');\n }\n } finally {\n this.events = [];\n }\n }\n}\n"],"mappings":"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","names":["DEFAULT_TIMEOUT_MS","warn","warn"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,622 @@
1
+ // src/buffered-sender.ts
2
+ var DEFAULT_BATCH_SIZE = 50;
3
+ var DEFAULT_FLUSH_INTERVAL_MS = 1e3;
4
+ var DEFAULT_RETRIES = 3;
5
+ var DEFAULT_RETRY_BACKOFF_MS = 500;
6
+ var DEFAULT_TIMEOUT_MS = 5e3;
7
+ function warn(message) {
8
+ console.warn(`[marlo] ${message}`);
9
+ }
10
+ function sleep(ms) {
11
+ return new Promise((resolve) => setTimeout(resolve, ms));
12
+ }
13
+ var BufferedEventSender = class {
14
+ constructor(config) {
15
+ this.queue = [];
16
+ this.flushTimer = null;
17
+ this.isShutdown = false;
18
+ this.eventsUrl = config.eventsUrl;
19
+ this.headers = { Authorization: `Bearer ${config.apiKey}` };
20
+ this.batchSize = Math.max(1, config.batchSize ?? DEFAULT_BATCH_SIZE);
21
+ this.flushIntervalMs = Math.max(
22
+ 100,
23
+ config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS
24
+ );
25
+ this.maxRetries = Math.max(1, config.maxRetries ?? DEFAULT_RETRIES);
26
+ this.retryBackoffMs = Math.max(
27
+ 100,
28
+ config.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS
29
+ );
30
+ this.flushTimer = setInterval(() => {
31
+ this.flushAsync().catch(() => {
32
+ });
33
+ }, this.flushIntervalMs);
34
+ }
35
+ enqueue(events) {
36
+ if (!events.length || this.isShutdown) {
37
+ return;
38
+ }
39
+ this.queue.push(...events);
40
+ if (this.queue.length >= this.batchSize) {
41
+ this.flushAsync().catch(() => {
42
+ });
43
+ }
44
+ }
45
+ async flush() {
46
+ await this.flushAsync();
47
+ }
48
+ async shutdown() {
49
+ this.isShutdown = true;
50
+ if (this.flushTimer) {
51
+ clearInterval(this.flushTimer);
52
+ this.flushTimer = null;
53
+ }
54
+ await this.flushAsync();
55
+ }
56
+ async flushAsync() {
57
+ while (this.queue.length > 0) {
58
+ const batch = this.queue.splice(0, this.batchSize);
59
+ const success = await this.sendWithRetry(batch);
60
+ if (!success) {
61
+ this.queue.unshift(...batch);
62
+ return;
63
+ }
64
+ }
65
+ }
66
+ async sendWithRetry(batch) {
67
+ for (let attempt = 0; attempt < this.maxRetries; attempt++) {
68
+ if (await this.sendBatch(batch)) {
69
+ return true;
70
+ }
71
+ await sleep(this.retryBackoffMs * 2 ** attempt);
72
+ }
73
+ return false;
74
+ }
75
+ async sendBatch(batch) {
76
+ try {
77
+ const controller = new AbortController();
78
+ const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
79
+ const response = await fetch(this.eventsUrl, {
80
+ method: "POST",
81
+ headers: {
82
+ ...this.headers,
83
+ "Content-Type": "application/json"
84
+ },
85
+ body: JSON.stringify(batch),
86
+ signal: controller.signal
87
+ });
88
+ clearTimeout(timeoutId);
89
+ if (response.status >= 200 && response.status < 300) {
90
+ return true;
91
+ }
92
+ warn(`Event send returned ${response.status}`);
93
+ return false;
94
+ } catch (error) {
95
+ if (error instanceof Error) {
96
+ if (error.name === "AbortError") {
97
+ warn("Event send timed out");
98
+ } else {
99
+ warn(`Event send failed: ${error.message}`);
100
+ }
101
+ } else {
102
+ warn("Event send failed");
103
+ }
104
+ return false;
105
+ }
106
+ }
107
+ };
108
+
109
+ // src/client.ts
110
+ var DEFAULT_ENDPOINT = "https://marlo.marshmallo.ai";
111
+ var DEFAULT_TIMEOUT_MS2 = 5e3;
112
+ function warn2(message) {
113
+ console.warn(`[marlo] ${message}`);
114
+ }
115
+ function info(message) {
116
+ console.info(`[marlo] ${message}`);
117
+ }
118
+ var _client = null;
119
+ var _enabled = false;
120
+ var MarloClient = class {
121
+ constructor(apiKey, endpoint, scope) {
122
+ this.apiKey = apiKey;
123
+ this.endpoint = endpoint.replace(/\/+$/, "");
124
+ this._scope = scope;
125
+ this.sender = new BufferedEventSender({
126
+ eventsUrl: `${this.endpoint}/events`,
127
+ apiKey
128
+ });
129
+ }
130
+ get scope() {
131
+ return this._scope;
132
+ }
133
+ sendEvents(events) {
134
+ this.sender.enqueue(events);
135
+ }
136
+ async flush() {
137
+ await this.sender.flush();
138
+ }
139
+ async shutdown() {
140
+ await this.sender.shutdown();
141
+ }
142
+ async fetchLearnings(learningKey) {
143
+ try {
144
+ const controller = new AbortController();
145
+ const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS2);
146
+ const response = await fetch(`${this.endpoint}/learnings`, {
147
+ method: "POST",
148
+ headers: {
149
+ Authorization: `Bearer ${this.apiKey}`,
150
+ "Content-Type": "application/json"
151
+ },
152
+ body: JSON.stringify({ learning_key: learningKey }),
153
+ signal: controller.signal
154
+ });
155
+ clearTimeout(timeoutId);
156
+ if (response.status < 200 || response.status >= 300) {
157
+ return null;
158
+ }
159
+ const data = await response.json();
160
+ return data.learning_state ?? null;
161
+ } catch (error) {
162
+ if (error instanceof Error) {
163
+ warn2(`Fetch learnings failed: ${error.message}`);
164
+ } else {
165
+ warn2("Fetch learnings failed");
166
+ }
167
+ return null;
168
+ }
169
+ }
170
+ };
171
+ async function init(apiKey, endpoint = DEFAULT_ENDPOINT) {
172
+ const normalizedEndpoint = endpoint.replace(/\/+$/, "");
173
+ const scopeUrl = `${normalizedEndpoint}/scope`;
174
+ try {
175
+ const controller = new AbortController();
176
+ const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS2);
177
+ const response = await fetch(scopeUrl, {
178
+ headers: { Authorization: `Bearer ${apiKey}` },
179
+ signal: controller.signal
180
+ });
181
+ clearTimeout(timeoutId);
182
+ if (response.status !== 200) {
183
+ warn2(`Marlo init failed: scope request returned ${response.status}`);
184
+ _enabled = false;
185
+ return;
186
+ }
187
+ const payload = await response.json();
188
+ const scopeData = payload.scope ?? {};
189
+ const projectId = scopeData.project_id;
190
+ const orgId = scopeData.org_id;
191
+ const userId = scopeData.user_id;
192
+ if (typeof projectId !== "string" || !projectId.trim() || typeof orgId !== "string" || !orgId.trim() || typeof userId !== "string" || !userId.trim()) {
193
+ warn2("Marlo init failed: invalid scope response");
194
+ _enabled = false;
195
+ return;
196
+ }
197
+ const scope = {
198
+ project_id: projectId.trim(),
199
+ org_id: orgId.trim(),
200
+ user_id: userId.trim()
201
+ };
202
+ _client = new MarloClient(apiKey, normalizedEndpoint, scope);
203
+ _enabled = true;
204
+ info(`Marlo SDK initialized for project ${projectId}`);
205
+ } catch (error) {
206
+ if (error instanceof Error) {
207
+ if (error.name === "AbortError") {
208
+ warn2("Marlo init failed: timeout");
209
+ } else if (error.message.includes("ECONNREFUSED") || error.message.includes("fetch failed")) {
210
+ warn2("Marlo init failed: connection error");
211
+ } else {
212
+ warn2(`Marlo init failed: ${error.message}`);
213
+ }
214
+ } else {
215
+ warn2("Marlo init failed");
216
+ }
217
+ _enabled = false;
218
+ }
219
+ }
220
+ function getClient() {
221
+ return _client;
222
+ }
223
+ function isEnabled() {
224
+ return _enabled;
225
+ }
226
+ async function shutdown() {
227
+ if (_client) {
228
+ await _client.shutdown();
229
+ _client = null;
230
+ }
231
+ _enabled = false;
232
+ }
233
+
234
+ // src/digest.ts
235
+ import { createHash } from "crypto";
236
+ function sortObject(value) {
237
+ if (value === null || value === void 0) {
238
+ return value;
239
+ }
240
+ if (Array.isArray(value)) {
241
+ return value.map(sortObject);
242
+ }
243
+ if (typeof value === "object") {
244
+ const sorted = {};
245
+ const keys = Object.keys(value).sort();
246
+ for (const key of keys) {
247
+ sorted[key] = sortObject(value[key]);
248
+ }
249
+ return sorted;
250
+ }
251
+ return value;
252
+ }
253
+ function jsonDigest(payload) {
254
+ const sorted = sortObject(payload);
255
+ const encoded = JSON.stringify(sorted);
256
+ return createHash("sha256").update(encoded, "utf-8").digest("hex");
257
+ }
258
+
259
+ // src/ids.ts
260
+ var ID_EPOCH_MS = 17e11;
261
+ var WORKER_ID_BITS = 10;
262
+ var SEQUENCE_BITS = 12;
263
+ var MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;
264
+ var MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1;
265
+ var WORKER_ID_SHIFT = SEQUENCE_BITS;
266
+ var TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
267
+ function parseWorkerId() {
268
+ const raw = (process.env.MARLO_WORKER_ID ?? "0").trim();
269
+ if (!raw) {
270
+ return 0;
271
+ }
272
+ const workerId = parseInt(raw, 10);
273
+ if (isNaN(workerId) || workerId < 0 || workerId > MAX_WORKER_ID) {
274
+ return 0;
275
+ }
276
+ return workerId;
277
+ }
278
+ var WORKER_ID = parseWorkerId();
279
+ var IdGenerator = class {
280
+ constructor() {
281
+ this.lastTs = 0;
282
+ this.sequence = 0;
283
+ }
284
+ nextId() {
285
+ let ts = Date.now();
286
+ if (ts < this.lastTs) {
287
+ ts = this.waitUntil(this.lastTs);
288
+ }
289
+ if (ts === this.lastTs) {
290
+ this.sequence = this.sequence + 1 & MAX_SEQUENCE;
291
+ if (this.sequence === 0) {
292
+ ts = this.waitUntil(this.lastTs + 1);
293
+ }
294
+ } else {
295
+ this.sequence = 0;
296
+ }
297
+ this.lastTs = ts;
298
+ return ts - ID_EPOCH_MS << TIMESTAMP_SHIFT | WORKER_ID << WORKER_ID_SHIFT | this.sequence;
299
+ }
300
+ waitUntil(targetMs) {
301
+ let ts = Date.now();
302
+ while (ts < targetMs) {
303
+ ts = Date.now();
304
+ }
305
+ return ts;
306
+ }
307
+ };
308
+ var idGenerator = new IdGenerator();
309
+ function generateId() {
310
+ return idGenerator.nextId();
311
+ }
312
+
313
+ // src/registry.ts
314
+ var AgentRegistry = class {
315
+ constructor() {
316
+ this.agents = /* @__PURE__ */ new Map();
317
+ }
318
+ register(definition) {
319
+ const existing = this.agents.get(definition.name);
320
+ if (!existing) {
321
+ this.agents.set(definition.name, definition);
322
+ } else if (existing.definition_hash !== definition.definition_hash) {
323
+ definition.sent = false;
324
+ this.agents.set(definition.name, definition);
325
+ } else {
326
+ definition.sent = existing.sent;
327
+ this.agents.set(definition.name, definition);
328
+ }
329
+ }
330
+ get(name) {
331
+ return this.agents.get(name) ?? null;
332
+ }
333
+ markSent(name) {
334
+ const agent = this.agents.get(name);
335
+ if (agent) {
336
+ agent.sent = true;
337
+ }
338
+ }
339
+ needsResend(name) {
340
+ const agent = this.agents.get(name);
341
+ return agent !== null && agent !== void 0 && !agent.sent;
342
+ }
343
+ };
344
+ var registry = null;
345
+ function getRegistry() {
346
+ if (!registry) {
347
+ registry = new AgentRegistry();
348
+ }
349
+ return registry;
350
+ }
351
+ function registerAgent(name, systemPrompt, tools, mcp, modelConfig) {
352
+ const definitionHash = jsonDigest({
353
+ name,
354
+ system_prompt: systemPrompt,
355
+ tool_definitions: tools,
356
+ mcp_definitions: mcp ?? null,
357
+ model_config: modelConfig ?? null
358
+ });
359
+ const definition = {
360
+ name,
361
+ system_prompt: systemPrompt,
362
+ tools,
363
+ mcp: mcp ?? null,
364
+ model_config: modelConfig ?? null,
365
+ definition_hash: definitionHash,
366
+ sent: false
367
+ };
368
+ getRegistry().register(definition);
369
+ return definitionHash;
370
+ }
371
+ function getAgent(name) {
372
+ return getRegistry().get(name);
373
+ }
374
+ function markAgentSent(name) {
375
+ getRegistry().markSent(name);
376
+ }
377
+ function needsResend(name) {
378
+ return getRegistry().needsResend(name);
379
+ }
380
+
381
+ // src/context.ts
382
+ function warn3(message) {
383
+ console.warn(`[marlo] ${message}`);
384
+ }
385
+ function generateInvocationId() {
386
+ return crypto.randomUUID();
387
+ }
388
+ function computeSessionId(projectId, threadId) {
389
+ const digest = jsonDigest(`${projectId}:${threadId}`);
390
+ return parseInt(digest.slice(0, 16), 16);
391
+ }
392
+ function task(threadId, agent, threadName) {
393
+ return new TaskContext(threadId, agent, threadName);
394
+ }
395
+ var TaskContext = class _TaskContext {
396
+ constructor(threadId, agent, threadName, parent) {
397
+ this.taskId = null;
398
+ this.sessionId = null;
399
+ this.invocationId = null;
400
+ this.inputText = null;
401
+ this.outputText = null;
402
+ this.errorMessage = null;
403
+ this.events = [];
404
+ this.threadId = threadId;
405
+ this.agentName = agent;
406
+ this.threadName = threadName;
407
+ this.parent = parent;
408
+ }
409
+ start() {
410
+ try {
411
+ const client = getClient();
412
+ const projectId = client?.scope.project_id ?? "";
413
+ this.sessionId = computeSessionId(projectId, this.threadId);
414
+ this.taskId = generateId();
415
+ this.invocationId = generateInvocationId();
416
+ if (needsResend(this.agentName)) {
417
+ const agentDef = getAgent(this.agentName);
418
+ if (agentDef) {
419
+ this.emit("agent_definition", {
420
+ name: agentDef.name,
421
+ system_prompt: agentDef.system_prompt,
422
+ tool_definitions: agentDef.tools,
423
+ mcp_definitions: agentDef.mcp,
424
+ model_config: agentDef.model_config,
425
+ definition_hash: agentDef.definition_hash
426
+ });
427
+ markAgentSent(this.agentName);
428
+ }
429
+ }
430
+ } catch (error) {
431
+ if (error instanceof Error) {
432
+ warn3(`TaskContext start failed: ${error.message}`);
433
+ } else {
434
+ warn3("TaskContext start failed");
435
+ }
436
+ }
437
+ return this;
438
+ }
439
+ end(hasError) {
440
+ try {
441
+ const status = hasError || this.errorMessage !== null ? "error" : "success";
442
+ const payload = { status };
443
+ if (this.outputText !== null) {
444
+ payload.final_answer = this.outputText;
445
+ }
446
+ if (this.errorMessage !== null) {
447
+ payload.error = this.errorMessage;
448
+ }
449
+ this.emit("task_end", payload);
450
+ this.flush();
451
+ } catch (error) {
452
+ if (error instanceof Error) {
453
+ warn3(`TaskContext end failed: ${error.message}`);
454
+ } else {
455
+ warn3("TaskContext end failed");
456
+ }
457
+ }
458
+ }
459
+ input(text) {
460
+ try {
461
+ this.inputText = text;
462
+ const metadata = { thread_id: this.threadId };
463
+ if (this.threadName !== void 0) {
464
+ metadata.thread_name = this.threadName;
465
+ }
466
+ this.emit("task_start", { task: text, metadata });
467
+ } catch (error) {
468
+ if (error instanceof Error) {
469
+ warn3(`TaskContext input failed: ${error.message}`);
470
+ } else {
471
+ warn3("TaskContext input failed");
472
+ }
473
+ }
474
+ }
475
+ output(text) {
476
+ try {
477
+ this.outputText = text;
478
+ } catch (error) {
479
+ if (error instanceof Error) {
480
+ warn3(`TaskContext output failed: ${error.message}`);
481
+ } else {
482
+ warn3("TaskContext output failed");
483
+ }
484
+ }
485
+ }
486
+ tool(name, input, output, error) {
487
+ try {
488
+ const payload = {
489
+ tool_name: name,
490
+ input,
491
+ output
492
+ };
493
+ if (error !== void 0) {
494
+ payload.error = error;
495
+ }
496
+ this.emit("tool_call", payload);
497
+ } catch (err) {
498
+ if (err instanceof Error) {
499
+ warn3(`TaskContext tool failed: ${err.message}`);
500
+ } else {
501
+ warn3("TaskContext tool failed");
502
+ }
503
+ }
504
+ }
505
+ reasoning(text) {
506
+ try {
507
+ this.emit("log", { reasoning: text });
508
+ } catch (error) {
509
+ if (error instanceof Error) {
510
+ warn3(`TaskContext reasoning failed: ${error.message}`);
511
+ } else {
512
+ warn3("TaskContext reasoning failed");
513
+ }
514
+ }
515
+ }
516
+ llm(params) {
517
+ try {
518
+ if (params.messages === void 0) {
519
+ warn3("llm() called without messages");
520
+ }
521
+ if (params.response === void 0) {
522
+ warn3("llm() called without response");
523
+ }
524
+ const payload = {
525
+ model: params.model,
526
+ usage: params.usage
527
+ };
528
+ if (params.messages !== void 0) {
529
+ payload.messages = params.messages;
530
+ }
531
+ if (params.response !== void 0) {
532
+ payload.response = params.response;
533
+ }
534
+ this.emit("llm_call", payload);
535
+ } catch (error) {
536
+ if (error instanceof Error) {
537
+ warn3(`TaskContext llm failed: ${error.message}`);
538
+ } else {
539
+ warn3("TaskContext llm failed");
540
+ }
541
+ }
542
+ }
543
+ error(message) {
544
+ try {
545
+ this.errorMessage = message;
546
+ } catch (error) {
547
+ if (error instanceof Error) {
548
+ warn3(`TaskContext error failed: ${error.message}`);
549
+ } else {
550
+ warn3("TaskContext error failed");
551
+ }
552
+ }
553
+ }
554
+ child(agent) {
555
+ return new _TaskContext(this.threadId, agent, this.threadName, this);
556
+ }
557
+ async getLearnings() {
558
+ try {
559
+ const client = getClient();
560
+ if (!client) {
561
+ return null;
562
+ }
563
+ return await client.fetchLearnings(this.agentName);
564
+ } catch (error) {
565
+ if (error instanceof Error) {
566
+ warn3(`TaskContext getLearnings failed: ${error.message}`);
567
+ } else {
568
+ warn3("TaskContext getLearnings failed");
569
+ }
570
+ return null;
571
+ }
572
+ }
573
+ emit(eventType, payload) {
574
+ const agentDef = getAgent(this.agentName);
575
+ const agentId = agentDef?.name ?? this.agentName;
576
+ const parentAgentId = this.parent?.agentName ?? null;
577
+ const event = {
578
+ run_id: this.sessionId,
579
+ agent_id: agentId,
580
+ parent_agent_id: parentAgentId,
581
+ invocation_id: this.invocationId,
582
+ task_id: this.taskId,
583
+ event_type: eventType,
584
+ payload
585
+ };
586
+ this.events.push(event);
587
+ }
588
+ flush() {
589
+ const client = getClient();
590
+ if (!client || !isEnabled()) {
591
+ this.events = [];
592
+ return;
593
+ }
594
+ try {
595
+ client.sendEvents(this.events);
596
+ client.flush();
597
+ } catch (error) {
598
+ if (error instanceof Error) {
599
+ warn3(`TaskContext flush failed: ${error.message}`);
600
+ } else {
601
+ warn3("TaskContext flush failed");
602
+ }
603
+ } finally {
604
+ this.events = [];
605
+ }
606
+ }
607
+ };
608
+ export {
609
+ MarloClient,
610
+ TaskContext,
611
+ registerAgent as agent,
612
+ generateId,
613
+ getAgent,
614
+ getClient,
615
+ init,
616
+ isEnabled,
617
+ jsonDigest,
618
+ registerAgent,
619
+ shutdown,
620
+ task
621
+ };
622
+ //# sourceMappingURL=index.mjs.map