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