tnega 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +63 -152
  2. package/dist/agent.js +531 -0
  3. package/dist/agent.js.map +7 -0
  4. package/dist/bin.js +3173 -640
  5. package/dist/bin.js.map +4 -4
  6. package/dist/cli-runtime.js +7808 -0
  7. package/dist/cli-runtime.js.map +7 -0
  8. package/dist/core.js +1325 -0
  9. package/dist/core.js.map +7 -0
  10. package/dist/eval.js +2736 -0
  11. package/dist/eval.js.map +7 -0
  12. package/dist/events.js +1194 -0
  13. package/dist/events.js.map +7 -0
  14. package/dist/evolve.js +2487 -0
  15. package/dist/evolve.js.map +7 -0
  16. package/dist/index.js +5019 -2154
  17. package/dist/index.js.map +4 -4
  18. package/dist/llm.js +1008 -0
  19. package/dist/llm.js.map +7 -0
  20. package/dist/services.js +1131 -0
  21. package/dist/services.js.map +7 -0
  22. package/dist/session.js +374 -0
  23. package/dist/session.js.map +7 -0
  24. package/dist/tools.js +2470 -0
  25. package/dist/tools.js.map +7 -0
  26. package/dist/types/packages/agent/src/definition.d.ts +17 -0
  27. package/dist/types/packages/agent/src/index.d.ts +3 -0
  28. package/dist/types/packages/agent/src/service.d.ts +44 -0
  29. package/dist/types/packages/agent/src/types.d.ts +141 -0
  30. package/dist/types/packages/cli/src/bin.d.ts +2 -0
  31. package/dist/types/packages/cli/src/commands.d.ts +122 -0
  32. package/dist/types/packages/cli/src/config.d.ts +26 -0
  33. package/dist/types/packages/cli/src/index.d.ts +7 -0
  34. package/dist/types/packages/cli/src/server.d.ts +12 -0
  35. package/dist/types/packages/cli/src/store.d.ts +59 -0
  36. package/dist/types/packages/cli/src/yaml.d.ts +1 -0
  37. package/dist/types/packages/core/src/context.d.ts +28 -0
  38. package/dist/types/packages/core/src/events.d.ts +54 -0
  39. package/dist/types/packages/core/src/fiber.d.ts +79 -0
  40. package/dist/types/packages/core/src/index.d.ts +9 -0
  41. package/dist/types/packages/core/src/logger.d.ts +48 -0
  42. package/dist/types/packages/core/src/reflect.d.ts +42 -0
  43. package/dist/types/packages/core/src/registry.d.ts +54 -0
  44. package/dist/types/packages/core/src/service.d.ts +19 -0
  45. package/dist/types/packages/core/src/utils.d.ts +54 -0
  46. package/dist/types/packages/eval/src/index.d.ts +5 -0
  47. package/dist/types/packages/eval/src/runner.d.ts +27 -0
  48. package/dist/types/packages/eval/src/service.d.ts +23 -0
  49. package/dist/types/packages/eval/src/strategies.d.ts +48 -0
  50. package/dist/types/packages/eval/src/types.d.ts +185 -0
  51. package/dist/types/packages/eval/src/utils.d.ts +5 -0
  52. package/dist/types/packages/evolve/src/diagnose.d.ts +9 -0
  53. package/dist/types/packages/evolve/src/index.d.ts +7 -0
  54. package/dist/types/packages/evolve/src/llm.d.ts +39 -0
  55. package/dist/types/packages/evolve/src/log.d.ts +26 -0
  56. package/dist/types/packages/evolve/src/select.d.ts +3 -0
  57. package/dist/types/packages/evolve/src/service.d.ts +29 -0
  58. package/dist/types/packages/evolve/src/types.d.ts +176 -0
  59. package/dist/types/packages/llm/src/anthropic-messages.d.ts +4 -0
  60. package/dist/types/packages/llm/src/errors.d.ts +6 -0
  61. package/dist/types/packages/llm/src/index.d.ts +7 -0
  62. package/dist/types/packages/llm/src/models.d.ts +29 -0
  63. package/dist/types/packages/llm/src/openai.d.ts +4 -0
  64. package/dist/types/packages/llm/src/provider.d.ts +3 -0
  65. package/dist/types/packages/llm/src/shared.d.ts +15 -0
  66. package/dist/types/packages/llm/src/types.d.ts +11 -0
  67. package/dist/types/packages/session/src/index.d.ts +115 -0
  68. package/dist/types/packages/tools/src/builtins.d.ts +23 -0
  69. package/dist/types/packages/tools/src/calc.d.ts +4 -0
  70. package/dist/types/packages/tools/src/index.d.ts +90 -0
  71. package/dist/types/packages/tools/src/path.d.ts +4 -0
  72. package/dist/types/packages/tools/src/policy.d.ts +14 -0
  73. package/dist/types/src/events.d.ts +1 -0
  74. package/dist/types/src/index.d.ts +15 -0
  75. package/dist/types/src/services.d.ts +4 -0
  76. package/dist/web/assets/index-C3jFlR4V.css +1 -0
  77. package/dist/web/assets/index-DeFGh2h4.js +268 -0
  78. package/dist/web/index.html +13 -0
  79. package/package.json +63 -10
package/dist/agent.js ADDED
@@ -0,0 +1,531 @@
1
+ // packages/session/src/index.ts
2
+ var DEFAULT_CONTEXT_LIMIT = 128e3;
3
+ function estimateMessageTokens(messages) {
4
+ let tokens = 0;
5
+ for (const message of messages) {
6
+ tokens += Math.ceil(message.content.length / 4);
7
+ for (const call of message.tool_calls ?? []) {
8
+ const raw = JSON.stringify(call.arguments ?? {}) ?? "";
9
+ tokens += Math.ceil(raw.length / 4);
10
+ }
11
+ }
12
+ return tokens;
13
+ }
14
+ function estimateContextUsage(messages, limit = DEFAULT_CONTEXT_LIMIT) {
15
+ const tokens = estimateMessageTokens(messages);
16
+ return {
17
+ tokens,
18
+ limit,
19
+ ratio: limit > 0 ? tokens / limit : 0
20
+ };
21
+ }
22
+
23
+ // packages/agent/src/service.ts
24
+ var AgentError = class extends Error {
25
+ name = "AgentError";
26
+ };
27
+ var AgentInbox = class {
28
+ _queue = [];
29
+ _injected = /* @__PURE__ */ new Map();
30
+ get size() {
31
+ return this._queue.length;
32
+ }
33
+ push(input) {
34
+ this._queue.push(input);
35
+ return input;
36
+ }
37
+ claim() {
38
+ return this._queue.shift();
39
+ }
40
+ peek() {
41
+ return this._queue[0];
42
+ }
43
+ inject(key, value) {
44
+ this._injected.set(key, value);
45
+ }
46
+ injected() {
47
+ return new Map(this._injected);
48
+ }
49
+ };
50
+ function copyMessages(messages) {
51
+ return messages.map((message) => {
52
+ const copy = {
53
+ role: message.role,
54
+ content: message.content
55
+ };
56
+ if (message.name) copy.name = message.name;
57
+ if (message.tool_call_id) copy.tool_call_id = message.tool_call_id;
58
+ if (message.toolOk !== void 0) copy.toolOk = message.toolOk;
59
+ if (message.toolError) copy.toolError = { ...message.toolError };
60
+ if (message.tool_calls) {
61
+ copy.tool_calls = message.tool_calls.map((call) => ({
62
+ id: call.id,
63
+ name: call.name,
64
+ arguments: call.arguments
65
+ }));
66
+ }
67
+ return copy;
68
+ });
69
+ }
70
+ function stringify(value) {
71
+ if (typeof value === "string") return value;
72
+ try {
73
+ return JSON.stringify(value) ?? String(value);
74
+ } catch {
75
+ return String(value);
76
+ }
77
+ }
78
+ function copyCompletion(completion) {
79
+ const copy = {
80
+ finishReason: completion.finishReason
81
+ };
82
+ if (completion.content !== void 0) copy.content = completion.content;
83
+ if (completion.toolCalls) {
84
+ copy.toolCalls = completion.toolCalls.map((call) => ({
85
+ id: call.id,
86
+ name: call.name,
87
+ arguments: call.arguments
88
+ }));
89
+ }
90
+ return copy;
91
+ }
92
+ var AgentService = class {
93
+ constructor(ctx, config = {}) {
94
+ this.ctx = ctx;
95
+ this.config = config;
96
+ this.inbox = config.inbox ?? new AgentInbox();
97
+ }
98
+ ctx;
99
+ config;
100
+ inbox;
101
+ async run(input, options = {}) {
102
+ return consumeAgentStream(this._stream(input, options, false));
103
+ }
104
+ async *runStream(input, options = {}) {
105
+ const iterator = this._stream(input, options)[Symbol.asyncIterator]();
106
+ while (true) {
107
+ const next = await iterator.next();
108
+ if (next.done) return next.value;
109
+ yield next.value;
110
+ }
111
+ }
112
+ async *_stream(input, options = {}, useStream = true) {
113
+ const claimed = input ?? this.inbox.claim();
114
+ if (!claimed) throw new AgentError("no agent input available");
115
+ await this.config.hooks?.beforeRun?.(claimed, options);
116
+ const session = this._session();
117
+ const tools = this._tools();
118
+ const llm = this._llm();
119
+ if (!llm) throw new AgentError("no LLM adapter available");
120
+ const maxTurns = options.maxTurns ?? this.config.maxTurns ?? 64;
121
+ const maxSteps = options.maxSteps ?? this.config.maxSteps ?? 64;
122
+ const contextBudget = options.contextBudget ?? this.config.contextBudget;
123
+ const injected = this.inbox.injected();
124
+ this.ctx.emit("agent/start", { input: claimed, options, injected });
125
+ let messages = this._initialMessages(claimed);
126
+ const systemPrompt = this.inbox.injected().get("agentSystem");
127
+ if (typeof systemPrompt === "string" && systemPrompt) {
128
+ await session.append("message", { role: "system", content: systemPrompt });
129
+ }
130
+ if (claimed.text) {
131
+ await session.append("message", { role: "user", content: claimed.text });
132
+ }
133
+ const steps = [];
134
+ let output = "";
135
+ let finishReason = "stop";
136
+ this.ctx.emit("agent/turn-start", {
137
+ input: claimed,
138
+ messages: copyMessages(messages),
139
+ injected
140
+ });
141
+ let index = 0;
142
+ let finalTurnGranted = false;
143
+ while (index < maxTurns + (finalTurnGranted ? 1 : 0)) {
144
+ if (steps.length >= maxSteps) {
145
+ finishReason = "max_steps";
146
+ break;
147
+ }
148
+ if (contextBudget) {
149
+ messages = await this._enforceContextBudget(session, contextBudget, messages);
150
+ }
151
+ const stepInput = copyMessages(messages);
152
+ this.ctx.emit("agent/step", { index, input: copyMessages(stepInput) });
153
+ const availableTools = finalTurnGranted ? [] : tools.list();
154
+ const completeOptions = {
155
+ maxSteps: maxSteps - steps.length
156
+ };
157
+ if (options.signal) completeOptions.signal = options.signal;
158
+ let completion;
159
+ const streamMethod = useStream ? llm.stream : void 0;
160
+ if (streamMethod) {
161
+ const streamEvents = [];
162
+ let cancelled = false;
163
+ try {
164
+ for await (const event of streamMethod(stepInput, availableTools, completeOptions)) {
165
+ streamEvents.push(event);
166
+ yield event;
167
+ }
168
+ } catch (error) {
169
+ if (!options.signal?.aborted) throw error;
170
+ finishReason = "cancelled";
171
+ cancelled = true;
172
+ }
173
+ if (cancelled) break;
174
+ completion = completionFromStreamEvents(streamEvents);
175
+ } else {
176
+ try {
177
+ completion = await llm.complete(stepInput, availableTools, completeOptions);
178
+ } catch (error) {
179
+ if (!options.signal?.aborted) throw error;
180
+ finishReason = "cancelled";
181
+ break;
182
+ }
183
+ }
184
+ const toolCalls = completion.toolCalls ?? [];
185
+ if (finalTurnGranted && toolCalls.length) {
186
+ finishReason = "max_turns";
187
+ break;
188
+ }
189
+ const toolResults = [];
190
+ if (toolCalls.length) {
191
+ await session.append("message", {
192
+ role: "assistant",
193
+ content: completion.content ?? ""
194
+ });
195
+ }
196
+ for (const call of toolCalls) {
197
+ this.ctx.emit("agent/tool-call", { index, call });
198
+ yield { type: "tool/start", index, call };
199
+ await session.append("tool-call", {
200
+ id: call.id,
201
+ name: call.name,
202
+ arguments: call.arguments
203
+ });
204
+ const toolOptions = { callId: call.id };
205
+ if (options.signal) toolOptions.signal = options.signal;
206
+ const startedAt = Date.now();
207
+ let result;
208
+ try {
209
+ result = await tools.execute(call.name, call.arguments, toolOptions);
210
+ } catch (error) {
211
+ result = {
212
+ ok: false,
213
+ name: call.name,
214
+ callId: call.id,
215
+ input: call.arguments,
216
+ error: toToolError(error),
217
+ startedAt,
218
+ durationMs: Date.now() - startedAt
219
+ };
220
+ }
221
+ toolResults.push(result);
222
+ const toolResultPayload = {
223
+ id: call.id,
224
+ toolCallId: call.id,
225
+ name: call.name,
226
+ ok: result.ok,
227
+ durationMs: result.durationMs
228
+ };
229
+ if (result.output !== void 0) toolResultPayload.output = result.output;
230
+ if (result.error) {
231
+ toolResultPayload.error = {
232
+ name: result.error.name,
233
+ message: result.error.message
234
+ };
235
+ if (result.error.stack) toolResultPayload.error.stack = result.error.stack;
236
+ }
237
+ await session.append("tool-result", toolResultPayload);
238
+ yield { type: "tool/end", index, call, result };
239
+ this.ctx.emit("agent/tool-result", { index, call, result });
240
+ }
241
+ if (options.signal?.aborted) {
242
+ finishReason = "cancelled";
243
+ break;
244
+ }
245
+ steps.push({
246
+ index,
247
+ input: stepInput,
248
+ completion,
249
+ toolResults
250
+ });
251
+ if (completion.content) {
252
+ output = completion.content;
253
+ }
254
+ if (!toolCalls.length) {
255
+ await session.append("message", { role: "assistant", content: completion.content ?? "" });
256
+ }
257
+ const nextMessages = this._extendMessages(messages, completion, toolResults);
258
+ if (toolCalls.length === 0) {
259
+ finishReason = completion.finishReason === "length" ? "length" : completion.finishReason === "error" ? "error" : "stop";
260
+ break;
261
+ }
262
+ if (index + 1 >= maxTurns && !finalTurnGranted) {
263
+ finalTurnGranted = true;
264
+ } else if (index + 1 >= maxTurns + (finalTurnGranted ? 1 : 0)) {
265
+ finishReason = "max_turns";
266
+ break;
267
+ }
268
+ finishReason = "tool_calls";
269
+ index += 1;
270
+ messages = nextMessages;
271
+ }
272
+ const runResult = {
273
+ input: claimed,
274
+ output,
275
+ finishReason,
276
+ steps,
277
+ messages: copyMessages(messages)
278
+ };
279
+ this.ctx.emit("agent/turn-end", {
280
+ input: claimed,
281
+ steps: copySteps(steps),
282
+ messages: copyMessages(messages),
283
+ output,
284
+ finishReason
285
+ });
286
+ this.ctx.emit("agent/end", {
287
+ input: claimed,
288
+ steps: copySteps(steps),
289
+ messages: copyMessages(messages),
290
+ output,
291
+ finishReason
292
+ });
293
+ await this.config.hooks?.afterRun?.(runResult, options);
294
+ yield { type: "run/end", run: runResult };
295
+ return runResult;
296
+ }
297
+ async _enforceContextBudget(session, budget, messages) {
298
+ const limit = budget.limit ?? DEFAULT_CONTEXT_LIMIT;
299
+ const compactRatio = budget.compactRatio ?? 0.9;
300
+ if (limit <= 0 || compactRatio <= 0 || compactRatio > 1) {
301
+ throw new AgentError("invalid context budget: limit must be positive and compactRatio must be in (0, 1]");
302
+ }
303
+ const usage = estimateContextUsage(messages, limit);
304
+ if (usage.ratio < compactRatio) return copyMessages(messages);
305
+ const keepTokens = budget.keepTokens ?? Math.max(1, Math.floor(limit * 0.5));
306
+ const compactMessages = budget.summarize ? await budget.summarize(messages, usage) : [{ role: "system", content: defaultContextSummary(messages, usage) }];
307
+ const summary = compactMessages.map((message) => `${message.role}: ${message.content}`).join("\n");
308
+ await session.compact({
309
+ keepTokens,
310
+ summary,
311
+ tokensBefore: usage.tokens,
312
+ messages: compactMessages.map((message) => copyMessages([message])[0])
313
+ });
314
+ this.ctx.emit("agent/context-compact", {
315
+ type: "agent/context-compact",
316
+ messagesBefore: messages.length,
317
+ tokensBefore: usage.tokens,
318
+ limit,
319
+ keepTokens,
320
+ messagesAfter: compactMessages.length
321
+ });
322
+ return compactMessages.map((message) => copyMessages([message])[0]);
323
+ }
324
+ _initialMessages(input) {
325
+ const systemPrompt = this.inbox.injected().get("agentSystem");
326
+ const systemMessage = typeof systemPrompt === "string" && systemPrompt ? [{ role: "system", content: systemPrompt }] : [];
327
+ if (input.messages?.length) {
328
+ const first = input.messages[0];
329
+ if (first?.role === "system") return copyMessages(input.messages);
330
+ return [...systemMessage, ...copyMessages(input.messages)];
331
+ }
332
+ if (input.text) return [...systemMessage, { role: "user", content: input.text }];
333
+ return systemMessage;
334
+ }
335
+ _extendMessages(messages, completion, toolResults) {
336
+ const next = copyMessages(messages);
337
+ const assistant = {
338
+ role: "assistant",
339
+ content: completion.content ?? ""
340
+ };
341
+ const toolCalls = completion.toolCalls ?? [];
342
+ if (toolCalls.length) {
343
+ assistant.tool_calls = toolCalls.map((call) => ({
344
+ id: call.id,
345
+ name: call.name,
346
+ arguments: call.arguments
347
+ }));
348
+ }
349
+ next.push(assistant);
350
+ for (const call of toolCalls) {
351
+ const result = toolResults.find((candidate) => candidate.callId === call.id);
352
+ const content = result ? result.ok ? stringify(result.output) : `error: ${result.error?.message ?? "unknown"}` : "error: missing tool result";
353
+ const message = {
354
+ role: "tool",
355
+ content,
356
+ tool_call_id: call.id
357
+ };
358
+ message.name = result?.name ?? call.name;
359
+ if (result && !result.ok) {
360
+ message.toolOk = false;
361
+ if (result.error) {
362
+ message.toolError = {
363
+ name: result.error.name,
364
+ message: result.error.message
365
+ };
366
+ }
367
+ }
368
+ next.push(message);
369
+ }
370
+ return next;
371
+ }
372
+ _session() {
373
+ const session = this.ctx.session;
374
+ if (!session) throw new AgentError("session service is required");
375
+ return session;
376
+ }
377
+ _tools() {
378
+ const tools = this.ctx.tools;
379
+ if (!tools) throw new AgentError("tools service is required");
380
+ return tools;
381
+ }
382
+ _llm() {
383
+ return this.config.llm;
384
+ }
385
+ };
386
+ function defaultContextSummary(messages, usage) {
387
+ const latest = messages.at(-1);
388
+ const latestText = latest ? `${latest.role}: ${latest.content}` : "none";
389
+ return [
390
+ "Earlier context was compacted.",
391
+ `Messages before compaction: ${messages.length}.`,
392
+ `Tokens before compaction: ${usage.tokens}.`,
393
+ `Latest message: ${latestText}`
394
+ ].join(" ");
395
+ }
396
+ function copySteps(steps) {
397
+ return steps.map((step) => ({
398
+ index: step.index,
399
+ input: copyMessages(step.input),
400
+ completion: copyCompletion(step.completion),
401
+ toolResults: step.toolResults.map((result) => ({ ...result }))
402
+ }));
403
+ }
404
+ function toToolError(error) {
405
+ if (error instanceof Error) {
406
+ const result = {
407
+ name: error.name,
408
+ message: error.message
409
+ };
410
+ if (error.stack) result.stack = error.stack;
411
+ return result;
412
+ }
413
+ return {
414
+ name: "ToolExecutionError",
415
+ message: String(error)
416
+ };
417
+ }
418
+ function completionFromStreamEvents(events) {
419
+ let content = "";
420
+ const calls = /* @__PURE__ */ new Map();
421
+ let finishReason = "error";
422
+ for (const event of events) {
423
+ if (event.type === "message_delta") {
424
+ content += event.delta;
425
+ } else if (event.type === "toolcall_end") {
426
+ calls.set(event.index, {
427
+ id: event.id,
428
+ name: event.name,
429
+ arguments: event.arguments
430
+ });
431
+ } else if (event.type === "message_stop") {
432
+ finishReason = event.finishReason;
433
+ }
434
+ }
435
+ const completion = { finishReason };
436
+ if (content) completion.content = content;
437
+ if (calls.size) completion.toolCalls = [...calls.values()];
438
+ return completion;
439
+ }
440
+ async function consumeAgentStream(stream) {
441
+ const iterator = stream[Symbol.asyncIterator]();
442
+ while (true) {
443
+ const next = await iterator.next();
444
+ if (next.done) return next.value;
445
+ }
446
+ }
447
+ var agent = {
448
+ name: "agent",
449
+ inject: ["session", "tools"],
450
+ apply: (ctx, config = {}) => {
451
+ const service = new AgentService(ctx, config);
452
+ ctx.provide("agent", service);
453
+ ctx.provide("agentLoop", (input, options) => service.run(input, options));
454
+ ctx.provide("inbox", service.inbox);
455
+ return () => {
456
+ };
457
+ }
458
+ };
459
+ var name = "@tnega/agent";
460
+
461
+ // packages/agent/src/definition.ts
462
+ function resolveSystemPrompt(ctx, system) {
463
+ if (!system) return void 0;
464
+ return typeof system === "function" ? system(ctx) : system;
465
+ }
466
+ function withSystemPrompt(input, system) {
467
+ if (!system) return input;
468
+ const messages = [
469
+ { role: "system", content: system },
470
+ ...input?.messages ?? []
471
+ ];
472
+ if (input?.text) messages.push({ role: "user", content: input.text });
473
+ return { ...input ?? {}, messages };
474
+ }
475
+ function defineAgent(definition) {
476
+ const name2 = definition.name.trim();
477
+ if (!name2) throw new TypeError("agent definition requires a non-empty name");
478
+ return {
479
+ name: `agent:${name2}`,
480
+ inject: ["session", "tools"],
481
+ apply: async (ctx, config = {}) => {
482
+ const dynamic = ctx;
483
+ const system = resolveSystemPrompt(ctx, definition.system);
484
+ let agentService;
485
+ if (definition.loop) {
486
+ const loop = async (input, options) => {
487
+ await definition.hooks?.beforeRun?.(input ?? {}, options ?? {});
488
+ const result = await definition.loop(
489
+ withSystemPrompt(input, system),
490
+ options
491
+ );
492
+ await definition.hooks?.afterRun?.(result, options ?? {});
493
+ return result;
494
+ };
495
+ ctx.provide("agentLoop", loop);
496
+ } else {
497
+ const agentConfig = {};
498
+ if (definition.hooks) agentConfig.hooks = definition.hooks;
499
+ if (config.llm) agentConfig.llm = config.llm;
500
+ if (config.maxTurns !== void 0) agentConfig.maxTurns = config.maxTurns;
501
+ if (config.maxSteps !== void 0) agentConfig.maxSteps = config.maxSteps;
502
+ if (config.inbox) agentConfig.inbox = config.inbox;
503
+ if (config.contextBudget) agentConfig.contextBudget = config.contextBudget;
504
+ const agentFiber = ctx.plugin(agent, agentConfig);
505
+ await agentFiber;
506
+ agentService = ctx.reflect.get("agent");
507
+ if (system) agentService.inbox.inject("agentSystem", system);
508
+ }
509
+ for (const tool of definition.tools ?? []) {
510
+ dynamic.tools.register(tool);
511
+ }
512
+ ctx.provide("agentDefinition", definition);
513
+ ctx.provide("agentSystem", system);
514
+ ctx.emit("agent/definition", {
515
+ name: name2,
516
+ version: definition.version,
517
+ system,
518
+ toolCount: (definition.tools ?? []).length
519
+ });
520
+ }
521
+ };
522
+ }
523
+ export {
524
+ AgentError,
525
+ AgentInbox,
526
+ AgentService,
527
+ agent,
528
+ defineAgent,
529
+ name
530
+ };
531
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../packages/session/src/index.ts", "../packages/agent/src/service.ts", "../packages/agent/src/definition.ts"],
4
+ "sourcesContent": ["import { randomUUID } from 'node:crypto'\nimport { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport type { Context } from '@tnega/core'\n\nexport type ModelRole = 'system' | 'user' | 'assistant' | 'tool'\n\nexport interface ModelToolCall {\n id: string\n name: string\n arguments: unknown\n}\n\nexport interface ModelMessage {\n role: ModelRole\n content: string\n name?: string\n tool_call_id?: string\n tool_calls?: ModelToolCall[]\n toolOk?: boolean\n toolError?: ToolResultErrorPayload\n}\n\nexport type MessageRole = 'system' | 'user' | 'assistant'\n\nexport interface MessagePayload {\n role: MessageRole\n content: string\n name?: string\n parentId?: string\n}\n\nexport interface ToolCallPayload {\n id: string\n name: string\n arguments: unknown\n}\n\nexport interface ToolResultErrorPayload {\n name?: string\n message: string\n stack?: string\n}\n\nexport interface ToolResultPayload {\n id: string\n toolCallId: string\n name: string\n ok: boolean\n durationMs?: number\n output?: unknown\n error?: ToolResultErrorPayload\n}\n\nexport interface CheckpointPayload {\n messages: ModelMessage[]\n summary?: string\n tokensBefore?: number\n snapshot?: SessionEvent[]\n}\n\nexport type SessionEventType =\n | 'message'\n | 'tool-call'\n | 'tool-result'\n | 'checkpoint'\n | 'meta'\n\nexport interface SessionEventBase<T extends SessionEventType, P> {\n id: string\n seq: number\n ts: number\n type: T\n payload: P\n}\n\nexport type SessionEvent =\n | SessionEventBase<'message', MessagePayload>\n | SessionEventBase<'tool-call', ToolCallPayload>\n | SessionEventBase<'tool-result', ToolResultPayload>\n | SessionEventBase<'checkpoint', CheckpointPayload>\n | SessionEventBase<'meta', Record<string, unknown>>\n\nexport interface SessionConfig {\n file: string\n projector?: SessionProjector\n}\n\nexport interface CompactOptions {\n keep?: number\n keepTokens?: number\n summary?: string\n tokensBefore?: number\n messages?: ModelMessage[]\n}\n\nexport type ReplayReducer<T> = (state: T, event: SessionEvent) => T | Promise<T>\n\nexport type SessionProjector = (events: readonly SessionEvent[]) => ModelMessage[]\n\nexport interface ContextUsage {\n tokens: number\n limit: number\n ratio: number\n}\n\nexport const DEFAULT_CONTEXT_LIMIT = 128_000\n\nfunction isSessionEvent(value: unknown): value is SessionEvent {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Record<string, unknown>\n return typeof record.id === 'string'\n && typeof record.seq === 'number'\n && typeof record.ts === 'number'\n && typeof record.type === 'string'\n && 'payload' in record\n}\n\nfunction clone<T>(value: T): T {\n return structuredClone(value)\n}\n\nexport function projectEvents(events: readonly SessionEvent[]): ModelMessage[] {\n const messages: ModelMessage[] = []\n for (const event of events) {\n switch (event.type) {\n case 'checkpoint':\n messages.push(...clone(event.payload.messages))\n break\n case 'message': {\n const message: ModelMessage = {\n role: event.payload.role,\n content: event.payload.content,\n }\n if (event.payload.name) message.name = event.payload.name\n messages.push(message)\n break\n }\n case 'tool-call': {\n const last = messages.at(-1)\n if (!last || last.role !== 'assistant') {\n messages.push({\n role: 'assistant',\n content: '',\n tool_calls: [],\n })\n } else if (!last.tool_calls) {\n last.tool_calls = []\n }\n messages.at(-1)!.tool_calls!.push({\n id: event.payload.id,\n name: event.payload.name,\n arguments: event.payload.arguments,\n })\n break\n }\n case 'tool-result': {\n const failed = !event.payload.ok\n const content = failed\n ? `error: ${event.payload.error?.message ?? 'unknown'}`\n : stringify(event.payload.output)\n const message: ModelMessage = {\n role: 'tool',\n content,\n tool_call_id: event.payload.toolCallId,\n }\n message.name = event.payload.name\n if (failed) {\n message.toolOk = false\n if (event.payload.error) message.toolError = event.payload.error\n }\n messages.push(message)\n break\n }\n case 'meta':\n break\n }\n }\n return messages\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\nexport function estimateMessageTokens(messages: readonly ModelMessage[]): number {\n let tokens = 0\n for (const message of messages) {\n tokens += Math.ceil(message.content.length / 4)\n for (const call of message.tool_calls ?? []) {\n const raw = JSON.stringify(call.arguments ?? {}) ?? ''\n tokens += Math.ceil(raw.length / 4)\n }\n }\n return tokens\n}\n\nexport function estimateEventTokens(event: SessionEvent): number {\n switch (event.type) {\n case 'message':\n return Math.ceil(event.payload.content.length / 4)\n case 'tool-call': {\n const raw = JSON.stringify(event.payload.arguments ?? {}) ?? ''\n return Math.ceil(raw.length / 4)\n }\n case 'tool-result': {\n const raw = event.payload.ok\n ? stringify(event.payload.output)\n : event.payload.error?.message ?? 'error'\n return Math.ceil(raw.length / 4)\n }\n case 'checkpoint':\n return estimateMessageTokens(event.payload.messages)\n case 'meta':\n return 0\n }\n}\n\nexport function suffixStartIndexForTokens(\n events: readonly SessionEvent[],\n targetTokens: number,\n): number {\n if (!events.length || targetTokens <= 0) return 0\n let tokens = 0\n let candidate = events.length\n for (let index = events.length - 1; index >= 0; index -= 1) {\n tokens += estimateEventTokens(events[index]!)\n if (tokens >= targetTokens) {\n candidate = index\n break\n }\n }\n if (candidate === events.length) return 0\n let cut = candidate\n while (cut < events.length) {\n const event = events[cut]\n if (event && event.type === 'message' && event.payload.role === 'user') return cut\n cut += 1\n }\n return candidate\n}\n\nexport function resolveCompactKeep(\n events: readonly SessionEvent[],\n options: CompactOptions,\n): number {\n if (\n typeof options.keepTokens === 'number'\n && Number.isFinite(options.keepTokens)\n && options.keepTokens > 0\n ) {\n return events.length - suffixStartIndexForTokens(events, options.keepTokens)\n }\n const keep = typeof options.keep === 'number' && Number.isFinite(options.keep) && options.keep > 0\n ? Math.floor(options.keep)\n : 0\n return Math.min(keep, events.length)\n}\n\nexport function estimateContextUsage(\n messages: readonly ModelMessage[],\n limit = DEFAULT_CONTEXT_LIMIT,\n): ContextUsage {\n const tokens = estimateMessageTokens(messages)\n return {\n tokens,\n limit,\n ratio: limit > 0 ? tokens / limit : 0,\n }\n}\n\nexport class SessionLog {\n private _events: SessionEvent[] = []\n private _loaded = false\n private _nextSeq = 1\n private _queue: Promise<unknown> = Promise.resolve()\n\n constructor(\n readonly file: string,\n private _projector: SessionProjector = projectEvents,\n ) {}\n\n init(): Promise<void> {\n return this._run(async () => {\n await this._ensureLoaded()\n })\n }\n\n append(type: 'message', payload: MessagePayload): Promise<SessionEvent>\n append(type: 'tool-call', payload: ToolCallPayload): Promise<SessionEvent>\n append(type: 'tool-result', payload: ToolResultPayload): Promise<SessionEvent>\n append(type: 'checkpoint', payload: CheckpointPayload): Promise<SessionEvent>\n append(type: 'meta', payload: Record<string, unknown>): Promise<SessionEvent>\n append(type: SessionEventType, payload: SessionEvent['payload']): Promise<SessionEvent> {\n return this._run(async () => {\n await this._ensureLoaded()\n const eventPayload = clone(payload)\n if (type === 'message') {\n for (let index = this._events.length - 1; index >= 0; index -= 1) {\n const previous = this._events[index]\n if (previous?.type === 'message') {\n const messagePayload = eventPayload as MessagePayload\n messagePayload.parentId ??= previous.id\n break\n }\n }\n }\n const event = {\n id: randomUUID(),\n seq: this._nextSeq,\n ts: Date.now(),\n type: type as SessionEvent['type'],\n payload: eventPayload,\n } as SessionEvent\n await appendFile(this.file, `${JSON.stringify(event)}\\n`, 'utf8')\n this._events.push(event)\n this._nextSeq += 1\n return event\n })\n }\n\n async lineage(messageId: string): Promise<SessionEvent[]> {\n return this._run(async () => {\n await this._ensureLoaded()\n return this._resolveLineage(messageId)\n })\n }\n\n async forkAt(messageId: string): Promise<SessionEvent[]> {\n return this._run(async () => {\n await this._ensureLoaded()\n const lineage = this._resolveLineage(messageId)\n const lineageIds = new Set(lineage.map(event => event.id))\n const targetIndex = this._events.findIndex(\n event => event.id === messageId && event.type === 'message',\n )\n if (targetIndex < 0) {\n throw new Error(`message not found: ${messageId}`)\n }\n const selected: SessionEvent[] = []\n let skippedMessage = false\n for (let index = 0; index <= targetIndex; index += 1) {\n const event = this._events[index]!\n if (event.type === 'message') {\n if (!lineageIds.has(event.id)) {\n skippedMessage = true\n continue\n }\n skippedMessage = false\n selected.push(clone(event))\n continue\n }\n if (event.type === 'meta') continue\n if (event.type === 'checkpoint') {\n selected.push(clone(event))\n continue\n }\n if (!skippedMessage) {\n selected.push(clone(event))\n }\n }\n return selected\n })\n }\n\n read(): Promise<SessionEvent[]> {\n return this._run(async () => {\n await this._ensureLoaded()\n return this._events.map(event => clone(event))\n })\n }\n\n deriveMessages(): Promise<ModelMessage[]> {\n return this._run(async () => {\n await this._ensureLoaded()\n return clone(this._projector(this._events))\n })\n }\n\n estimateContext(limit = DEFAULT_CONTEXT_LIMIT): Promise<ContextUsage> {\n return this._run(async () => {\n await this._ensureLoaded()\n return estimateContextUsage(this._projector(this._events), limit)\n })\n }\n\n replay(): Promise<SessionEvent[]>\n replay<T>(reduce: ReplayReducer<T>, initial: T): Promise<T>\n replay<T>(reduce?: ReplayReducer<T>, initial?: T): Promise<SessionEvent[] | T> {\n return this.read().then((events) => {\n if (!reduce) return events\n let state = initial as T\n let pending: Promise<void> = Promise.resolve()\n for (const event of events) {\n pending = pending.then(async () => {\n state = await reduce(state, event)\n })\n }\n return pending.then(() => state)\n })\n }\n\n compact(options: CompactOptions = {}): Promise<number> {\n return this._run(async () => {\n await this._ensureLoaded()\n const keep = resolveCompactKeep(this._events, options)\n const split = this._events.length - keep\n const prefix = this._events.slice(0, split)\n const suffix = this._events.slice(split)\n const checkpoint: SessionEvent = {\n id: randomUUID(),\n seq: this._events.at(-1)?.seq ?? 0,\n ts: Date.now(),\n type: 'checkpoint',\n payload: {\n messages: options.messages\n ? clone(options.messages)\n : this._projector(prefix),\n ...(options.summary ? { summary: options.summary } : {}),\n ...(options.tokensBefore !== undefined\n ? { tokensBefore: options.tokensBefore }\n : {}),\n ...(prefix.length ? { snapshot: prefix } : {}),\n },\n }\n const next = [checkpoint, ...suffix]\n if (next.length) {\n await writeFile(this.file, `${next.map(event => JSON.stringify(event)).join('\\n')}\\n`, 'utf8')\n } else {\n await writeFile(this.file, '', 'utf8')\n }\n this._events = next\n return next.length\n })\n }\n\n close(): Promise<void> {\n return this._queue.then(() => undefined)\n }\n\n private _run<T>(task: () => Promise<T>): Promise<T> {\n const next = this._queue.then(task, task)\n this._queue = next.then(() => undefined, () => undefined)\n return next\n }\n\n private async _ensureLoaded(): Promise<void> {\n if (this._loaded) return\n await mkdir(dirname(resolve(this.file)), { recursive: true })\n this._events = await this._read()\n this._nextSeq = (this._events.at(-1)?.seq ?? 0) + 1\n this._loaded = true\n }\n\n private async _read(): Promise<SessionEvent[]> {\n try {\n const text = await readFile(this.file, 'utf8')\n const events: SessionEvent[] = []\n for (const line of text.split('\\n')) {\n if (!line.trim()) continue\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch {\n continue\n }\n if (isSessionEvent(parsed)) events.push(parsed)\n }\n return events\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return []\n throw error\n }\n }\n\n private _resolveLineage(messageId: string): SessionEvent[] {\n const messages = this._events.filter(\n (event): event is Extract<SessionEvent, { type: 'message' }> => event.type === 'message',\n )\n const byId = new Map<string, Extract<SessionEvent, { type: 'message' }>>(\n messages.map(event => [event.id, event] as const),\n )\n if (!byId.has(messageId)) {\n throw new Error(`message not found: ${messageId}`)\n }\n const chain: SessionEvent[] = []\n const seen = new Set<string>()\n let cursorId: string | undefined = messageId\n while (cursorId && byId.has(cursorId) && !seen.has(cursorId)) {\n seen.add(cursorId)\n const event: Extract<SessionEvent, { type: 'message' }> = byId.get(cursorId)!\n chain.unshift(clone(event))\n const parentId: string | undefined = event.payload.parentId\n if (parentId && byId.has(parentId)) {\n cursorId = parentId\n continue\n }\n const index = messages.findIndex(message => message.id === cursorId)\n cursorId = index > 0 ? messages[index - 1]!.id : undefined\n }\n return chain\n }\n}\n\nexport const session = {\n name: 'session',\n apply: async (ctx: Context, config: SessionConfig) => {\n const log = new SessionLog(config.file, config.projector)\n await log.init()\n ctx.provide('session', log)\n return () => log.close()\n },\n}\n\nexport const name = '@tnega/session'\n", "import type { Context } from '@tnega/core'\nimport {\n DEFAULT_CONTEXT_LIMIT,\n estimateContextUsage,\n type ModelMessage,\n type SessionLog,\n type ToolResultPayload,\n} from '@tnega/session'\nimport type { ToolError, ToolResult } from '@tnega/tools'\nimport type { ToolsService } from '@tnega/tools'\n\nimport type {\n AgentContextBudget,\n AgentFinishReason,\n AgentHooks,\n AgentInput,\n AgentRunOptions,\n AgentRunResult,\n AgentStep,\n AgentStreamEvent,\n CompleteOptions,\n LLMAdapter,\n LLMCompletion,\n LLMStreamEvent,\n LLMToolCall,\n} from './types.js'\n\nexport class AgentError extends Error {\n override name = 'AgentError'\n}\n\nexport class AgentInbox {\n private _queue: AgentInput[] = []\n private _injected = new Map<string, unknown>()\n\n get size(): number {\n return this._queue.length\n }\n\n push(input: AgentInput): AgentInput {\n this._queue.push(input)\n return input\n }\n\n claim(): AgentInput | undefined {\n return this._queue.shift()\n }\n\n peek(): AgentInput | undefined {\n return this._queue[0]\n }\n\n inject(key: string, value: unknown): void {\n this._injected.set(key, value)\n }\n\n injected(): ReadonlyMap<string, unknown> {\n return new Map(this._injected)\n }\n}\n\nexport interface AgentConfig {\n llm?: LLMAdapter\n maxTurns?: number\n maxSteps?: number\n inbox?: AgentInbox\n hooks?: AgentHooks\n contextBudget?: AgentContextBudget\n}\n\nfunction copyMessages(messages: readonly ModelMessage[]): ModelMessage[] {\n return messages.map((message) => {\n const copy: ModelMessage = {\n role: message.role,\n content: message.content,\n }\n if (message.name) copy.name = message.name\n if (message.tool_call_id) copy.tool_call_id = message.tool_call_id\n if (message.toolOk !== undefined) copy.toolOk = message.toolOk\n if (message.toolError) copy.toolError = { ...message.toolError }\n if (message.tool_calls) {\n copy.tool_calls = message.tool_calls.map(call => ({\n id: call.id,\n name: call.name,\n arguments: call.arguments,\n }))\n }\n return copy\n })\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\nfunction copyCompletion(completion: LLMCompletion): LLMCompletion {\n const copy: LLMCompletion = {\n finishReason: completion.finishReason,\n }\n if (completion.content !== undefined) copy.content = completion.content\n if (completion.toolCalls) {\n copy.toolCalls = completion.toolCalls.map(call => ({\n id: call.id,\n name: call.name,\n arguments: call.arguments,\n }))\n }\n return copy\n}\n\nexport class AgentService {\n readonly inbox: AgentInbox\n\n constructor(\n private ctx: Context,\n private config: AgentConfig = {},\n ) {\n this.inbox = config.inbox ?? new AgentInbox()\n }\n\n async run(input?: AgentInput, options: AgentRunOptions = {}): Promise<AgentRunResult> {\n return consumeAgentStream(this._stream(input, options, false))\n }\n\n async *runStream(\n input?: AgentInput,\n options: AgentRunOptions = {},\n ): AsyncGenerator<AgentStreamEvent, AgentRunResult, void> {\n const iterator = this._stream(input, options)[Symbol.asyncIterator]()\n while (true) {\n const next = await iterator.next()\n if (next.done) return next.value\n yield next.value\n }\n }\n\n private async *_stream(\n input?: AgentInput,\n options: AgentRunOptions = {},\n useStream = true,\n ): AsyncGenerator<AgentStreamEvent, AgentRunResult, void> {\n const claimed = input ?? this.inbox.claim()\n if (!claimed) throw new AgentError('no agent input available')\n await this.config.hooks?.beforeRun?.(claimed, options)\n\n const session = this._session()\n const tools = this._tools()\n const llm = this._llm()\n if (!llm) throw new AgentError('no LLM adapter available')\n\n const maxTurns = options.maxTurns ?? this.config.maxTurns ?? 64\n const maxSteps = options.maxSteps ?? this.config.maxSteps ?? 64\n const contextBudget = options.contextBudget ?? this.config.contextBudget\n const injected = this.inbox.injected()\n this.ctx.emit('agent/start', { input: claimed, options, injected })\n\n let messages = this._initialMessages(claimed)\n const systemPrompt = this.inbox.injected().get('agentSystem')\n if (typeof systemPrompt === 'string' && systemPrompt) {\n await session.append('message', { role: 'system', content: systemPrompt })\n }\n if (claimed.text) {\n await session.append('message', { role: 'user', content: claimed.text })\n }\n\n const steps: AgentStep[] = []\n let output = ''\n let finishReason: AgentFinishReason = 'stop'\n\n this.ctx.emit('agent/turn-start', {\n input: claimed,\n messages: copyMessages(messages),\n injected,\n })\n\n let index = 0\n let finalTurnGranted = false\n while (index < maxTurns + (finalTurnGranted ? 1 : 0)) {\n if (steps.length >= maxSteps) {\n finishReason = 'max_steps'\n break\n }\n if (contextBudget) {\n messages = await this._enforceContextBudget(session, contextBudget, messages)\n }\n\n const stepInput = copyMessages(messages)\n this.ctx.emit('agent/step', { index, input: copyMessages(stepInput) })\n const availableTools = finalTurnGranted ? [] : tools.list()\n const completeOptions: CompleteOptions = {\n maxSteps: maxSteps - steps.length,\n }\n if (options.signal) completeOptions.signal = options.signal\n\n let completion: LLMCompletion\n const streamMethod = useStream ? llm.stream : undefined\n if (streamMethod) {\n const streamEvents: LLMStreamEvent[] = []\n let cancelled = false\n try {\n for await (const event of streamMethod(stepInput, availableTools, completeOptions)) {\n streamEvents.push(event)\n yield event\n }\n } catch (error) {\n if (!options.signal?.aborted) throw error\n finishReason = 'cancelled'\n cancelled = true\n }\n if (cancelled) break\n completion = completionFromStreamEvents(streamEvents)\n } else {\n try {\n completion = await llm.complete(stepInput, availableTools, completeOptions)\n } catch (error) {\n if (!options.signal?.aborted) throw error\n finishReason = 'cancelled'\n break\n }\n }\n\n const toolCalls = completion.toolCalls ?? []\n if (finalTurnGranted && toolCalls.length) {\n finishReason = 'max_turns'\n break\n }\n const toolResults: ToolResult[] = []\n if (toolCalls.length) {\n await session.append('message', {\n role: 'assistant',\n content: completion.content ?? '',\n })\n }\n for (const call of toolCalls) {\n this.ctx.emit('agent/tool-call', { index, call })\n yield { type: 'tool/start', index, call }\n await session.append('tool-call', {\n id: call.id,\n name: call.name,\n arguments: call.arguments,\n })\n const toolOptions: { callId: string; signal?: AbortSignal } = { callId: call.id }\n if (options.signal) toolOptions.signal = options.signal\n const startedAt = Date.now()\n let result: ToolResult\n try {\n result = await tools.execute(call.name, call.arguments, toolOptions)\n } catch (error) {\n result = {\n ok: false,\n name: call.name,\n callId: call.id,\n input: call.arguments,\n error: toToolError(error),\n startedAt,\n durationMs: Date.now() - startedAt,\n }\n }\n toolResults.push(result)\n const toolResultPayload: ToolResultPayload = {\n id: call.id,\n toolCallId: call.id,\n name: call.name,\n ok: result.ok,\n durationMs: result.durationMs,\n }\n if (result.output !== undefined) toolResultPayload.output = result.output\n if (result.error) {\n toolResultPayload.error = {\n name: result.error.name,\n message: result.error.message,\n }\n if (result.error.stack) toolResultPayload.error.stack = result.error.stack\n }\n await session.append('tool-result', toolResultPayload)\n yield { type: 'tool/end', index, call, result }\n this.ctx.emit('agent/tool-result', { index, call, result })\n }\n if (options.signal?.aborted) {\n finishReason = 'cancelled'\n break\n }\n\n steps.push({\n index,\n input: stepInput,\n completion,\n toolResults,\n })\n\n if (completion.content) {\n output = completion.content\n }\n if (!toolCalls.length) {\n await session.append('message', { role: 'assistant', content: completion.content ?? '' })\n }\n\n const nextMessages = this._extendMessages(messages, completion, toolResults)\n if (toolCalls.length === 0) {\n finishReason = completion.finishReason === 'length'\n ? 'length'\n : completion.finishReason === 'error'\n ? 'error'\n : 'stop'\n break\n }\n if (index + 1 >= maxTurns && !finalTurnGranted) {\n finalTurnGranted = true\n } else if (index + 1 >= maxTurns + (finalTurnGranted ? 1 : 0)) {\n finishReason = 'max_turns'\n break\n }\n finishReason = 'tool_calls'\n index += 1\n messages = nextMessages\n }\n\n const runResult: AgentRunResult = {\n input: claimed,\n output,\n finishReason,\n steps,\n messages: copyMessages(messages),\n }\n this.ctx.emit('agent/turn-end', {\n input: claimed,\n steps: copySteps(steps),\n messages: copyMessages(messages),\n output,\n finishReason,\n })\n this.ctx.emit('agent/end', {\n input: claimed,\n steps: copySteps(steps),\n messages: copyMessages(messages),\n output,\n finishReason,\n })\n await this.config.hooks?.afterRun?.(runResult, options)\n\n yield { type: 'run/end', run: runResult }\n return runResult\n }\n\n private async _enforceContextBudget(\n session: SessionLog,\n budget: AgentContextBudget,\n messages: readonly ModelMessage[],\n ): Promise<ModelMessage[]> {\n const limit = budget.limit ?? DEFAULT_CONTEXT_LIMIT\n const compactRatio = budget.compactRatio ?? 0.9\n if (limit <= 0 || compactRatio <= 0 || compactRatio > 1) {\n throw new AgentError('invalid context budget: limit must be positive and compactRatio must be in (0, 1]')\n }\n const usage = estimateContextUsage(messages, limit)\n if (usage.ratio < compactRatio) return copyMessages(messages)\n const keepTokens = budget.keepTokens ?? Math.max(1, Math.floor(limit * 0.5))\n const compactMessages = budget.summarize\n ? await budget.summarize(messages, usage)\n : [{ role: 'system' as const, content: defaultContextSummary(messages, usage) }]\n const summary = compactMessages\n .map(message => `${message.role}: ${message.content}`)\n .join('\\n')\n await session.compact({\n keepTokens,\n summary,\n tokensBefore: usage.tokens,\n messages: compactMessages.map(message => copyMessages([message])[0]!),\n })\n this.ctx.emit('agent/context-compact', {\n type: 'agent/context-compact',\n messagesBefore: messages.length,\n tokensBefore: usage.tokens,\n limit,\n keepTokens,\n messagesAfter: compactMessages.length,\n })\n return compactMessages.map(message => copyMessages([message])[0]!)\n }\n\n private _initialMessages(input: AgentInput): ModelMessage[] {\n const systemPrompt = this.inbox.injected().get('agentSystem')\n const systemMessage = typeof systemPrompt === 'string' && systemPrompt\n ? [{ role: 'system' as const, content: systemPrompt }]\n : []\n if (input.messages?.length) {\n const first = input.messages[0]\n if (first?.role === 'system') return copyMessages(input.messages)\n return [...systemMessage, ...copyMessages(input.messages)]\n }\n if (input.text) return [...systemMessage, { role: 'user', content: input.text }]\n return systemMessage\n }\n\n private _extendMessages(\n messages: readonly ModelMessage[],\n completion: LLMCompletion,\n toolResults: readonly ToolResult[],\n ): ModelMessage[] {\n const next = copyMessages(messages)\n const assistant: ModelMessage = {\n role: 'assistant',\n content: completion.content ?? '',\n }\n const toolCalls = completion.toolCalls ?? []\n if (toolCalls.length) {\n assistant.tool_calls = toolCalls.map(call => ({\n id: call.id,\n name: call.name,\n arguments: call.arguments,\n }))\n }\n next.push(assistant)\n\n for (const call of toolCalls) {\n const result = toolResults.find(candidate => candidate.callId === call.id)\n const content = result\n ? result.ok\n ? stringify(result.output)\n : `error: ${result.error?.message ?? 'unknown'}`\n : 'error: missing tool result'\n const message: ModelMessage = {\n role: 'tool',\n content,\n tool_call_id: call.id,\n }\n message.name = result?.name ?? call.name\n if (result && !result.ok) {\n message.toolOk = false\n if (result.error) {\n message.toolError = {\n name: result.error.name,\n message: result.error.message,\n }\n }\n }\n next.push(message)\n }\n return next\n }\n\n private _session(): SessionLog {\n const session = (this.ctx as unknown as { session?: SessionLog }).session\n if (!session) throw new AgentError('session service is required')\n return session\n }\n\n private _tools(): ToolsService {\n const tools = (this.ctx as unknown as { tools?: ToolsService }).tools\n if (!tools) throw new AgentError('tools service is required')\n return tools\n }\n\n private _llm(): LLMAdapter | undefined {\n return this.config.llm\n }\n}\n\nfunction defaultContextSummary(\n messages: readonly ModelMessage[],\n usage: { tokens: number },\n): string {\n const latest = messages.at(-1)\n const latestText = latest ? `${latest.role}: ${latest.content}` : 'none'\n return [\n 'Earlier context was compacted.',\n `Messages before compaction: ${messages.length}.`,\n `Tokens before compaction: ${usage.tokens}.`,\n `Latest message: ${latestText}`,\n ].join(' ')\n}\n\nfunction copySteps(steps: readonly AgentStep[]): readonly AgentStep[] {\n return steps.map(step => ({\n index: step.index,\n input: copyMessages(step.input),\n completion: copyCompletion(step.completion),\n toolResults: step.toolResults.map(result => ({ ...result })),\n }))\n}\n\nfunction toToolError(error: unknown): ToolError {\n if (error instanceof Error) {\n const result: ToolError = {\n name: error.name,\n message: error.message,\n }\n if (error.stack) result.stack = error.stack\n return result\n }\n return {\n name: 'ToolExecutionError',\n message: String(error),\n }\n}\n\nfunction completionFromStreamEvents(events: readonly LLMStreamEvent[]): LLMCompletion {\n let content = ''\n const calls = new Map<number, LLMToolCall>()\n let finishReason: AgentFinishReason = 'error'\n for (const event of events) {\n if (event.type === 'message_delta') {\n content += event.delta\n } else if (event.type === 'toolcall_end') {\n calls.set(event.index, {\n id: event.id,\n name: event.name,\n arguments: event.arguments,\n })\n } else if (event.type === 'message_stop') {\n finishReason = event.finishReason\n }\n }\n const completion: LLMCompletion = { finishReason }\n if (content) completion.content = content\n if (calls.size) completion.toolCalls = [...calls.values()]\n return completion\n}\n\nasync function consumeAgentStream(\n stream: AsyncGenerator<AgentStreamEvent, AgentRunResult, void>,\n): Promise<AgentRunResult> {\n const iterator = stream[Symbol.asyncIterator]()\n while (true) {\n const next = await iterator.next()\n if (next.done) return next.value\n }\n}\n\nexport const agent = {\n name: 'agent',\n inject: ['session', 'tools'],\n apply: (ctx: Context, config: AgentConfig = {}) => {\n const service = new AgentService(ctx, config)\n ctx.provide('agent', service)\n ctx.provide('agentLoop', (input?: AgentInput, options?: AgentRunOptions) => service.run(input, options))\n ctx.provide('inbox', service.inbox)\n return () => {}\n },\n}\n\nexport const name = '@tnega/agent'\n", "import type { Context, Plugin } from '@tnega/core'\nimport type { ModelMessage } from '@tnega/session'\nimport type { ToolDefinition } from '@tnega/tools'\n\nimport { agent, AgentService, type AgentConfig } from './service.js'\nimport type { AgentHooks, AgentInput, AgentLoop } from './types.js'\n\nexport type AgentDefinitionHooks = AgentHooks\n\nexport interface AgentDefinition {\n name: string\n version?: string\n system?: string | ((ctx: Context) => string)\n tools?: readonly ToolDefinition[]\n loop?: AgentLoop\n hooks?: AgentDefinitionHooks\n}\n\nexport interface DefineAgentConfig extends Partial<\n Pick<AgentConfig, 'llm' | 'maxTurns' | 'maxSteps' | 'inbox' | 'contextBudget'>\n> {\n [key: string]: unknown\n}\n\nfunction resolveSystemPrompt(\n ctx: Context,\n system: string | ((ctx: Context) => string) | undefined,\n): string | undefined {\n if (!system) return undefined\n return typeof system === 'function' ? system(ctx) : system\n}\n\nfunction withSystemPrompt(\n input: AgentInput | undefined,\n system: string | undefined,\n): AgentInput | undefined {\n if (!system) return input\n const messages: ModelMessage[] = [\n { role: 'system', content: system },\n ...(input?.messages ?? []),\n ]\n if (input?.text) messages.push({ role: 'user', content: input.text })\n return { ...(input ?? {}), messages }\n}\n\nexport function defineAgent(\n definition: AgentDefinition,\n): Plugin {\n const name = definition.name.trim()\n if (!name) throw new TypeError('agent definition requires a non-empty name')\n\n return {\n name: `agent:${name}`,\n inject: ['session', 'tools'],\n apply: async (ctx: Context, config: DefineAgentConfig = {}) => {\n const dynamic = ctx as unknown as {\n tools: { register(tool: ToolDefinition): () => void }\n }\n const system = resolveSystemPrompt(ctx, definition.system)\n let agentService: AgentService | undefined\n\n if (definition.loop) {\n const loop: AgentLoop = async (input, options) => {\n await definition.hooks?.beforeRun?.(input ?? {}, options ?? {})\n const result = await definition.loop!(\n withSystemPrompt(input, system),\n options,\n )\n await definition.hooks?.afterRun?.(result, options ?? {})\n return result\n }\n ctx.provide('agentLoop', loop)\n } else {\n const agentConfig: AgentConfig = {}\n if (definition.hooks) agentConfig.hooks = definition.hooks\n if (config.llm) agentConfig.llm = config.llm\n if (config.maxTurns !== undefined) agentConfig.maxTurns = config.maxTurns\n if (config.maxSteps !== undefined) agentConfig.maxSteps = config.maxSteps\n if (config.inbox) agentConfig.inbox = config.inbox\n if (config.contextBudget) agentConfig.contextBudget = config.contextBudget\n const agentFiber = ctx.plugin(agent, agentConfig)\n await agentFiber\n agentService = ctx.reflect.get('agent') as AgentService\n if (system) agentService.inbox.inject('agentSystem', system)\n }\n\n for (const tool of definition.tools ?? []) {\n dynamic.tools.register(tool)\n }\n\n ctx.provide('agentDefinition', definition)\n ctx.provide('agentSystem', system)\n ctx.emit('agent/definition', {\n name,\n version: definition.version,\n system,\n toolCount: (definition.tools ?? []).length,\n })\n },\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["name"]
7
+ }