@ai-setting/roy-agent-core 1.4.11 → 1.4.12

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 (39) hide show
  1. package/dist/config/index.js +23 -0
  2. package/dist/env/agent/index.js +3035 -0
  3. package/dist/env/commands/index.js +1685 -0
  4. package/dist/env/debug/formatters/index.js +639 -0
  5. package/dist/env/debug/index.js +2300 -0
  6. package/dist/env/hook/index.js +273 -0
  7. package/dist/env/index.js +12591 -0
  8. package/dist/env/llm/index.js +2736 -0
  9. package/dist/env/log-trace/index.js +1779 -0
  10. package/dist/env/mcp/index.js +2173 -0
  11. package/dist/env/mcp/tool/index.js +1149 -0
  12. package/dist/env/memory/built-in/index.js +225 -0
  13. package/dist/env/memory/index.js +2171 -0
  14. package/dist/env/memory/plugin/index.js +1263 -0
  15. package/dist/env/prompt/index.js +2107 -0
  16. package/dist/env/session/index.js +3594 -0
  17. package/dist/env/session/storage/index.js +2049 -0
  18. package/dist/env/skill/index.js +1635 -0
  19. package/dist/env/skill/tool/index.js +114 -0
  20. package/dist/env/task/delegate/index.js +1844 -0
  21. package/dist/env/task/hooks/index.js +67 -0
  22. package/dist/env/task/index.js +3578 -0
  23. package/dist/env/task/plugins/index.js +1626 -0
  24. package/dist/env/task/storage/index.js +1464 -0
  25. package/dist/env/task/tools/index.js +344 -0
  26. package/dist/env/task/tools/operation/index.js +270 -0
  27. package/dist/env/tool/built-in/index.js +1151 -0
  28. package/dist/env/tool/index.js +2284 -0
  29. package/dist/env/workflow/decorators/index.js +449 -0
  30. package/dist/env/workflow/engine/index.js +4391 -0
  31. package/dist/env/workflow/index.js +6214 -0
  32. package/dist/env/workflow/nodes/index.js +650 -0
  33. package/dist/env/workflow/service/index.js +262 -0
  34. package/dist/env/workflow/storage/index.js +1236 -0
  35. package/dist/env/workflow/tools/index.js +1081 -0
  36. package/dist/env/workflow/types/index.js +479 -0
  37. package/dist/env/workflow/utils/index.js +1631 -0
  38. package/dist/index.js +15006 -14265
  39. package/package.json +2 -2
@@ -0,0 +1,1844 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ function __accessProp(key) {
7
+ return this[key];
8
+ }
9
+ var __toCommonJS = (from) => {
10
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
11
+ if (entry)
12
+ return entry;
13
+ entry = __defProp({}, "__esModule", { value: true });
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (var key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(entry, key))
17
+ __defProp(entry, key, {
18
+ get: __accessProp.bind(from, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ __moduleCache.set(from, entry);
23
+ return entry;
24
+ };
25
+ var __moduleCache;
26
+ var __returnValue = (v) => v;
27
+ function __exportSetter(name, newValue) {
28
+ this[name] = __returnValue.bind(null, newValue);
29
+ }
30
+ var __export = (target, all) => {
31
+ for (var name in all)
32
+ __defProp(target, name, {
33
+ get: all[name],
34
+ enumerable: true,
35
+ configurable: true,
36
+ set: __exportSetter.bind(all, name)
37
+ });
38
+ };
39
+ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
40
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
41
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
42
+ r = Reflect.decorate(decorators, target, key, desc);
43
+ else
44
+ for (var i = decorators.length - 1;i >= 0; i--)
45
+ if (d = decorators[i])
46
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
47
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
48
+ };
49
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
50
+ var __require = import.meta.require;
51
+
52
+ // packages/core/src/env/log-trace/span-storage.ts
53
+ var exports_span_storage = {};
54
+ __export(exports_span_storage, {
55
+ SQLiteSpanStorage: () => SQLiteSpanStorage
56
+ });
57
+
58
+ class SQLiteSpanStorage {
59
+ db = null;
60
+ dbPath;
61
+ initialized = false;
62
+ constructor(dbPath) {
63
+ if (!dbPath) {
64
+ throw new Error("SQLiteSpanStorage requires a valid dbPath parameter");
65
+ }
66
+ if (dbPath === ":memory:") {
67
+ throw new Error("SQLiteSpanStorage does not support :memory: mode. Use a file path instead.");
68
+ }
69
+ this.dbPath = dbPath;
70
+ }
71
+ async initialize() {
72
+ if (this.initialized)
73
+ return;
74
+ const { Database } = __require("bun:sqlite");
75
+ const fs = __require("fs");
76
+ const path = __require("path");
77
+ const dir = path.dirname(this.dbPath);
78
+ if (!fs.existsSync(dir)) {
79
+ fs.mkdirSync(dir, { recursive: true });
80
+ }
81
+ this.db = new Database(this.dbPath);
82
+ this.db.run("PRAGMA journal_mode=WAL");
83
+ this.db.run("PRAGMA busy_timeout=5000");
84
+ this.db.run("PRAGMA synchronous=NORMAL");
85
+ this.db.run(`
86
+ CREATE TABLE IF NOT EXISTS span (
87
+ span_id TEXT PRIMARY KEY,
88
+ trace_id TEXT NOT NULL,
89
+ parent_span_id TEXT,
90
+ name TEXT NOT NULL,
91
+ kind TEXT NOT NULL,
92
+ status TEXT NOT NULL,
93
+ start_time INTEGER NOT NULL,
94
+ end_time INTEGER,
95
+ attributes TEXT,
96
+ result TEXT,
97
+ error TEXT,
98
+ time_created INTEGER NOT NULL
99
+ )
100
+ `);
101
+ this.db.run("CREATE INDEX IF NOT EXISTS idx_span_trace ON span(trace_id)");
102
+ this.db.run("CREATE INDEX IF NOT EXISTS idx_span_parent ON span(parent_span_id)");
103
+ this.initialized = true;
104
+ }
105
+ save(span) {
106
+ if (!this.db)
107
+ return;
108
+ const stmt = this.db.prepare(`
109
+ INSERT OR REPLACE INTO span
110
+ (span_id, trace_id, parent_span_id, name, kind, status, start_time, end_time, attributes, result, error, time_created)
111
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
112
+ `);
113
+ const resultValue = span.result !== undefined && span.result !== null ? typeof span.result === "string" ? span.result : JSON.stringify(span.result) : null;
114
+ stmt.run(span.spanId, span.traceId, span.parentSpanId || null, span.name, span.kind, span.status, span.startTime, span.endTime || null, JSON.stringify(span.attributes), resultValue, span.error || null, Date.now());
115
+ }
116
+ saveBatch(spans) {
117
+ for (const span of spans) {
118
+ this.save(span);
119
+ }
120
+ }
121
+ findByTraceId(traceId) {
122
+ if (!this.db)
123
+ return [];
124
+ const rows = this.db.prepare("SELECT * FROM span WHERE trace_id = ?").all(traceId);
125
+ return this.buildTree(rows.map(this.rowToSpan));
126
+ }
127
+ findBySpanId(spanId) {
128
+ if (!this.db)
129
+ return;
130
+ const row = this.db.prepare("SELECT * FROM span WHERE span_id = ?").get(spanId);
131
+ return row ? this.rowToSpan(row) : undefined;
132
+ }
133
+ listTraces(limit = 10) {
134
+ if (!this.db)
135
+ return [];
136
+ const rows = this.db.prepare(`
137
+ SELECT trace_id,
138
+ MIN(start_time) as start_time,
139
+ MAX(end_time) as end_time,
140
+ COUNT(*) as span_count
141
+ FROM span
142
+ GROUP BY trace_id
143
+ ORDER BY start_time DESC
144
+ LIMIT ?
145
+ `).all(limit);
146
+ return rows.map((row) => ({
147
+ traceId: row.trace_id,
148
+ rootSpanName: "unknown",
149
+ startTime: row.start_time,
150
+ endTime: row.end_time,
151
+ duration: row.end_time - row.start_time,
152
+ spanCount: row.span_count,
153
+ status: "ok"
154
+ }));
155
+ }
156
+ deleteByTraceId(traceId) {
157
+ if (this.db) {
158
+ this.db.prepare("DELETE FROM span WHERE trace_id = ?").run(traceId);
159
+ }
160
+ }
161
+ close() {
162
+ if (this.db) {
163
+ this.db.close();
164
+ this.db = null;
165
+ }
166
+ }
167
+ rowToSpan(row) {
168
+ return {
169
+ traceId: row.trace_id,
170
+ spanId: row.span_id,
171
+ parentSpanId: row.parent_span_id,
172
+ name: row.name,
173
+ kind: row.kind,
174
+ status: row.status,
175
+ startTime: row.start_time,
176
+ endTime: row.end_time,
177
+ attributes: row.attributes ? JSON.parse(row.attributes) : {},
178
+ result: row.result || undefined,
179
+ error: row.error || undefined
180
+ };
181
+ }
182
+ buildTree(spans) {
183
+ const spanMap = new Map;
184
+ const roots = [];
185
+ for (const span of spans) {
186
+ spanMap.set(span.spanId, { ...span, children: [] });
187
+ }
188
+ for (const span of spanMap.values()) {
189
+ if (span.parentSpanId) {
190
+ const parent = spanMap.get(span.parentSpanId);
191
+ if (parent) {
192
+ parent.children.push(span);
193
+ } else {
194
+ roots.push(span);
195
+ }
196
+ } else {
197
+ roots.push(span);
198
+ }
199
+ }
200
+ return roots;
201
+ }
202
+ }
203
+
204
+ // packages/core/src/env/log-trace/opentelemetry/propagation.ts
205
+ function padLeft(str, length) {
206
+ return str.padStart(length, "0");
207
+ }
208
+ function isValidHex(str) {
209
+ return /^[0-9a-f]+$/i.test(str);
210
+ }
211
+ function serialize(context) {
212
+ const traceId = padLeft(context.traceId.toLowerCase(), TRACE_ID_LENGTH);
213
+ const spanId = padLeft(context.spanId.toLowerCase(), PARENT_SPAN_ID_LENGTH);
214
+ const parts = [
215
+ TRACE_CONTEXT_VERSION,
216
+ traceId,
217
+ spanId,
218
+ TRACE_FLAGS_SAMPLED
219
+ ];
220
+ return parts.join("-");
221
+ }
222
+ function parse(traceparent) {
223
+ if (!traceparent || typeof traceparent !== "string") {
224
+ return;
225
+ }
226
+ const trimmed = traceparent.trim();
227
+ const parts = trimmed.split("-");
228
+ if (parts.length !== 4) {
229
+ return;
230
+ }
231
+ const [version, traceId, senderSpanId, flags] = parts;
232
+ if (version !== TRACE_CONTEXT_VERSION) {
233
+ if (version > TRACE_CONTEXT_VERSION) {
234
+ return;
235
+ }
236
+ }
237
+ if (traceId.length !== TRACE_ID_LENGTH || !isValidHex(traceId)) {
238
+ return;
239
+ }
240
+ if (senderSpanId.length !== PARENT_SPAN_ID_LENGTH || !isValidHex(senderSpanId)) {
241
+ return;
242
+ }
243
+ if (flags.length !== FLAGS_LENGTH || !isValidHex(flags)) {
244
+ return;
245
+ }
246
+ return {
247
+ traceId: traceId.toLowerCase(),
248
+ spanId: senderSpanId.toLowerCase()
249
+ };
250
+ }
251
+ var TRACE_CONTEXT_VERSION = "00", TRACE_FLAGS_SAMPLED = "01", TRACEPARENT_HEADER = "TRACEPARENT", TRACE_ID_LENGTH = 32, PARENT_SPAN_ID_LENGTH = 16, FLAGS_LENGTH = 2, propagation;
252
+ var init_propagation = __esm(() => {
253
+ propagation = {
254
+ inject(carrier, context) {
255
+ carrier[TRACEPARENT_HEADER] = serialize(context);
256
+ },
257
+ extract(carrier) {
258
+ const traceparent = carrier[TRACEPARENT_HEADER];
259
+ if (!traceparent) {
260
+ return;
261
+ }
262
+ return parse(traceparent);
263
+ },
264
+ getTraceparentHeader() {
265
+ return TRACEPARENT_HEADER;
266
+ }
267
+ };
268
+ });
269
+
270
+ // packages/core/src/env/log-trace/types.ts
271
+ var SpanKind, SpanStatus;
272
+ var init_types = __esm(() => {
273
+ ((SpanKind2) => {
274
+ SpanKind2["CLIENT"] = "client";
275
+ SpanKind2["SERVER"] = "server";
276
+ SpanKind2["INTERNAL"] = "internal";
277
+ })(SpanKind ||= {});
278
+ ((SpanStatus2) => {
279
+ SpanStatus2["OK"] = "ok";
280
+ SpanStatus2["ERROR"] = "error";
281
+ })(SpanStatus ||= {});
282
+ });
283
+
284
+ // packages/core/src/env/log-trace/opentelemetry/tracer-provider.ts
285
+ var exports_tracer_provider = {};
286
+ __export(exports_tracer_provider, {
287
+ resetTracerProvider: () => resetTracerProvider,
288
+ getTracerProvider: () => getTracerProvider,
289
+ OTelTracerProvider: () => OTelTracerProvider
290
+ });
291
+
292
+ class OTelSpanImpl {
293
+ name;
294
+ kind;
295
+ spanContext;
296
+ attributes = {};
297
+ startTime;
298
+ endTime;
299
+ error;
300
+ storage;
301
+ parentSpanContext;
302
+ onEnd;
303
+ constructor(name, spanContext, storage, parentSpanContext, onEnd) {
304
+ this.name = name;
305
+ this.kind = "internal";
306
+ this.spanContext = spanContext;
307
+ this.parentSpanContext = parentSpanContext;
308
+ this.startTime = Date.now();
309
+ this.storage = storage;
310
+ this.onEnd = onEnd;
311
+ }
312
+ setAttribute(key, value) {
313
+ this.attributes[key] = value;
314
+ }
315
+ addEvent(name, attributes) {
316
+ const events = this.attributes._events || [];
317
+ events.push({ name, attributes });
318
+ this.attributes._events = events;
319
+ }
320
+ end(result, error) {
321
+ this.endTime = Date.now();
322
+ if (error) {
323
+ this.error = error.message;
324
+ }
325
+ this.storage.save({
326
+ traceId: this.spanContext.traceId,
327
+ spanId: this.spanContext.spanId,
328
+ parentSpanId: this.spanContext.parentSpanId,
329
+ name: this.name,
330
+ kind: this.kind,
331
+ status: error ? "error" /* ERROR */ : "ok" /* OK */,
332
+ startTime: this.startTime,
333
+ endTime: this.endTime,
334
+ attributes: this.attributes,
335
+ result,
336
+ error: this.error
337
+ });
338
+ this.onEnd?.();
339
+ }
340
+ }
341
+
342
+ class OTelTracerImpl {
343
+ name;
344
+ version;
345
+ storage;
346
+ currentContext;
347
+ activeSpans = new Map;
348
+ onSpanEndCallback;
349
+ provider;
350
+ constructor(name, version, storage, provider) {
351
+ this.name = name;
352
+ this.version = version;
353
+ this.storage = storage;
354
+ this.provider = provider;
355
+ }
356
+ setOnSpanEndCallback(callback) {
357
+ this.onSpanEndCallback = callback;
358
+ }
359
+ getActiveSpanCount() {
360
+ return this.activeSpans.size;
361
+ }
362
+ startSpan(name, options) {
363
+ const parentFromOptions = options?.parent;
364
+ const hasExplicitParent = options && "parent" in options;
365
+ const globalContext = this.provider.getGlobalContext();
366
+ let effectiveParentContext;
367
+ if (hasExplicitParent) {
368
+ effectiveParentContext = parentFromOptions;
369
+ } else if (this.currentContext) {
370
+ effectiveParentContext = this.currentContext;
371
+ } else if (globalContext) {
372
+ effectiveParentContext = globalContext;
373
+ }
374
+ const traceId = effectiveParentContext?.traceId || this.generateTraceId();
375
+ const spanId = this.generateSpanId();
376
+ let parentSpanId;
377
+ if (hasExplicitParent && parentFromOptions) {
378
+ parentSpanId = parentFromOptions.parentSpanId || parentFromOptions.spanId;
379
+ } else if (this.currentContext) {
380
+ parentSpanId = this.currentContext.spanId;
381
+ } else if (globalContext) {
382
+ parentSpanId = globalContext.spanId;
383
+ }
384
+ const spanContext = {
385
+ traceId,
386
+ spanId,
387
+ parentSpanId
388
+ };
389
+ this.currentContext = {
390
+ traceId,
391
+ spanId,
392
+ parentSpanId
393
+ };
394
+ const span = new OTelSpanImpl(name, spanContext, this.storage, effectiveParentContext, () => this.handleSpanEnd(spanContext.spanId, effectiveParentContext?.spanId));
395
+ if (options?.attributes) {
396
+ for (const [key, value] of Object.entries(options.attributes)) {
397
+ span.setAttribute(key, value);
398
+ }
399
+ }
400
+ this.activeSpans.set(spanId, span);
401
+ return span;
402
+ }
403
+ injectToEnv(env) {
404
+ if (this.currentContext) {
405
+ propagation.inject(env, this.currentContext);
406
+ }
407
+ }
408
+ getCurrentContext() {
409
+ return this.currentContext;
410
+ }
411
+ setCurrentContext(context) {
412
+ this.currentContext = context;
413
+ }
414
+ endSpan(span) {
415
+ const spanContext = span.spanContext;
416
+ this.activeSpans.delete(spanContext.spanId);
417
+ const currentTraceId = this.currentContext?.traceId;
418
+ if (spanContext.parentSpanId) {
419
+ const parentSpan = this.activeSpans.get(spanContext.parentSpanId);
420
+ if (parentSpan) {
421
+ const parentContext = {
422
+ traceId: spanContext.traceId,
423
+ spanId: parentSpan.spanContext.spanId,
424
+ parentSpanId: parentSpan.spanContext.parentSpanId
425
+ };
426
+ this.currentContext = parentContext;
427
+ return parentContext;
428
+ }
429
+ if (currentTraceId) {
430
+ const parentContext = {
431
+ traceId: currentTraceId,
432
+ spanId: spanContext.parentSpanId,
433
+ parentSpanId: undefined
434
+ };
435
+ this.currentContext = parentContext;
436
+ return parentContext;
437
+ }
438
+ }
439
+ this.currentContext = undefined;
440
+ return;
441
+ }
442
+ generateTraceId() {
443
+ const timestamp = Date.now().toString(16).padStart(12, "0");
444
+ const random = Array.from({ length: 5 }, () => Math.floor(Math.random() * 4294967295).toString(16).padStart(8, "0")).join("");
445
+ return (timestamp + random).slice(0, 32).padStart(32, "0");
446
+ }
447
+ generateSpanId() {
448
+ return Math.floor(Math.random() * 18446744073709552000).toString(16).padStart(16, "0");
449
+ }
450
+ handleSpanEnd(spanId, parentSpanId) {
451
+ this.activeSpans.delete(spanId);
452
+ const currentTraceId = this.currentContext?.traceId;
453
+ if (parentSpanId) {
454
+ const parentSpan = this.activeSpans.get(parentSpanId);
455
+ if (parentSpan) {
456
+ this.currentContext = {
457
+ traceId: parentSpan.spanContext.traceId,
458
+ spanId: parentSpan.spanContext.spanId,
459
+ parentSpanId: parentSpan.spanContext.parentSpanId
460
+ };
461
+ return;
462
+ }
463
+ if (currentTraceId) {
464
+ this.currentContext = {
465
+ traceId: currentTraceId,
466
+ spanId: parentSpanId,
467
+ parentSpanId: undefined
468
+ };
469
+ return;
470
+ }
471
+ }
472
+ this.currentContext = undefined;
473
+ }
474
+ }
475
+
476
+ class OTelTracerProvider {
477
+ tracers = new Map;
478
+ storage;
479
+ initialized = false;
480
+ globalContext;
481
+ constructor(storage, dbPath) {
482
+ this.storage = storage || new SQLiteSpanStorage(dbPath || getDefaultDbPath());
483
+ }
484
+ async initialize() {
485
+ if (this.initialized)
486
+ return;
487
+ await this.storage.initialize();
488
+ this.initialized = true;
489
+ }
490
+ isInitialized() {
491
+ return this.initialized;
492
+ }
493
+ getGlobalContext() {
494
+ return this.globalContext;
495
+ }
496
+ setGlobalContext(context) {
497
+ this.globalContext = context;
498
+ }
499
+ getTracer(name, version) {
500
+ const key = `${name}@${version || "0.0.0"}`;
501
+ let tracer = this.tracers.get(key);
502
+ if (!tracer) {
503
+ tracer = new OTelTracerImpl(name, version, this.storage, this);
504
+ this.tracers.set(key, tracer);
505
+ if (this.initialized) {
506
+ this.restoreFromEnv(tracer);
507
+ }
508
+ }
509
+ return tracer;
510
+ }
511
+ restoreFromEnv(tracer) {
512
+ const extracted = propagation.extract(process.env);
513
+ if (extracted) {
514
+ tracer.setCurrentContext({
515
+ traceId: extracted.traceId,
516
+ spanId: extracted.spanId,
517
+ parentSpanId: undefined
518
+ });
519
+ }
520
+ }
521
+ shutdown() {
522
+ for (const tracer of this.tracers.values()) {}
523
+ this.tracers.clear();
524
+ this.storage.close();
525
+ this.initialized = false;
526
+ this.globalContext = undefined;
527
+ delete process.env["TRACEPARENT"];
528
+ delete process.env["TRACE_ID"];
529
+ delete process.env["LOG_TRACE_REQUEST_ID"];
530
+ }
531
+ getStorage() {
532
+ return this.storage;
533
+ }
534
+ }
535
+ function getTracerProvider() {
536
+ if (!providerInstance) {
537
+ providerInstance = new OTelTracerProvider;
538
+ }
539
+ return providerInstance;
540
+ }
541
+ function resetTracerProvider() {
542
+ if (providerInstance) {
543
+ providerInstance.shutdown();
544
+ providerInstance = null;
545
+ }
546
+ }
547
+ function getDefaultDbPath() {
548
+ const os = __require("os");
549
+ const path = __require("path");
550
+ const home = os.homedir();
551
+ const dataHome = process.env.XDG_DATA_HOME || path.join(home, ".local", "share");
552
+ return path.join(dataHome, "roy-agent", "traces.db");
553
+ }
554
+ var providerInstance = null;
555
+ var init_tracer_provider = __esm(() => {
556
+ init_propagation();
557
+ init_types();
558
+ });
559
+
560
+ // packages/core/src/env/log-trace/logger.ts
561
+ import { appendFileSync, existsSync, mkdirSync } from "fs";
562
+ import { join } from "path";
563
+ function simplifyFilePath(fullPath) {
564
+ let path = fullPath.replace(/\\/g, "/");
565
+ const bunfsMatch = path.match(/\/\$bunfs\/root\/(.+)$/);
566
+ if (bunfsMatch) {
567
+ const virtualPath = bunfsMatch[1];
568
+ const packagesMatch = virtualPath.match(/(packages\/[^/]+\/src\/[^/]+\/.+)$/);
569
+ if (packagesMatch) {
570
+ return packagesMatch[1];
571
+ }
572
+ return virtualPath;
573
+ }
574
+ const fileProtocolMatch = path.match(/@roy-agent\+core@file\+([^/]+)\/node_modules\/@roy-agent\/core\/(.+)$/);
575
+ if (fileProtocolMatch) {
576
+ const rootPkg = fileProtocolMatch[1].replace(/\+/g, "/");
577
+ const remaining = fileProtocolMatch[2];
578
+ const prefix = rootPkg;
579
+ const suffix = remaining.startsWith("src/") ? remaining : `src/${remaining}`;
580
+ return `${prefix}/${suffix}`;
581
+ }
582
+ const packagesRootMatch = path.match(/(packages\/[^/]+\/src\/[^/]+\/.+)$/);
583
+ if (packagesRootMatch) {
584
+ return packagesRootMatch[1];
585
+ }
586
+ const rootMarkers = ["packages/core/src", "packages/core", "packages"];
587
+ for (const marker of rootMarkers) {
588
+ const idx = path.indexOf(marker);
589
+ if (idx !== -1) {
590
+ return path.substring(idx);
591
+ }
592
+ }
593
+ return path;
594
+ }
595
+ function getDefaultLogDir() {
596
+ const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
597
+ try {
598
+ const xdg = __require("xdg-basedir");
599
+ if (xdg.xdgData) {
600
+ return join(xdg.xdgData, "roy-agent", "logs");
601
+ }
602
+ } catch {}
603
+ return join(home, ".local", "share", "roy-agent", "logs");
604
+ }
605
+ function isQuietMode() {
606
+ return quietMode;
607
+ }
608
+ function setQuietMode(enabled) {
609
+ quietMode = enabled;
610
+ }
611
+ function setConfigComponent(component) {
612
+ configComponentInstance = component;
613
+ }
614
+ function getLogLevel() {
615
+ if (configComponentInstance) {
616
+ const level = configComponentInstance.get("log_trace.logging.level");
617
+ if (level && ["debug", "info", "warn", "error"].includes(level)) {
618
+ return level;
619
+ }
620
+ }
621
+ const envLevel = process.env.LOG_LEVEL;
622
+ if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) {
623
+ return envLevel;
624
+ }
625
+ return "info";
626
+ }
627
+ function getCategoryLogLevel(category) {
628
+ if (configComponentInstance) {
629
+ const levels = configComponentInstance.get("log_trace.logging.levels");
630
+ if (levels && typeof levels === "object") {
631
+ const categoryLevel = levels[category];
632
+ if (categoryLevel && ["debug", "info", "warn", "error"].includes(categoryLevel)) {
633
+ return categoryLevel;
634
+ }
635
+ }
636
+ const directLevel = configComponentInstance.get(`log_trace.logging.levels.${category}`);
637
+ if (directLevel && ["debug", "info", "warn", "error"].includes(directLevel)) {
638
+ return directLevel;
639
+ }
640
+ }
641
+ const envKey = `LOG_LEVEL_${category.toUpperCase().replace(/:/g, "_")}`;
642
+ const envLevel = process.env[envKey];
643
+ if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) {
644
+ return envLevel;
645
+ }
646
+ return getLogLevel();
647
+ }
648
+ function isAbsolutePath(path) {
649
+ if (path.startsWith("/")) {
650
+ return true;
651
+ }
652
+ if (/^[a-zA-Z]:[/\\]/.test(path)) {
653
+ return true;
654
+ }
655
+ return false;
656
+ }
657
+ function expandHomeDir(path) {
658
+ if (path.startsWith("~")) {
659
+ const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
660
+ return join(home, path.slice(1));
661
+ }
662
+ return path;
663
+ }
664
+ function getLogFile() {
665
+ if (configComponentInstance) {
666
+ const file = configComponentInstance.get("log_trace.logging.file");
667
+ if (file) {
668
+ return file;
669
+ }
670
+ }
671
+ return "app.log";
672
+ }
673
+ function getLogDir() {
674
+ if (configComponentInstance) {
675
+ const dir = configComponentInstance.get("log_trace.logging.dir");
676
+ if (dir) {
677
+ return dir;
678
+ }
679
+ }
680
+ return getDefaultLogDir();
681
+ }
682
+ function getMaxOutput() {
683
+ if (configComponentInstance) {
684
+ const maxOutput = configComponentInstance.get("log-trace.logging.maxOutput");
685
+ if (typeof maxOutput === "number") {
686
+ return maxOutput;
687
+ }
688
+ }
689
+ return;
690
+ }
691
+ function setLogDirOverride(dir) {
692
+ logDirOverride = dir;
693
+ }
694
+ function getLogDirOverride() {
695
+ return logDirOverride;
696
+ }
697
+
698
+ class Logger {
699
+ prefix;
700
+ constructor(prefix) {
701
+ this.prefix = prefix;
702
+ }
703
+ shouldLog(level) {
704
+ const categoryLevel = getCategoryLogLevel(this.prefix);
705
+ return levelPriority[level] >= levelPriority[categoryLevel];
706
+ }
707
+ ensureLogDirectory(dir) {
708
+ if (!existsSync(dir)) {
709
+ try {
710
+ mkdirSync(dir, { recursive: true });
711
+ } catch (err) {
712
+ console.error("[Logger] Failed to create log directory:", dir, err);
713
+ }
714
+ }
715
+ }
716
+ getCallerLocation() {
717
+ const originalLimit = Error.stackTraceLimit;
718
+ Error.stackTraceLimit = 10;
719
+ const err = new Error;
720
+ Error.captureStackTrace(err, this.formatMessage);
721
+ const stack = err.stack?.split(`
722
+ `) || [];
723
+ Error.stackTraceLimit = originalLimit;
724
+ for (let i = 1;i < stack.length; i++) {
725
+ const line = stack[i];
726
+ if (line.includes("at ") && !line.includes("logger.ts") && !line.includes("formatMessage")) {
727
+ const match = line.match(/at\s+.+\s+\((.+):(\d+):\d+\)/) || line.match(/at\s+(.+):(\d+):\d+/);
728
+ if (match) {
729
+ const filePath = match[1];
730
+ const relativePath = this.getRelativePath(filePath);
731
+ return {
732
+ file: relativePath,
733
+ line: parseInt(match[2], 10)
734
+ };
735
+ }
736
+ }
737
+ }
738
+ return null;
739
+ }
740
+ getRelativePath(fullPath) {
741
+ return simplifyFilePath(fullPath);
742
+ }
743
+ formatMessage(level, message, data) {
744
+ const now = new Date;
745
+ const timestamp = now.toLocaleString("zh-CN", {
746
+ timeZone: "Asia/Shanghai",
747
+ year: "numeric",
748
+ month: "2-digit",
749
+ day: "2-digit",
750
+ hour: "2-digit",
751
+ minute: "2-digit",
752
+ second: "2-digit",
753
+ hour12: false
754
+ }).replace(/\//g, "-") + "." + String(now.getMilliseconds()).padStart(3, "0");
755
+ const prefix = this.prefix ? `[${this.prefix}]` : "";
756
+ let traceIdStr = "";
757
+ try {
758
+ const provider = getTracerProvider();
759
+ const tracer = provider.getTracer("roy-tracer");
760
+ const context = tracer.getCurrentContext();
761
+ if (context?.traceId) {
762
+ traceIdStr = `[traceId=${context.traceId}]`;
763
+ }
764
+ } catch {}
765
+ let locationStr = "";
766
+ if (data && typeof data === "object" && "callerLocation" in data) {
767
+ const logData = data;
768
+ locationStr = logData.callerLocation ? ` [${logData.callerLocation}]` : "";
769
+ const { callerLocation: _callerLocation, ...rest } = logData;
770
+ data = Object.keys(rest).length > 0 ? rest : undefined;
771
+ } else {
772
+ const location = this.getCallerLocation();
773
+ if (location) {
774
+ locationStr = ` [${location.file}:${location.line}]`;
775
+ }
776
+ }
777
+ let formatted = `${timestamp} [${level.toUpperCase()}]${traceIdStr}${locationStr}${prefix} ${message}`;
778
+ if (data !== undefined) {
779
+ if (typeof data === "object") {
780
+ formatted += " " + JSON.stringify(data).replace(/\n/g, "");
781
+ } else {
782
+ formatted += " " + String(data);
783
+ }
784
+ }
785
+ const maxOutput = getMaxOutput();
786
+ if (maxOutput && maxOutput > 0 && formatted.length > maxOutput) {
787
+ formatted = formatted.substring(0, maxOutput) + " [TRUNCATED]";
788
+ }
789
+ return formatted;
790
+ }
791
+ writeToFile(message) {
792
+ try {
793
+ const dir = getLogDir();
794
+ const filename = getLogFile();
795
+ const expandedDir = expandHomeDir(dir);
796
+ const resolvedDir = isAbsolutePath(expandedDir) ? expandedDir : join(process.cwd(), expandedDir);
797
+ this.ensureLogDirectory(resolvedDir);
798
+ const logFile = join(resolvedDir, filename);
799
+ appendFileSync(logFile, message + `
800
+ `, "utf-8");
801
+ } catch (err) {
802
+ console.error("[Logger] Failed to write to log file:", err);
803
+ }
804
+ }
805
+ log(level, message, data) {
806
+ if (!this.shouldLog(level))
807
+ return;
808
+ const formatted = this.formatMessage(level, message, data);
809
+ this.writeToFile(formatted);
810
+ if (!isQuietMode()) {
811
+ const consoleMethod = level === "error" ? console.error : level === "warn" ? console.warn : level === "info" ? console.log : console.debug;
812
+ consoleMethod(formatted);
813
+ }
814
+ }
815
+ debug(message, data) {
816
+ this.log("debug", message, data);
817
+ }
818
+ info(message, data) {
819
+ this.log("info", message, data);
820
+ }
821
+ warn(message, data) {
822
+ this.log("warn", message, data);
823
+ }
824
+ error(message, data) {
825
+ this.log("error", message, data);
826
+ }
827
+ }
828
+ function createLogger(prefix) {
829
+ if (!loggerCache.has(prefix)) {
830
+ loggerCache.set(prefix, new Logger(prefix));
831
+ }
832
+ return loggerCache.get(prefix);
833
+ }
834
+ function getLogLevels() {
835
+ return ["debug", "info", "warn", "error"];
836
+ }
837
+ var configComponentInstance = null, quietMode = false, logDirOverride, levelPriority, loggerCache;
838
+ var init_logger = __esm(() => {
839
+ init_tracer_provider();
840
+ levelPriority = {
841
+ debug: 0,
842
+ info: 1,
843
+ warn: 2,
844
+ error: 3
845
+ };
846
+ loggerCache = new Map;
847
+ });
848
+
849
+ // packages/core/src/env/task/hooks/task-hook-points.ts
850
+ var TaskHookPoints = {
851
+ BEFORE_CREATE: "task:before.create",
852
+ AFTER_CREATE: "task:after.create",
853
+ BEFORE_UPDATE: "task:before.update",
854
+ AFTER_UPDATE: "task:after.update",
855
+ BEFORE_DELETE: "task:before.delete",
856
+ AFTER_DELETE: "task:after.delete",
857
+ DELEGATE_BEFORE: "task:delegate:before",
858
+ DELEGATE_AFTER: "task:delegate:after",
859
+ OPERATION_BEFORE_CREATE: "task:operation:before.create",
860
+ OPERATION_AFTER_CREATE: "task:operation:after.create"
861
+ };
862
+ // packages/core/src/env/task/delegate/delegate-tool.ts
863
+ init_logger();
864
+ import { z } from "zod";
865
+
866
+ // packages/core/src/env/task/delegate/task-events.ts
867
+ var TaskEventTypes = {
868
+ TASK_STARTED: "task.started",
869
+ TASK_PROGRESS: "task.progress",
870
+ TASK_COMPLETED: "task.completed",
871
+ TASK_FAILED: "task.failed",
872
+ TASK_TIMEOUT: "task.timeout",
873
+ TASK_STOPPED: "task.stopped"
874
+ };
875
+ function createTaskStartedPayload(task, parentSessionId) {
876
+ return {
877
+ taskId: task.id,
878
+ subSessionId: task.subSessionId,
879
+ parentSessionId,
880
+ description: task.description,
881
+ subagentType: task.subagentType,
882
+ associatedTaskId: task.taskId
883
+ };
884
+ }
885
+ function createTaskProgressPayload(task, parentSessionId) {
886
+ return {
887
+ taskId: task.id,
888
+ subSessionId: task.subSessionId,
889
+ parentSessionId,
890
+ status: task.status,
891
+ progress: task.progress,
892
+ progressMessage: task.progressMessage,
893
+ description: task.description,
894
+ subagentType: task.subagentType
895
+ };
896
+ }
897
+ function createTaskCompletedPayload(task, parentSessionId, executionTimeMs) {
898
+ return {
899
+ taskId: task.id,
900
+ subSessionId: task.subSessionId,
901
+ parentSessionId,
902
+ status: task.status,
903
+ result: task.result,
904
+ error: task.error,
905
+ executionTimeMs,
906
+ associatedTaskId: task.taskId,
907
+ description: task.description,
908
+ subagentType: task.subagentType
909
+ };
910
+ }
911
+
912
+ // packages/core/src/env/hook/hook-manager.ts
913
+ class HookManager {
914
+ _hooks = new Map;
915
+ componentName;
916
+ componentVersion;
917
+ defaultPriority;
918
+ constructor(options = {}) {
919
+ this.componentName = options.componentName ?? "unknown";
920
+ this.componentVersion = options.componentVersion ?? "0.0.0";
921
+ this.defaultPriority = options.defaultPriority ?? 0;
922
+ }
923
+ register(hookPoint, hook) {
924
+ const hooks = this.getOrCreateHooks(hookPoint);
925
+ hooks.push(hook);
926
+ }
927
+ registerMany(hookPoint, hooks) {
928
+ const hookList = this.getOrCreateHooks(hookPoint);
929
+ hookList.push(...hooks);
930
+ }
931
+ unregister(hookPoint, name) {
932
+ const hooks = this._hooks.get(hookPoint);
933
+ if (!hooks)
934
+ return false;
935
+ const index = hooks.findIndex((h) => h.name === name);
936
+ if (index === -1)
937
+ return false;
938
+ hooks.splice(index, 1);
939
+ return true;
940
+ }
941
+ unregisterAll(hookPoint) {
942
+ this._hooks.delete(hookPoint);
943
+ }
944
+ async execute(hookPoint, data, metadata = {}) {
945
+ const hooks = this._hooks.get(hookPoint);
946
+ if (!hooks || hooks.length === 0)
947
+ return;
948
+ const sortedHooks = this.sortHooks(hooks);
949
+ const ctx = this.createContext(hookPoint, data, metadata, "before");
950
+ for (const hook of sortedHooks) {
951
+ await this.safeExecute(hook, ctx);
952
+ }
953
+ }
954
+ async executeAndCollect(hookPoint, data, metadata = {}) {
955
+ const hooks = this._hooks.get(hookPoint);
956
+ if (!hooks || hooks.length === 0)
957
+ return [];
958
+ const sortedHooks = this.sortHooks(hooks);
959
+ const ctx = this.createContext(hookPoint, data, metadata, "before");
960
+ const results = [];
961
+ for (const hook of sortedHooks) {
962
+ const result = await this.safeExecuteAndReturn(hook, ctx);
963
+ if (result !== undefined) {
964
+ results.push(result);
965
+ }
966
+ }
967
+ return results;
968
+ }
969
+ count(hookPoint) {
970
+ return this._hooks.get(hookPoint)?.length ?? 0;
971
+ }
972
+ clear() {
973
+ this._hooks.clear();
974
+ }
975
+ getHookPoints() {
976
+ return Array.from(this._hooks.keys());
977
+ }
978
+ hasHooks(hookPoint) {
979
+ return this.count(hookPoint) > 0;
980
+ }
981
+ setComponentInfo(name, version) {
982
+ this.componentName = name;
983
+ this.componentVersion = version;
984
+ }
985
+ get hooks() {
986
+ return this._hooks;
987
+ }
988
+ async executeWithIntervention(hookPoint, data, metadata = {}) {
989
+ const hooks = this._hooks.get(hookPoint);
990
+ if (!hooks || hooks.length === 0) {
991
+ return { stopped: false, results: [] };
992
+ }
993
+ const sortedHooks = this.sortHooks(hooks);
994
+ const ctx = this.createContext(hookPoint, data, metadata, "before");
995
+ const results = [];
996
+ let stopped = false;
997
+ let action;
998
+ for (const hook of sortedHooks) {
999
+ if (stopped)
1000
+ break;
1001
+ const result = await this.safeExecuteAndReturn(hook, ctx);
1002
+ results.push(result);
1003
+ if (result && typeof result === "object" && "stopped" in result) {
1004
+ const hookResult = result;
1005
+ if (hookResult.stopped) {
1006
+ stopped = true;
1007
+ action = hookResult.action;
1008
+ }
1009
+ }
1010
+ }
1011
+ return { stopped, action, results };
1012
+ }
1013
+ getOrCreateHooks(hookPoint) {
1014
+ let hooks = this._hooks.get(hookPoint);
1015
+ if (!hooks) {
1016
+ hooks = [];
1017
+ this._hooks.set(hookPoint, hooks);
1018
+ }
1019
+ return hooks;
1020
+ }
1021
+ sortHooks(hooks) {
1022
+ return [...hooks].sort((a, b) => {
1023
+ const priorityA = a.priority ?? this.defaultPriority;
1024
+ const priorityB = b.priority ?? this.defaultPriority;
1025
+ return priorityA - priorityB;
1026
+ });
1027
+ }
1028
+ createContext(hookPoint, data, metadata, phase) {
1029
+ return {
1030
+ component: {
1031
+ name: this.componentName,
1032
+ version: this.componentVersion
1033
+ },
1034
+ data,
1035
+ metadata,
1036
+ phase,
1037
+ hookPoint
1038
+ };
1039
+ }
1040
+ async safeExecute(hook, ctx) {
1041
+ try {
1042
+ await hook.execute(ctx);
1043
+ } catch (error) {
1044
+ console.error(`Hook "${hook.name}" failed:`, error);
1045
+ }
1046
+ }
1047
+ async safeExecuteAndReturn(hook, ctx) {
1048
+ try {
1049
+ return await hook.execute(ctx);
1050
+ } catch (error) {
1051
+ console.error(`Hook "${hook.name}" failed:`, error);
1052
+ return;
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
+ // packages/core/src/env/hook/global-hook-manager.ts
1058
+ var globalHookManager = new HookManager;
1059
+ var AgentHookPoints = {
1060
+ BEFORE_START: "agent:before.start",
1061
+ BEFORE_LLM: "agent:before.llm",
1062
+ AFTER_LLM: "agent:after.llm",
1063
+ BEFORE_TOOL: "agent:before.tool",
1064
+ AFTER_TOOL: "agent:after.tool",
1065
+ ON_ITERATION: "agent:on.iteration",
1066
+ ON_THRESHOLD: "agent:on.threshold",
1067
+ AFTER_COMPLETE: "agent:after.complete",
1068
+ ON_ERROR: "agent:on.error"
1069
+ };
1070
+ var LLMHookPoints = {
1071
+ BEFORE_INVOKE: "llm:before.invoke",
1072
+ AFTER_INVOKE: "llm:after.invoke",
1073
+ ON_STREAM: "llm:on.stream"
1074
+ };
1075
+ var ToolHookPoints = {
1076
+ BEFORE_EXECUTE: "tool:before.execute",
1077
+ AFTER_EXECUTE: "tool:after.execute",
1078
+ BEFORE_REGISTER: "tool:before.register",
1079
+ AFTER_REGISTER: "tool:after.register",
1080
+ ON_ERROR: "tool:on.error"
1081
+ };
1082
+ var hookPointAliases = {
1083
+ "before.tool": "tool:before.execute",
1084
+ "after.tool": "tool:after.execute",
1085
+ "llm.before-invoke": "llm:before.invoke",
1086
+ "llm.after-invoke": "llm:after.invoke",
1087
+ "llm.stream": "llm:on.stream"
1088
+ };
1089
+ function setupAliasHooks() {
1090
+ const originalRegister = globalHookManager.register.bind(globalHookManager);
1091
+ globalHookManager.register = function(hookPoint, hook) {
1092
+ originalRegister(hookPoint, hook);
1093
+ const alias = hookPointAliases[hookPoint];
1094
+ if (alias) {
1095
+ originalRegister(alias, hook);
1096
+ }
1097
+ };
1098
+ }
1099
+ setupAliasHooks();
1100
+ async function executeAgentHook(hookPoint, data, metadata = {}) {
1101
+ await globalHookManager.execute(hookPoint, data, metadata);
1102
+ }
1103
+ async function executeAgentHookWithIntervention(hookPoint, data, metadata = {}) {
1104
+ return globalHookManager.executeWithIntervention(hookPoint, data, metadata);
1105
+ }
1106
+ async function executeLLMHook(hookPoint, data, metadata = {}) {
1107
+ await globalHookManager.execute(hookPoint, data, metadata);
1108
+ }
1109
+ async function executeToolHook(hookPoint, data, metadata = {}) {
1110
+ await globalHookManager.execute(hookPoint, data, metadata);
1111
+ }
1112
+
1113
+ // packages/core/src/env/task/delegate/delegate-tool.ts
1114
+ var logger = createLogger("task:delegate");
1115
+ var builtInSubAgents = [
1116
+ {
1117
+ id: "general",
1118
+ name: "general",
1119
+ mode: "subagent",
1120
+ description: "General-purpose agent for researching complex questions and executing multi-step tasks.",
1121
+ promptOverride: `You are a subagent created by the main agent to handle a specific task.
1122
+
1123
+ ## Your Role
1124
+ - You were created to handle: {task_description}
1125
+ - Complete this task. That's your entire purpose.
1126
+ - You are NOT the main agent. Don't try to be.
1127
+
1128
+ ## Task Context Awareness (Required Behavior)
1129
+
1130
+ **IMPORTANT: Before starting any work, you MUST gather task context to avoid working with outdated or missing information.**
1131
+
1132
+ 1. **Read task details first**: Use \`task_get\` to read the task's:
1133
+ - \`description\`: Detailed description of what needs to be done
1134
+ - \`goals_and_expected_deliverables\`: Clear success criteria and expected outputs
1135
+ - \`current_status\`: Current work progress
1136
+ - \`parent_task_id\`: If exists, this is a sub-task
1137
+
1138
+ 2. **Read recent operations**: Use \`task_operation_list\` to get the last ~15 operation records
1139
+ - These provide history, progress, decisions, and context from previous work
1140
+
1141
+ 3. **Read parent task context** (if \`parent_task_id\` exists):
1142
+ - Use \`task_get\` to read the parent task's description and goals
1143
+ - Use \`task_operation_list\` to get parent's recent operations
1144
+ - This forms the overall task background and ensures alignment
1145
+
1146
+ **Why this matters**:
1147
+ - The main agent may have made critical decisions recorded in operations
1148
+ - Parent task goals provide the broader context for your sub-task
1149
+ - Without this context, you risk working on wrong/outdated goals
1150
+
1151
+ ## Rules
1152
+ 1. **Gather context first** - Always read task details and operations before starting
1153
+ 2. **Stay focused** - Do your assigned task, nothing else
1154
+ 3. **Complete the task** - Your final message will be automatically reported to the main agent
1155
+ 4. **Don't initiate** - No heartbeats, no proactive actions, no side quests
1156
+ 5. **Be ephemeral** - You may be terminated after task completion. That's fine.
1157
+ 6. **No nested delegation** - Do NOT use delegate_task or stop_task tools. Complete the task yourself.
1158
+
1159
+ ## Execution
1160
+ - Use the available tools to complete the task
1161
+ - If you need more information, ask the main agent through the result
1162
+ - Return a clear summary of what you did and the results`,
1163
+ deniedTools: ["delegate_task", "stop_task"]
1164
+ },
1165
+ {
1166
+ id: "explore",
1167
+ name: "explore",
1168
+ mode: "subagent",
1169
+ description: "Fast agent specialized for exploring codebases, finding files, and searching for patterns.",
1170
+ allowedTools: ["glob", "grep", "read", "bash"],
1171
+ deniedTools: ["delegate_task", "stop_task"]
1172
+ },
1173
+ {
1174
+ id: "file_agent",
1175
+ name: "file_agent",
1176
+ mode: "subagent",
1177
+ description: "File operation expert, skilled at reading, writing, searching and organizing files.",
1178
+ allowedTools: ["file_read", "file_write", "file_glob", "grep", "glob", "read"],
1179
+ deniedTools: ["delegate_task", "stop_task"]
1180
+ },
1181
+ {
1182
+ id: "web_search_agent",
1183
+ name: "web_search_agent",
1184
+ mode: "subagent",
1185
+ description: "Web search expert, using Exa search engine to get latest information.",
1186
+ allowedTools: ["exa_web_search_exa"],
1187
+ deniedTools: ["delegate_task", "stop_task"]
1188
+ }
1189
+ ];
1190
+ function getSubAgentSpec(id) {
1191
+ return builtInSubAgents.find((agent) => agent.id === id);
1192
+ }
1193
+ function getSubAgentToolDescription() {
1194
+ return builtInSubAgents.map((agent) => `- ${agent.id}: ${agent.description}`).join(`
1195
+ `);
1196
+ }
1197
+ function ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools) {
1198
+ let agentInstance = agentComponent.getAgent(subagentType);
1199
+ if (!agentInstance) {
1200
+ const agentConfig = {
1201
+ type: "sub",
1202
+ systemPrompt: basePrompt
1203
+ };
1204
+ if (subAgent?.allowedTools && subAgent.allowedTools.length > 0) {
1205
+ agentConfig.allowedTools = subAgent.allowedTools;
1206
+ }
1207
+ if (deniedTools.length > 0) {
1208
+ agentConfig.deniedTools = deniedTools;
1209
+ }
1210
+ agentInstance = agentComponent.registerAgent(subagentType, agentConfig);
1211
+ logger.debug(`[delegate] Registered subagent: ${subagentType}`);
1212
+ }
1213
+ return agentInstance;
1214
+ }
1215
+ var DelegateToolParameters = z.object({
1216
+ description: z.string().describe("A short (3-5 words) description of the task"),
1217
+ prompt: z.string().describe("The task for the agent to perform"),
1218
+ subagent_type: z.string().describe("The type of specialized agent to use for this task").default("general"),
1219
+ background: z.boolean().describe("Whether to run the task in background. If true, returns immediately and notifies when complete (default: false)").default(false),
1220
+ timeout: z.number().describe("Task timeout in milliseconds. If set, task will be terminated after timeout (optional)").optional(),
1221
+ cleanup: z.enum(["delete", "keep"]).describe("Whether to delete sub session after completion. 'delete' removes the session, 'keep' retains it (default: keep)").default("keep").optional(),
1222
+ task_id: z.number().describe("Optional task ID to associate with this delegate task, for tracking in operation records").optional(),
1223
+ reason: z.string().describe("Brief reason for calling this tool (max 30 chars, e.g., 'Delegate refactor task')").optional()
1224
+ });
1225
+ var DEFAULT_TIMEOUT = 900000;
1226
+ var PROGRESS_INTERVAL = 120000;
1227
+
1228
+ class BackgroundTaskManager {
1229
+ env;
1230
+ tasks = new Map;
1231
+ progressTimers = new Map;
1232
+ abortControllers = new Map;
1233
+ constructor(env) {
1234
+ this.env = env;
1235
+ }
1236
+ getSessionComponent() {
1237
+ return this.env?.getComponent?.("session");
1238
+ }
1239
+ async createTask(options) {
1240
+ const { parentSessionId, description, prompt, subagentType, timeout, cleanup, taskId } = options;
1241
+ const taskIdGen = `task_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
1242
+ const sessionComponent = this.getSessionComponent();
1243
+ if (!sessionComponent) {
1244
+ throw new Error("SessionComponent not found");
1245
+ }
1246
+ const parentSession = await sessionComponent.get(parentSessionId);
1247
+ if (!parentSession) {
1248
+ throw new Error(`Parent session not found: ${parentSessionId}`);
1249
+ }
1250
+ const metadata = {
1251
+ subagent_type: subagentType,
1252
+ created_by: "subagent",
1253
+ task_description: description
1254
+ };
1255
+ if (taskId) {
1256
+ metadata.task_id = taskId;
1257
+ }
1258
+ const subSession = await sessionComponent.create({
1259
+ title: `${description} (@${subagentType} subagent)`,
1260
+ metadata
1261
+ });
1262
+ if (!subSession) {
1263
+ throw new Error("Failed to create sub-session");
1264
+ }
1265
+ const abortController = new AbortController;
1266
+ const task = {
1267
+ id: taskIdGen,
1268
+ subSessionId: subSession.id,
1269
+ parentSessionId,
1270
+ description,
1271
+ subagentType,
1272
+ status: "pending",
1273
+ createdAt: Date.now(),
1274
+ abortController,
1275
+ taskId
1276
+ };
1277
+ this.tasks.set(taskIdGen, task);
1278
+ this.abortControllers.set(taskIdGen, abortController);
1279
+ this.publishEvent(TaskEventTypes.TASK_STARTED, createTaskStartedPayload(task, parentSessionId), parentSessionId);
1280
+ this.executeTask(taskIdGen, prompt, timeout, cleanup, parentSessionId).catch((err) => {
1281
+ logger.error(`[BackgroundTaskManager] executeTask unhandled rejection`, {
1282
+ taskId: taskIdGen,
1283
+ error: err instanceof Error ? err.message : String(err)
1284
+ });
1285
+ });
1286
+ return { taskId: taskIdGen, subSessionId: subSession.id };
1287
+ }
1288
+ async executeTask(taskId, prompt, timeout, cleanup, parentSessionId) {
1289
+ const task = this.tasks.get(taskId);
1290
+ if (!task) {
1291
+ logger.warn(`[BackgroundTaskManager] executeTask: Task not found`, { taskId });
1292
+ return;
1293
+ }
1294
+ task.status = "running";
1295
+ task.startedAt = Date.now();
1296
+ const timeoutMs = timeout || DEFAULT_TIMEOUT;
1297
+ const abortController = this.abortControllers.get(taskId);
1298
+ this.startProgressReporter(taskId, parentSessionId || task.parentSessionId);
1299
+ try {
1300
+ const sessionComponent = this.getSessionComponent();
1301
+ const subSession = await sessionComponent.get(task.subSessionId);
1302
+ if (!subSession) {
1303
+ throw new Error(`Sub session not found: ${task.subSessionId}`);
1304
+ }
1305
+ const result = await this.executeWithAbort(subSession, prompt, timeoutMs, abortController?.signal);
1306
+ if (abortController?.signal.aborted) {
1307
+ logger.info(`[BackgroundTaskManager] Task was aborted`, { taskId });
1308
+ return;
1309
+ }
1310
+ task.status = "completed";
1311
+ task.completedAt = Date.now();
1312
+ task.result = result;
1313
+ const executionTimeMs = task.completedAt - task.startedAt;
1314
+ this.publishEvent(TaskEventTypes.TASK_COMPLETED, createTaskCompletedPayload(task, parentSessionId || task.parentSessionId, executionTimeMs), parentSessionId || task.parentSessionId);
1315
+ logger.info(`[BackgroundTaskManager] Task completed successfully`, {
1316
+ taskId,
1317
+ executionTimeMs
1318
+ });
1319
+ } catch (error) {
1320
+ const errorMessage = error instanceof Error ? error.message : String(error);
1321
+ const isStoppedError = errorMessage.toLowerCase().includes("stopped") || errorMessage.toLowerCase().includes("aborted");
1322
+ if (isStoppedError) {
1323
+ task.status = "stopped";
1324
+ this.publishEvent(TaskEventTypes.TASK_STOPPED, createTaskCompletedPayload(task, parentSessionId || task.parentSessionId, task.completedAt - task.startedAt), parentSessionId || task.parentSessionId);
1325
+ } else if (errorMessage.includes("timeout")) {
1326
+ task.status = "timeout";
1327
+ this.publishEvent(TaskEventTypes.TASK_TIMEOUT, createTaskCompletedPayload(task, parentSessionId || task.parentSessionId, task.completedAt - task.startedAt), parentSessionId || task.parentSessionId);
1328
+ } else {
1329
+ task.status = "failed";
1330
+ this.publishEvent(TaskEventTypes.TASK_FAILED, createTaskCompletedPayload(task, parentSessionId || task.parentSessionId, task.completedAt - task.startedAt), parentSessionId || task.parentSessionId);
1331
+ }
1332
+ task.error = errorMessage;
1333
+ task.completedAt = Date.now();
1334
+ logger.error(`[BackgroundTaskManager] Task execution error`, {
1335
+ taskId,
1336
+ status: task.status,
1337
+ error: errorMessage
1338
+ });
1339
+ } finally {
1340
+ this.stopProgressReporter(taskId);
1341
+ }
1342
+ }
1343
+ async executeWithAbort(subSession, prompt, timeoutMs, signal) {
1344
+ return new Promise((resolve, reject) => {
1345
+ const timer = setTimeout(() => {
1346
+ reject(new Error(`Task execution timeout after ${timeoutMs}ms`));
1347
+ }, timeoutMs);
1348
+ signal?.addEventListener("abort", () => {
1349
+ clearTimeout(timer);
1350
+ reject(new Error("Task execution stopped"));
1351
+ });
1352
+ const metadata = subSession.info?.metadata || {};
1353
+ const taskId = metadata.task_id;
1354
+ const taskDescription = metadata.task_description || "";
1355
+ const sessionId = subSession.id;
1356
+ const subagentType = metadata.subagent_type || "general";
1357
+ const subAgent = getSubAgentSpec(subagentType);
1358
+ let basePrompt = subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
1359
+ const deniedTools = subAgent?.deniedTools || [];
1360
+ let fullPrompt = basePrompt.replace(/{task_description}/g, taskDescription || "N/A");
1361
+ fullPrompt += `
1362
+
1363
+ ---
1364
+
1365
+ # Session Info
1366
+ - task_id: ${taskId || "N/A"}
1367
+ - session_id: ${sessionId}
1368
+
1369
+ ---
1370
+
1371
+ ## \u7528\u6237\u6307\u4EE4
1372
+ ${prompt}
1373
+
1374
+ ---
1375
+
1376
+ ## \u6267\u884C\u89C4\u8303
1377
+ - \u4F7F\u7528\u53EF\u7528\u5DE5\u5177\u5B8C\u6210\u4EFB\u52A1
1378
+ - \u8FD4\u56DE\u6E05\u6670\u7684\u4EFB\u52A1\u6267\u884C\u7ED3\u679C\u6458\u8981
1379
+ - \u9002\u65F6\u8C03\u7528 task_operation_create \u8BB0\u5F55\u8FDB\u5C55`;
1380
+ const agentComponent = this.env?.getComponent?.("agent");
1381
+ if (!agentComponent) {
1382
+ clearTimeout(timer);
1383
+ reject(new Error("AgentComponent not found"));
1384
+ return;
1385
+ }
1386
+ ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools);
1387
+ this.env.handle_query?.(fullPrompt, {
1388
+ sessionId,
1389
+ deniedTools: deniedTools.length > 0 ? deniedTools : undefined,
1390
+ agentType: subagentType
1391
+ }).then((result) => {
1392
+ clearTimeout(timer);
1393
+ resolve(result);
1394
+ }).catch((error) => {
1395
+ clearTimeout(timer);
1396
+ reject(error);
1397
+ });
1398
+ });
1399
+ }
1400
+ startProgressReporter(taskId, parentSessionId) {
1401
+ const timer = setInterval(() => {
1402
+ const task = this.tasks.get(taskId);
1403
+ if (!task || task.status !== "running") {
1404
+ this.stopProgressReporter(taskId);
1405
+ return;
1406
+ }
1407
+ if (task.startedAt) {
1408
+ const elapsedMs = Date.now() - task.startedAt;
1409
+ task.progress = Math.min(95, Math.floor(elapsedMs / PROGRESS_INTERVAL * 100));
1410
+ }
1411
+ this.publishEvent(TaskEventTypes.TASK_PROGRESS, createTaskProgressPayload(task, parentSessionId), parentSessionId);
1412
+ }, PROGRESS_INTERVAL);
1413
+ this.progressTimers.set(taskId, timer);
1414
+ }
1415
+ stopProgressReporter(taskId) {
1416
+ const timer = this.progressTimers.get(taskId);
1417
+ if (timer) {
1418
+ clearInterval(timer);
1419
+ this.progressTimers.delete(taskId);
1420
+ }
1421
+ }
1422
+ publishEvent(type, payload, triggerSessionId) {
1423
+ if (this.env?.pushEnvEvent) {
1424
+ this.env.pushEnvEvent({
1425
+ type,
1426
+ metadata: {
1427
+ trigger_session_id: triggerSessionId,
1428
+ source: "task.delegate"
1429
+ },
1430
+ payload
1431
+ });
1432
+ logger.info(`[BackgroundTaskManager] Event published: ${type}`, { payload });
1433
+ }
1434
+ }
1435
+ stopTask(taskId) {
1436
+ const task = this.tasks.get(taskId);
1437
+ if (!task) {
1438
+ return { success: false, message: "Task not found" };
1439
+ }
1440
+ if (task.status === "completed" || task.status === "failed" || task.status === "stopped" || task.status === "timeout") {
1441
+ return {
1442
+ success: false,
1443
+ task,
1444
+ message: `Cannot stop task with status: ${task.status}`
1445
+ };
1446
+ }
1447
+ task.status = "stopped";
1448
+ task.abortController?.abort();
1449
+ task.completedAt = Date.now();
1450
+ this.publishEvent(TaskEventTypes.TASK_STOPPED, createTaskCompletedPayload(task, task.parentSessionId, task.completedAt - task.startedAt), task.parentSessionId);
1451
+ return { success: true, task, message: "Task has been stopped" };
1452
+ }
1453
+ getTask(taskId) {
1454
+ return this.tasks.get(taskId);
1455
+ }
1456
+ listTasks() {
1457
+ return Array.from(this.tasks.values());
1458
+ }
1459
+ dispose() {
1460
+ for (const [taskId, timer] of this.progressTimers) {
1461
+ clearInterval(timer);
1462
+ logger.debug(`[BackgroundTaskManager] Cleared progress timer for task: ${taskId}`);
1463
+ }
1464
+ this.progressTimers.clear();
1465
+ for (const [taskId, controller] of this.abortControllers) {
1466
+ controller.abort();
1467
+ logger.debug(`[BackgroundTaskManager] Aborted task: ${taskId}`);
1468
+ }
1469
+ this.abortControllers.clear();
1470
+ this.tasks.clear();
1471
+ logger.info(`[BackgroundTaskManager] Disposed`);
1472
+ }
1473
+ }
1474
+ function createDelegateTool(taskComponent) {
1475
+ const env = taskComponent.env;
1476
+ const backgroundTaskManager = new BackgroundTaskManager(env);
1477
+ const tool = {
1478
+ name: "delegate_task",
1479
+ description: `Launch a new sub-agent to handle complex, multistep tasks autonomously.
1480
+
1481
+ Available agent types:
1482
+ ${getSubAgentToolDescription()}
1483
+
1484
+ When using the delegate_task tool, you must specify a subagent_type parameter to select which agent type to use.
1485
+
1486
+ ## When to use delegate_task:
1487
+ - When you need to perform complex, multi-step tasks that require independent execution
1488
+ - When you need to explore a codebase thoroughly (use "explore" subagent)
1489
+ - When you need to run long-running tasks without blocking the main agent (use background=true)
1490
+
1491
+ ## Parameters:
1492
+ - **description**: A short (3-5 words) description of the task
1493
+ - **prompt**: The task for the agent to perform
1494
+ - **subagent_type**: The type of specialized agent to use (e.g., "general", "explore")
1495
+ - **background**: Whether to run in background (default: false)
1496
+ - **timeout**: Task timeout in milliseconds (optional)
1497
+ - **task_id**: Optional task ID to associate with this delegate task
1498
+
1499
+ ## Synchronous vs Background mode:
1500
+ **Synchronous mode (default)**: Waits for subagent to complete and returns result directly
1501
+ **Background mode (background=true)**: Returns immediately with "accepted" status, runs independently`,
1502
+ parameters: DelegateToolParameters,
1503
+ execute: async (args, ctx) => {
1504
+ const startTime = Date.now();
1505
+ const params = DelegateToolParameters.parse(args);
1506
+ const { description, prompt, subagent_type = "general", background = false, timeout, cleanup, task_id, reason } = params;
1507
+ const parentSessionId = ctx.session_id || "default";
1508
+ logger.info(`[delegate_task] Called: description=${description}, subagent_type=${subagent_type}, background=${background}, task_id=${task_id}`);
1509
+ const subAgent = getSubAgentSpec(subagent_type);
1510
+ if (!subAgent) {
1511
+ return {
1512
+ success: false,
1513
+ output: "",
1514
+ error: `Unknown subagent type: ${subagent_type}`,
1515
+ metadata: { execution_time_ms: Date.now() - startTime }
1516
+ };
1517
+ }
1518
+ const tagService = taskComponent.getTagService();
1519
+ let promptWithTaskInfo = prompt;
1520
+ const delegateCtx = {
1521
+ taskId: task_id,
1522
+ prompt: promptWithTaskInfo,
1523
+ subagentType: subagent_type,
1524
+ background,
1525
+ timeout,
1526
+ cleanup,
1527
+ reason,
1528
+ tagService
1529
+ };
1530
+ const hookCtx = {
1531
+ component: { name: "task", version: "1.0.0" },
1532
+ data: delegateCtx,
1533
+ metadata: { sessionId: parentSessionId },
1534
+ phase: "before",
1535
+ hookPoint: TaskHookPoints.DELEGATE_BEFORE
1536
+ };
1537
+ await globalHookManager.execute(TaskHookPoints.DELEGATE_BEFORE, hookCtx, { sessionId: parentSessionId });
1538
+ promptWithTaskInfo = delegateCtx.prompt;
1539
+ if (background) {
1540
+ return await handleBackgroundTask(taskComponent, backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, delegateCtx.cleanup, delegateCtx.taskId);
1541
+ } else {
1542
+ return await handleSyncTask(taskComponent, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, delegateCtx.taskId);
1543
+ }
1544
+ }
1545
+ };
1546
+ return tool;
1547
+ }
1548
+ async function handleSyncTask(taskComponent, parentSessionId, description, prompt, subagentType, timeout, taskId) {
1549
+ const startTime = Date.now();
1550
+ try {
1551
+ const sessionComponent = taskComponent.env?.getComponent?.("session");
1552
+ if (!sessionComponent) {
1553
+ return {
1554
+ success: false,
1555
+ output: "",
1556
+ error: "SessionComponent not found",
1557
+ metadata: { execution_time_ms: Date.now() - startTime }
1558
+ };
1559
+ }
1560
+ const parentSession = await sessionComponent.get(parentSessionId);
1561
+ if (!parentSession) {
1562
+ return {
1563
+ success: false,
1564
+ output: "",
1565
+ error: `Parent session not found: ${parentSessionId}`,
1566
+ metadata: { execution_time_ms: Date.now() - startTime }
1567
+ };
1568
+ }
1569
+ const metadata = {
1570
+ subagent_type: subagentType,
1571
+ created_by: "subagent",
1572
+ task_description: description
1573
+ };
1574
+ if (taskId) {
1575
+ metadata.task_id = taskId;
1576
+ }
1577
+ const subSession = await sessionComponent.create({
1578
+ parentID: parentSessionId,
1579
+ title: `${description} (@${subagentType} subagent)`,
1580
+ metadata
1581
+ });
1582
+ if (!subSession) {
1583
+ return {
1584
+ success: false,
1585
+ output: "",
1586
+ error: "Failed to create sub-session",
1587
+ metadata: { execution_time_ms: Date.now() - startTime }
1588
+ };
1589
+ }
1590
+ const subAgent = getSubAgentSpec(subagentType);
1591
+ let basePrompt = subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
1592
+ const deniedTools = subAgent?.deniedTools || [];
1593
+ let fullPrompt = basePrompt.replace(/{task_description}/g, description || "N/A");
1594
+ fullPrompt += `
1595
+
1596
+ ---
1597
+
1598
+ # Session Info
1599
+ - task_id: ${taskId || "N/A"}
1600
+ - session_id: ${subSession.id}
1601
+
1602
+ ---
1603
+
1604
+ ## \u7528\u6237\u6307\u4EE4
1605
+ ${prompt}
1606
+
1607
+ ---
1608
+
1609
+ ## \u6267\u884C\u89C4\u8303
1610
+ - \u4F7F\u7528\u53EF\u7528\u5DE5\u5177\u5B8C\u6210\u4EFB\u52A1
1611
+ - \u8FD4\u56DE\u6E05\u6670\u7684\u4EFB\u52A1\u6267\u884C\u7ED3\u679C\u6458\u8981
1612
+ - \u9002\u65F6\u8C03\u7528 task_operation_create \u8BB0\u5F55\u8FDB\u5C55`;
1613
+ const agentComponent = taskComponent.env?.getComponent?.("agent");
1614
+ if (!agentComponent) {
1615
+ return {
1616
+ success: false,
1617
+ output: "",
1618
+ error: "AgentComponent not found",
1619
+ metadata: { execution_time_ms: Date.now() - startTime }
1620
+ };
1621
+ }
1622
+ ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools);
1623
+ const timeoutMs = timeout || DEFAULT_TIMEOUT;
1624
+ let result;
1625
+ try {
1626
+ result = await Promise.race([
1627
+ taskComponent.env?.handle_query?.(fullPrompt, {
1628
+ sessionId: subSession.id,
1629
+ deniedTools: deniedTools.length > 0 ? deniedTools : undefined,
1630
+ agentType: subagentType
1631
+ }),
1632
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Task execution timeout after ${timeoutMs}ms`)), timeoutMs))
1633
+ ]);
1634
+ } catch (error) {
1635
+ result = error instanceof Error ? error.message : String(error);
1636
+ }
1637
+ await sessionComponent.addMessage(subSession.id, {
1638
+ role: "assistant",
1639
+ content: result
1640
+ });
1641
+ return {
1642
+ success: true,
1643
+ output: result + `
1644
+
1645
+ ` + [
1646
+ "<task_metadata>",
1647
+ `session_id: ${subSession.id}`,
1648
+ `subagent_type: ${subagentType}`,
1649
+ "</task_metadata>"
1650
+ ].join(`
1651
+ `),
1652
+ metadata: {
1653
+ execution_time_ms: Date.now() - startTime,
1654
+ sessionId: subSession.id
1655
+ }
1656
+ };
1657
+ } catch (error) {
1658
+ return {
1659
+ success: false,
1660
+ output: "",
1661
+ error: error instanceof Error ? error.message : String(error),
1662
+ metadata: { execution_time_ms: Date.now() - startTime }
1663
+ };
1664
+ }
1665
+ }
1666
+ async function handleBackgroundTask(taskComponent, backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, cleanup, taskId) {
1667
+ const startTime = Date.now();
1668
+ try {
1669
+ let associatedTaskId = taskId;
1670
+ if (!associatedTaskId) {
1671
+ const newTask = await taskComponent.createTask({
1672
+ title: description,
1673
+ description: `Background task delegated to ${subagentType} subagent`,
1674
+ priority: "medium",
1675
+ goals_and_expected_deliverables: prompt,
1676
+ sessionId: parentSessionId
1677
+ });
1678
+ associatedTaskId = newTask.id;
1679
+ await taskComponent.createOperation({
1680
+ taskId: associatedTaskId,
1681
+ sessionId: parentSessionId,
1682
+ actionType: "create",
1683
+ actionTitle: `Delegated to ${subagentType} subagent`,
1684
+ actionDescription: `Background task started: ${description}`
1685
+ });
1686
+ } else {
1687
+ await taskComponent.updateTask(associatedTaskId, {
1688
+ status: "active",
1689
+ current_status: `Running ${subagentType} subagent`
1690
+ });
1691
+ await taskComponent.createOperation({
1692
+ taskId: associatedTaskId,
1693
+ sessionId: parentSessionId,
1694
+ actionType: "progress",
1695
+ actionTitle: `Started ${subagentType} subagent`,
1696
+ actionDescription: `Background task: ${description}`
1697
+ });
1698
+ }
1699
+ const { taskId: bgTaskId, subSessionId } = await backgroundTaskManager.createTask({
1700
+ parentSessionId,
1701
+ description,
1702
+ prompt,
1703
+ subagentType,
1704
+ timeout,
1705
+ cleanup,
1706
+ taskId: associatedTaskId
1707
+ });
1708
+ const output = [
1709
+ `\u2705 Background task accepted`,
1710
+ "",
1711
+ `\uD83D\uDCCB Task ID: ${bgTaskId}`,
1712
+ `\uD83D\uDCDD Description: ${description}`,
1713
+ `\uD83E\uDD16 Sub-agent: ${subagentType}`,
1714
+ associatedTaskId ? `\uD83D\uDCCC Associated Task: #${associatedTaskId}` : "",
1715
+ `\u23F1\uFE0F Timeout: ${(timeout || DEFAULT_TIMEOUT) / 1000}s`,
1716
+ "",
1717
+ `Use stop_task with task_id="${bgTaskId}" to cancel this task.`
1718
+ ].filter(Boolean).join(`
1719
+ `);
1720
+ return {
1721
+ success: true,
1722
+ output,
1723
+ metadata: {
1724
+ execution_time_ms: Date.now() - startTime,
1725
+ sessionId: subSessionId,
1726
+ background: true,
1727
+ status: "accepted",
1728
+ task_id: associatedTaskId,
1729
+ bgTaskId
1730
+ }
1731
+ };
1732
+ } catch (error) {
1733
+ return {
1734
+ success: false,
1735
+ output: "",
1736
+ error: error instanceof Error ? error.message : String(error),
1737
+ metadata: { execution_time_ms: Date.now() - startTime }
1738
+ };
1739
+ }
1740
+ }
1741
+ // packages/core/src/env/task/delegate/stop-tool.ts
1742
+ import { z as z2 } from "zod";
1743
+ var StopTaskToolParameters = z2.object({
1744
+ task_id: z2.string().describe("The ID of the background task to stop")
1745
+ });
1746
+ var STOP_TASK_DESCRIPTION = `Stop a running background task.
1747
+
1748
+ Use this tool to stop a background task that is currently running. This is useful when:
1749
+ - The user wants to cancel a long-running task
1750
+ - The task is taking too long and needs to be stopped
1751
+ - The user wants to change direction and doesn't need the task result anymore
1752
+
1753
+ When stopped, the task will be terminated immediately and you will receive a confirmation.
1754
+
1755
+ Parameters:
1756
+ - task_id: The ID of the background task to stop (obtained from the delegate_task response)`;
1757
+ function formatDuration(ms) {
1758
+ const seconds = Math.floor(ms / 1000);
1759
+ const minutes = Math.floor(seconds / 60);
1760
+ const hours = Math.floor(minutes / 60);
1761
+ if (hours > 0) {
1762
+ return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
1763
+ } else if (minutes > 0) {
1764
+ return `${minutes}m ${seconds % 60}s`;
1765
+ } else {
1766
+ return `${seconds}s`;
1767
+ }
1768
+ }
1769
+ function createStopTool(taskManager) {
1770
+ return {
1771
+ name: "stop_task",
1772
+ description: STOP_TASK_DESCRIPTION,
1773
+ parameters: StopTaskToolParameters,
1774
+ execute: async (args, ctx) => {
1775
+ const startTime = Date.now();
1776
+ const params = StopTaskToolParameters.parse(args);
1777
+ const { task_id } = params;
1778
+ const result = taskManager.stopTask(task_id);
1779
+ if (result.success) {
1780
+ const task = result.task;
1781
+ const elapsedMs = task.startedAt ? Date.now() - task.startedAt : Date.now() - task.createdAt;
1782
+ const output = [
1783
+ `\u2705 Task stopped successfully`,
1784
+ "",
1785
+ `\uD83D\uDCCB Task ID: ${task_id}`,
1786
+ `\uD83D\uDCDD Description: ${task.description}`,
1787
+ `\uD83D\uDD04 Status: ${task.status} \u2192 stopped`,
1788
+ `\u23F1\uFE0F Elapsed Time: ${formatDuration(elapsedMs)}`,
1789
+ "",
1790
+ result.message
1791
+ ].join(`
1792
+ `);
1793
+ return {
1794
+ success: true,
1795
+ output,
1796
+ metadata: {
1797
+ execution_time_ms: Date.now() - startTime,
1798
+ task_id,
1799
+ previous_status: task.status
1800
+ }
1801
+ };
1802
+ } else {
1803
+ const task = result.task;
1804
+ let output;
1805
+ if (task) {
1806
+ output = [
1807
+ `\u26A0\uFE0F Cannot stop task`,
1808
+ "",
1809
+ `\uD83D\uDCCB Task ID: ${task_id}`,
1810
+ `\uD83D\uDCDD Description: ${task.description}`,
1811
+ `\uD83D\uDD04 Current Status: ${task.status}`,
1812
+ "",
1813
+ result.message
1814
+ ].join(`
1815
+ `);
1816
+ } else {
1817
+ output = [
1818
+ `\u274C Task not found`,
1819
+ "",
1820
+ `\uD83D\uDCCB Task ID: ${task_id}`,
1821
+ "",
1822
+ result.message
1823
+ ].join(`
1824
+ `);
1825
+ }
1826
+ return {
1827
+ success: false,
1828
+ output,
1829
+ error: result.message,
1830
+ metadata: {
1831
+ execution_time_ms: Date.now() - startTime,
1832
+ task_id
1833
+ }
1834
+ };
1835
+ }
1836
+ }
1837
+ };
1838
+ }
1839
+ export {
1840
+ createStopTool,
1841
+ createDelegateTool,
1842
+ TaskEventTypes,
1843
+ BackgroundTaskManager
1844
+ };