@schlenkr/ragents 0.1.6 → 0.1.8

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 (150) hide show
  1. package/apps/server/src/chat-handler.ts +2 -0
  2. package/apps/server/src/config.ts +6 -0
  3. package/apps/server/src/host-api.json +1 -0
  4. package/apps/server/src/layout.ts +0 -15
  5. package/apps/server/src/plugin-support/agent-tool.ts +2 -3
  6. package/apps/server/src/plugin-support/plugin-folder.ts +2 -1
  7. package/apps/server/src/provider.ts +34 -11
  8. package/apps/server/src/ragents/actor-chat-history.ts +1 -0
  9. package/apps/server/src/ragents/engine.ts +23 -24
  10. package/apps/server/src/ragents/journal-chat-events.ts +2 -0
  11. package/apps/server/src/ragents/run-owner.ts +3 -2
  12. package/apps/server/src/ragents/session.ts +3 -3
  13. package/apps/server/src/run-preparation.ts +14 -18
  14. package/apps/server/src/run-transfer.ts +65 -4
  15. package/apps/server/src/settings.ts +2 -4
  16. package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-B9qYBARS.js → highlighted-body-KPVGNVTW-xXXhTDbh.js} +1 -1
  17. package/apps/web/dist/assets/{main-BCjvD2Hh.js → main-C7JeZFjs.js} +1 -1
  18. package/apps/web/dist/assets/{mermaid-HWGCJPDP-CvYYFK_n.js → mermaid-HWGCJPDP-DfsU5ofC.js} +69 -69
  19. package/apps/web/dist/assets/{runPanel-CG7kRMJh.js → runPanel-ZT6TPDLM.js} +1 -1
  20. package/apps/web/dist/help/guide-clients.html +13 -4
  21. package/apps/web/dist/help/guide-clients.md +14 -4
  22. package/apps/web/dist/help/guide-distributed.html +8 -3
  23. package/apps/web/dist/help/guide-distributed.md +8 -3
  24. package/apps/web/dist/help/guide-runtime.html +18 -12
  25. package/apps/web/dist/help/guide-runtime.md +19 -12
  26. package/apps/web/dist/help/mini-app.css +23 -3
  27. package/apps/web/dist/host-web.json +4 -4
  28. package/apps/web/dist/index.html +2 -2
  29. package/apps/web/dist/run-panel.html +2 -2
  30. package/apps/web/src/SessionList.tsx +16 -8
  31. package/apps/web/src/StartTiles.tsx +1 -1
  32. package/apps/web/src/api.ts +2 -0
  33. package/apps/web/src/panel/PanelPage.tsx +1 -1
  34. package/apps/web/src/panel/RunLine.tsx +4 -2
  35. package/apps/web/src/panel/contract.ts +2 -0
  36. package/bundles/ragents.activity/ragents-bundle.json +1 -1
  37. package/bundles/ragents.actor-programs/ragents-bundle.json +1 -1
  38. package/bundles/ragents.ask/ragents-bundle.json +1 -1
  39. package/bundles/ragents.browser/ragents-bundle.json +1 -1
  40. package/bundles/ragents.documents/ragents-bundle.json +1 -1
  41. package/bundles/ragents.lsp-fsharp/ragents-bundle.json +1 -1
  42. package/bundles/ragents.lsp-roslyn/ragents-bundle.json +1 -1
  43. package/bundles/ragents.lsp-typescript/ragents-bundle.json +1 -1
  44. package/bundles/ragents.model-relay/ragents-bundle.json +1 -1
  45. package/bundles/ragents.orchestration/ragents-bundle.json +1 -1
  46. package/bundles/ragents.overseer/ragents-bundle.json +1 -1
  47. package/bundles/ragents.processes/ragents-bundle.json +1 -1
  48. package/bundles/ragents.product/ragents-bundle.json +1 -1
  49. package/bundles/ragents.profile-distribution/ragents-bundle.json +1 -1
  50. package/bundles/ragents.reference/ragents-bundle.json +2 -2
  51. package/bundles/ragents.reference/run-scripts/learning-afternoon/tests/program.test.ts +1 -1
  52. package/bundles/ragents.reference/run-scripts/word-game/tests/program.test.ts +3 -3
  53. package/bundles/ragents.todo/ragents-bundle.json +1 -1
  54. package/bundles/ragents.transcript/ragents-bundle.json +1 -1
  55. package/bundles/ragents.watch/ragents-bundle.json +1 -1
  56. package/bundles/ragents.workspace/ragents-bundle.json +1 -1
  57. package/package.json +2 -2
  58. package/packages/agent/dist/core/agent-settings.d.ts +2 -2
  59. package/packages/agent/dist/core/compaction/compaction.d.ts +16 -50
  60. package/packages/agent/dist/core/context-log.d.ts +25 -0
  61. package/packages/agent/dist/core/messages.d.ts +3 -10
  62. package/packages/agent/dist/core/tool-definition.d.ts +17 -0
  63. package/packages/agent/dist/core/tools/bash.d.ts +2 -7
  64. package/packages/agent/dist/core/tools/edit.d.ts +1 -1
  65. package/packages/agent/dist/core/tools/read.d.ts +1 -1
  66. package/packages/agent/dist/core/tools/write.d.ts +1 -1
  67. package/packages/agent/dist/index.d.ts +7 -8
  68. package/packages/agent/dist/loop/agent.d.ts +2 -6
  69. package/packages/agent/package.json +1 -1
  70. package/packages/agent/src/core/agent-settings.ts +2 -2
  71. package/packages/agent/src/core/compaction/compaction.ts +49 -175
  72. package/packages/agent/src/core/context-log.ts +49 -0
  73. package/packages/agent/src/core/messages.ts +5 -11
  74. package/packages/agent/src/core/tool-definition.ts +29 -0
  75. package/packages/agent/src/core/tools/bash.ts +2 -9
  76. package/packages/agent/src/core/tools/edit.ts +2 -11
  77. package/packages/agent/src/core/tools/read.ts +3 -18
  78. package/packages/agent/src/core/tools/write.ts +1 -5
  79. package/packages/agent/src/index.ts +28 -14
  80. package/packages/agent/src/loop/agent-loop.ts +1 -2
  81. package/packages/agent/src/loop/agent.ts +8 -2
  82. package/packages/ai/dist/api/ai-sdk.d.ts +2 -0
  83. package/packages/ai/dist/types.d.ts +2 -0
  84. package/packages/ai/src/api/ai-sdk-messages.ts +15 -10
  85. package/packages/ai/src/api/ai-sdk.ts +11 -0
  86. package/packages/ai/src/api/transform-messages.ts +1 -1
  87. package/packages/ai/src/types.ts +2 -0
  88. package/packages/ai/src/utils/retry.ts +14 -0
  89. package/packages/ragents/src/agents/actor-input.ts +15 -0
  90. package/packages/ragents/src/agents/model-context.ts +360 -0
  91. package/packages/ragents/src/agents/plugins.ts +5 -0
  92. package/packages/ragents/src/agents/scheduler.ts +3 -7
  93. package/packages/ragents/src/agents/tools.ts +2 -2
  94. package/packages/ragents/src/agents/toolset.ts +47 -20
  95. package/packages/ragents/src/agents/workspaces.ts +0 -6
  96. package/packages/ragents/src/domain/event-semantics.ts +51 -0
  97. package/packages/ragents/src/domain/event-validation.ts +166 -0
  98. package/packages/ragents/src/domain/events.ts +72 -0
  99. package/packages/ragents/src/domain/model.ts +4 -2
  100. package/packages/ragents/src/domain/projection.ts +9 -0
  101. package/packages/ragents/src/domain/tool-result-text.ts +9 -0
  102. package/packages/ragents/src/drivers/agent-hooks.ts +25 -38
  103. package/packages/ragents/src/drivers/agent-runtime.ts +118 -933
  104. package/packages/ragents/src/drivers/agent-turn.ts +735 -0
  105. package/packages/ragents/src/drivers/agent.ts +9 -7
  106. package/packages/ragents/src/drivers/skill-preload.ts +53 -63
  107. package/packages/ragents/src/drivers/types.ts +21 -5
  108. package/packages/ragents/src/index.ts +8 -6
  109. package/packages/ragents/src/plugin-host.ts +60 -13
  110. package/packages/ragents/src/plugin-types.ts +7 -2
  111. package/packages/ragents/src/runtime/decisions/actors.ts +10 -0
  112. package/packages/ragents/src/runtime/decisions/turns.ts +66 -7
  113. package/packages/ragents/src/runtime/journal-storage.ts +7 -4
  114. package/packages/ragents/src/runtime/journal.ts +35 -0
  115. package/packages/ragents/src/runtime/orchestration.ts +140 -9
  116. package/packages/workspace-executor/src/sandbox-tools.ts +10 -11
  117. package/plugins/ragents.reference/run-scripts/learning-afternoon/tests/program.test.ts +1 -1
  118. package/plugins/ragents.reference/run-scripts/word-game/tests/program.test.ts +3 -3
  119. package/scripts/agent/journal.ts +5 -3
  120. package/scripts/package/publish-package.ts +4 -3
  121. package/packages/agent/dist/core/agent-session-runtime.d.ts +0 -33
  122. package/packages/agent/dist/core/agent-session-services.d.ts +0 -35
  123. package/packages/agent/dist/core/agent-session.d.ts +0 -234
  124. package/packages/agent/dist/core/auth-guidance.d.ts +0 -4
  125. package/packages/agent/dist/core/defaults.d.ts +0 -3
  126. package/packages/agent/dist/core/extensions/index.d.ts +0 -11
  127. package/packages/agent/dist/core/extensions/loader.d.ts +0 -12
  128. package/packages/agent/dist/core/extensions/runner.d.ts +0 -39
  129. package/packages/agent/dist/core/extensions/types.d.ts +0 -156
  130. package/packages/agent/dist/core/extensions/wrapper.d.ts +0 -12
  131. package/packages/agent/dist/core/resource-loader.d.ts +0 -39
  132. package/packages/agent/dist/core/sdk.d.ts +0 -38
  133. package/packages/agent/dist/core/session-manager.d.ts +0 -189
  134. package/packages/agent/dist/core/source-info.d.ts +0 -16
  135. package/packages/agent/dist/core/system-prompt.d.ts +0 -21
  136. package/packages/agent/src/core/agent-session-runtime.ts +0 -94
  137. package/packages/agent/src/core/agent-session-services.ts +0 -74
  138. package/packages/agent/src/core/agent-session.ts +0 -1108
  139. package/packages/agent/src/core/auth-guidance.ts +0 -14
  140. package/packages/agent/src/core/defaults.ts +0 -3
  141. package/packages/agent/src/core/extensions/index.ts +0 -38
  142. package/packages/agent/src/core/extensions/loader.ts +0 -125
  143. package/packages/agent/src/core/extensions/runner.ts +0 -211
  144. package/packages/agent/src/core/extensions/types.ts +0 -197
  145. package/packages/agent/src/core/extensions/wrapper.ts +0 -24
  146. package/packages/agent/src/core/resource-loader.ts +0 -142
  147. package/packages/agent/src/core/sdk.ts +0 -123
  148. package/packages/agent/src/core/session-manager.ts +0 -743
  149. package/packages/agent/src/core/source-info.ts +0 -28
  150. package/packages/agent/src/core/system-prompt.ts +0 -108
@@ -1,4 +1,8 @@
1
- import type { JournalEvent, UncommittedEvent } from "../domain/events.ts";
1
+ import type { ImageContent, TextContent, UserContent } from "@ragents/ai";
2
+
3
+ import type { EventPayloads, JournalEvent, ModelInputContent, ModelToolResultPart, UncommittedEvent } from "../domain/events.ts";
4
+ import { derivedToolResultText } from "../domain/tool-result-text.ts";
5
+ import { ModelContexts } from "../agents/model-context.ts";
2
6
  import { assertJsonValue, type JsonObject, type JsonValue } from "../domain/json.ts";
3
7
  import type {
4
8
  ActionInput,
@@ -41,17 +45,32 @@ export type { CommandContext } from "./command.ts";
41
45
 
42
46
  const errorMessage = (error: unknown) => error instanceof Error ? error.message : String(error);
43
47
 
48
+ const firstOf = <Value, Found extends Value>(values: Iterable<Value>, matches: (value: Value) => value is Found): Found | undefined => {
49
+ for (const value of values)
50
+ if (matches(value))
51
+ return value;
52
+
53
+ return undefined;
54
+ };
55
+
44
56
  export class Orchestration {
45
57
  readonly #journal: Journal;
46
58
  readonly #services: RuntimeServices;
47
59
  readonly #artifactContents: ArtifactContents;
48
60
  readonly #suppressedSubscriptionRuns = new Set<string>();
61
+ readonly #modelContexts: ModelContexts;
49
62
 
50
63
  constructor(journal: Journal, services: RuntimeServices, artifactContents: ArtifactContents = new MemoryArtifactContents()) {
51
64
  this.#journal = journal;
52
65
  this.#services = services;
53
66
  this.#artifactContents = artifactContents;
67
+ this.#modelContexts = new ModelContexts({
68
+ eventsSince: (runId, sequence) => this.#journal.eventsSince(runId, sequence),
69
+ firstEventId: (runId) => this.#journal.firstEventId(runId),
70
+ media: (hash) => this.mediaContent(hash),
71
+ });
54
72
  this.#journal.subscribe((events) => {
73
+ this.#releaseModelContexts(events);
55
74
  this.#dispatchSubscriptions(events);
56
75
  this.#dispatchCreatorAlerts(events);
57
76
  });
@@ -107,6 +126,21 @@ export class Orchestration {
107
126
  return state;
108
127
  }
109
128
 
129
+ /** A value of the current state without cloning all of it; `read` must neither keep nor change the state. */
130
+ select<Value>(runId: string, read: (state: RunState) => Value): Value {
131
+ const found = this.#journal.select(runId, (state) => ({ value: read(state) }));
132
+
133
+ if (!found)
134
+ throw new DomainError("run-not-found", `Run ${runId} does not exist.`, 404);
135
+
136
+ return found.value;
137
+ }
138
+
139
+ /** The events of a run from the newest back, without copying the journal. */
140
+ recentEvents(runId: string) {
141
+ return this.#journal.recentEvents(runId);
142
+ }
143
+
110
144
  view(runId: string) {
111
145
  return viewOf(this.state(runId));
112
146
  }
@@ -275,6 +309,14 @@ export class Orchestration {
275
309
  };
276
310
  }
277
311
 
312
+ if (entry.type === "context.compacted") {
313
+ return {
314
+ ...entry,
315
+ ...identities,
316
+ payload: { ...entry.payload, firstKeptEventId: rewriteEventId(entry.payload.firstKeptEventId) },
317
+ };
318
+ }
319
+
278
320
  if (entry.type === "subscription.failed") {
279
321
  return {
280
322
  ...entry,
@@ -385,22 +427,111 @@ export class Orchestration {
385
427
  return this.#run(context, runId, "turn.steer", { actorId, ...input }, turns.steerInputs(actorId, input));
386
428
  }
387
429
 
388
- appendModelOutput(context: CommandContext, runId: string, actorId: string, input: { turnId: string; text: string }) {
389
- return this.#run(context, runId, "model.output.complete", { actorId, ...input }, turns.appendModelOutput(actorId, input));
390
- }
391
-
392
430
  appendInterruptedModelOutput(context: CommandContext, runId: string, actorId: string, input: { turnId: string; text: string }) {
393
431
  return this.#run(context, runId, "model.output.interrupt", { actorId, ...input }, turns.appendInterruptedModelOutput(actorId, input));
394
432
  }
395
433
 
396
- appendModelReasoning(context: CommandContext, runId: string, actorId: string, input: { turnId: string; text: string }) {
397
- return this.#run(context, runId, "model.reasoning.complete", { actorId, ...input }, turns.appendModelReasoning(actorId, input));
398
- }
399
-
400
434
  appendRuntimeOutput(context: CommandContext, runId: string, actorId: string, input: { turnId: string; text: string }) {
401
435
  return this.#run(context, runId, "runtime.output.record", { actorId, ...input }, turns.appendRuntimeOutput(actorId, input));
402
436
  }
403
437
 
438
+ /** The model context of an actor, extended by the events since the last call. */
439
+ modelContext(runId: string, actorId: string) {
440
+ return this.#modelContexts.contextOf(runId, actorId);
441
+ }
442
+
443
+ /** How many actor contexts are held in memory. */
444
+ heldModelContexts() {
445
+ return this.#modelContexts.size;
446
+ }
447
+
448
+ #releaseModelContexts(events: readonly JournalEvent[]) {
449
+ for (const event of events) {
450
+ if ((event.type !== "turn.finished" && event.type !== "turn.interrupted") || this.#journal.failureOf(event.runId))
451
+ continue;
452
+
453
+ const actorId = this.#journal.select(event.runId, (state) => state.turns.get(event.payload.turnId)?.actorId);
454
+
455
+ if (actorId)
456
+ this.#modelContexts.forgetActor(event.runId, actorId);
457
+ }
458
+ }
459
+
460
+ /** Removes a run from the journal and everything held for it in memory; its files stay. */
461
+ forgetRun(runId: string) {
462
+ this.#modelContexts.forget(runId);
463
+ return this.#journal.forget(runId);
464
+ }
465
+
466
+ /** The Base64 of stored media bytes, for the model context. */
467
+ mediaContent(hash: string): string {
468
+ return Buffer.from(this.#artifactContents.read(hash)).toString("base64");
469
+ }
470
+
471
+ #storedMedia(data: string): string {
472
+ return this.#artifactContents.put(Buffer.from(data, "base64")).hash;
473
+ }
474
+
475
+ presentModelInput(
476
+ context: CommandContext,
477
+ runId: string,
478
+ actorId: string,
479
+ input: { turnId: string; inputId: string | null; content: string | readonly UserContent[] },
480
+ ) {
481
+ const content: ModelInputContent = typeof input.content === "string"
482
+ ? input.content
483
+ : input.content.map((part) => {
484
+ if (part.type === "text") return { type: "text" as const, text: part.text };
485
+ const hash = this.#storedMedia(part.data);
486
+ return part.type === "file"
487
+ ? { type: "file" as const, mimeType: part.mimeType, filename: part.filename, hash }
488
+ : { type: part.type, mimeType: part.mimeType, hash };
489
+ });
490
+ const payload = { turnId: input.turnId, inputId: input.inputId, content };
491
+
492
+ return this.#run(context, runId, "model.input.present", { actorId, ...payload }, turns.presentModelInput(actorId, payload));
493
+ }
494
+
495
+ completeModelStep(context: CommandContext, runId: string, actorId: string, input: { turnId: string; step: turns.CompletedModelStep }) {
496
+ const step = JSON.parse(JSON.stringify(input.step)) as turns.CompletedModelStep;
497
+
498
+ return this.#run(context, runId, "model.step.complete", { actorId, turnId: input.turnId, step }, turns.completeModelStep(actorId, { turnId: input.turnId, step }));
499
+ }
500
+
501
+ /** Stores what the model saw of a tool result; the content is left out when it is exactly the text of the recorded result. */
502
+ presentToolResult(
503
+ context: CommandContext,
504
+ runId: string,
505
+ actorId: string,
506
+ input: { turnId: string; toolCallId: string; toolName: string; isError: boolean; content: readonly (TextContent | ImageContent)[] },
507
+ ) {
508
+ const content: ModelToolResultPart[] = input.content.map((part) => part.type === "text"
509
+ ? { type: "text", text: part.text }
510
+ : { type: "image", mimeType: part.mimeType, hash: this.#storedMedia(part.data) });
511
+ const recorded = firstOf(this.recentEvents(runId), (event): event is Extract<JournalEvent, { type: "tool.call.completed" | "tool.call.failed" }> =>
512
+ (event.type === "tool.call.completed" || event.type === "tool.call.failed")
513
+ && event.actorId === actorId
514
+ && event.payload.turnId === input.turnId
515
+ && event.payload.toolCallId === input.toolCallId);
516
+ const derived = recorded !== undefined
517
+ && content.length === 1
518
+ && content[0]!.type === "text"
519
+ && content[0]!.text === derivedToolResultText(recorded);
520
+ const payload = {
521
+ turnId: input.turnId,
522
+ toolCallId: input.toolCallId,
523
+ toolName: input.toolName,
524
+ isError: input.isError,
525
+ ...(derived ? {} : { content }),
526
+ };
527
+
528
+ return this.#run(context, runId, "model.tool-result.present", { actorId, ...payload }, turns.presentToolResult(actorId, payload));
529
+ }
530
+
531
+ compactContext(context: CommandContext, runId: string, actorId: string, input: EventPayloads["context.compacted"]) {
532
+ return this.#run(context, runId, "context.compact", { actorId, ...input }, turns.compactContext(actorId, input));
533
+ }
534
+
404
535
  startToolCall(
405
536
  context: CommandContext,
406
537
  runId: string,
@@ -27,7 +27,6 @@ type ToolExecute = (
27
27
  input: unknown,
28
28
  signal: AbortSignal | undefined,
29
29
  onUpdate: ((update: ToolUpdate) => void) | undefined,
30
- context: unknown,
31
30
  ) => Promise<unknown>;
32
31
 
33
32
  export interface SandboxToolCall {
@@ -177,17 +176,17 @@ export const createSandboxTools = async (
177
176
  await allowedWorkspacePath(path.resolve(cwd, String(raw)), roots);
178
177
  };
179
178
 
180
- const concurrent = (execute: ToolExecute): ToolExecute => (toolCallId, input, signal, onUpdate, context) => {
179
+ const concurrent = (execute: ToolExecute): ToolExecute => (toolCallId, input, signal, onUpdate) => {
181
180
  if (shuttingDown) throw new Error("Die Werkzeuge werden killed");
182
181
  if (signal?.aborted) throw new Error("Abgebrochen");
183
- const run = () => execute(toolCallId, input, signal, onUpdate, context);
182
+ const run = () => execute(toolCallId, input, signal, onUpdate);
184
183
  return initial.runOperation ? initial.runOperation(run) : run();
185
184
  };
186
185
 
187
186
  const serial = (execute: ToolExecute): ToolExecute => {
188
187
  const inner = concurrent(execute);
189
- return (toolCallId, input, signal, onUpdate, context) => {
190
- const call = () => inner(toolCallId, input, signal, onUpdate, context);
188
+ return (toolCallId, input, signal, onUpdate) => {
189
+ const call = () => inner(toolCallId, input, signal, onUpdate);
191
190
  const result = toolOperation.then(call, call);
192
191
  toolOperation = result.then(() => undefined, () => undefined);
193
192
  return result;
@@ -222,7 +221,7 @@ export const createSandboxTools = async (
222
221
 
223
222
  const guarded = (name: FileToolName, execute: ToolExecute): ToolExecute => {
224
223
  const writing = name !== "read";
225
- const checked: ToolExecute = async (toolCallId, input, signal, onUpdate, ctx) => {
224
+ const checked: ToolExecute = async (toolCallId, input, signal, onUpdate) => {
226
225
  const { seen, ...params } = (input ?? {}) as FileToolInput;
227
226
  const context = await contextFor();
228
227
  const shown = typeof params.path === "string" ? params.path : undefined;
@@ -236,7 +235,7 @@ export const createSandboxTools = async (
236
235
  const tracked = seen !== undefined && file !== undefined && shown !== undefined;
237
236
  const early = tracked ? await checkedAgainstSeen(name, file, shown, params, seen) : undefined;
238
237
  if (early) return early;
239
- const result = await execute(toolCallId, requested === undefined ? params : { ...params, path: requested }, signal, onUpdate, ctx);
238
+ const result = await execute(toolCallId, requested === undefined ? params : { ...params, path: requested }, signal, onUpdate);
240
239
  const recorded = tracked ? { ...result as ToolResult, details: { ...(result as ToolResult).details as object, seen: seenAfter(name, file, params, result) } } : result;
241
240
  const annotated = writing && annotate && file !== undefined ? withAnnotation(recorded, await annotate(file)) : recorded;
242
241
  return requested === undefined || shown === undefined ? annotated : withShownPath(annotated, requested, shown);
@@ -248,9 +247,9 @@ export const createSandboxTools = async (
248
247
  };
249
248
 
250
249
  /** Der Ordner eines Bash-Aufrufs: relativ zum Arbeitsverzeichnis oder mit Alias, auf jedem Rechner gleich, darum nie absolut, und immer in einer Wurzel des Runs. */
251
- const inFolder = (execute: ToolExecute): ToolExecute => async (toolCallId, input, signal, onUpdate, ctx) => {
250
+ const inFolder = (execute: ToolExecute): ToolExecute => async (toolCallId, input, signal, onUpdate) => {
252
251
  const params = input as { cwd?: unknown } | undefined;
253
- if (params?.cwd === undefined) return execute(toolCallId, input, signal, onUpdate, ctx);
252
+ if (params?.cwd === undefined) return execute(toolCallId, input, signal, onUpdate);
254
253
  const requested = params.cwd;
255
254
  if (typeof requested !== "string" || requested === "" || path.isAbsolute(requested)) {
256
255
  throw new WorkspaceOperationError("workspace-path-invalid",
@@ -262,7 +261,7 @@ export const createSandboxTools = async (
262
261
  if (!(await stat(directory).catch(() => undefined))?.isDirectory()) {
263
262
  throw new WorkspaceOperationError("workspace-path-not-found", `Den Ordner ${requested} gibt es nicht`, 404);
264
263
  }
265
- return execute(toolCallId, { ...params, cwd: directory }, signal, onUpdate, ctx);
264
+ return execute(toolCallId, { ...params, cwd: directory }, signal, onUpdate);
266
265
  };
267
266
 
268
267
  const startBash: BashOperations["exec"] = async (command, commandCwd, options) => {
@@ -355,7 +354,7 @@ export const createSandboxTools = async (
355
354
  ];
356
355
  return {
357
356
  tools: new Map(wrapped.map(([name, execute]) =>
358
- [name, (input: unknown, call: SandboxToolCall) => execute(call.toolCallId, input, call.signal, call.onUpdate, undefined)])),
357
+ [name, (input: unknown, call: SandboxToolCall) => execute(call.toolCallId, input, call.signal, call.onUpdate)])),
359
358
  shutdown,
360
359
  };
361
360
  };
@@ -214,5 +214,5 @@ test("der gemeinsame Ablauf liefert Helferaufträge, Prompt und parallele Graphz
214
214
  await program.onInput(eventOf("experiment", "actor.stopped", {}), context);
215
215
  const failed = workflowGraph(learningWorkflow, learningWorkflowState(context.state.read().board!));
216
216
  assert.deepEqual(failed.nodes.map((node) => [node.id, node.status]), [["experiment", "blocked"], ["quiz", "done"], ["collect", "blocked"]]);
217
- assert.match(failed.nodes.find((node) => node.id === "collect")!.detail!, /1 von 2/);
217
+ assert.match(failed.nodes.find((node) => node.id === "collect")!.detail!, /1 of 2/);
218
218
  });
@@ -96,7 +96,7 @@ test("wartet auf spätere Ereignisse, zählt zwölf Beiträge und beendet die We
96
96
  assert.deepEqual(inputs.map((call) => (call.input as { actor: string }).actor), words.map((_word, index) => `actor-${participants[index % 4]!.handle}`));
97
97
  assert.equal(context.state.read().status, "completed");
98
98
  assert.equal(context.state.read().entries?.length, 12);
99
- assert.match(context.state.read().document!, /12\. Grün: Blume/);
99
+ assert.match(context.state.read().document!, /12\. Green: Blume/);
100
100
  assert.equal(context.state.read().pendingInputId, undefined);
101
101
  assert.deepEqual(await program.functions.start({}, context), { accepted: false });
102
102
  });
@@ -122,7 +122,7 @@ for (const scenario of [
122
122
  { name: "Modellfehler", word: "Strand", options: { outcome: "failed" } },
123
123
  { name: "Unterbrechung", word: "Strand", options: { type: "turn.interrupted" } },
124
124
  { name: "Mehrwortantwort", word: "Schöner Strand", options: {} },
125
- { name: "wiederholtes Ausgangswort", word: "sonne", options: {} },
125
+ { name: "wiederholtes Ausgangswort", word: "sun", options: {} },
126
126
  ]) {
127
127
  test(`${scenario.name} bleibt als Fehler sichtbar und startet nicht erneut`, async () => {
128
128
  const { context, calls, response, start } = fixture();
@@ -247,6 +247,6 @@ test("ein gestoppter aktueller Teilnehmer hält das Spiel an", async () => {
247
247
  await start();
248
248
  await program.onInput(response("Strand", { type: "actor.stopped" }), context);
249
249
  assert.equal(context.state.read().status, "error");
250
- assert.match(context.state.read().error!, /Rot wurde gestoppt/);
250
+ assert.match(context.state.read().error!, /Red wurde gestoppt/);
251
251
  assert.equal(context.state.read().entries?.length, 0);
252
252
  });
@@ -84,7 +84,7 @@ export const usageByActor = (events: readonly JournalEvent[]): Map<string, Actor
84
84
  const result = new Map<string, ActorUsage>();
85
85
  for (const event of events) {
86
86
  const model = event.payload.usage as Record<string, unknown> | undefined;
87
- if (!model) continue;
87
+ if (!model || event.type === "model.step.completed") continue;
88
88
  const entry = result.get(event.actorId) ?? { calls: 0, inputTokens: 0, cacheReadTokens: 0, outputTokens: 0, costUsd: 0 };
89
89
  entry.calls += 1;
90
90
  for (const key of ["inputTokens", "cacheReadTokens", "outputTokens", "costUsd"] as const) {
@@ -111,8 +111,10 @@ export const journalLines = (events: readonly JournalEvent[], mode: JournalMode,
111
111
  const output = text(payload.text);
112
112
  if (output.trim()) lines.push(`[${event.sequence}] ${actor}: ${output.slice(0, 800)}`);
113
113
  } else if (type === "actor.input.enqueued" && mode !== "tools") {
114
- const input = payload.input as Record<string, unknown> | undefined;
115
- lines.push(`[${event.sequence}] INPUT -> ${String(payload.actorId ?? "").slice(0, 14)}: ${text(payload.text ?? input?.text).slice(0, 300)}`);
114
+ const content = payload.subscriptionId ? `[event ${String((payload.sourceEventIds as string[] | undefined)?.[0] ?? "")}]` : text(payload.content);
115
+ lines.push(`[${event.sequence}] INPUT -> ${String(payload.actorId ?? "").slice(0, 14)}: ${content.slice(0, 300)}`);
116
+ } else if (type === "context.compacted" && mode !== "tools") {
117
+ lines.push(`[${event.sequence}] CONTEXT COMPACTED ${actor}: about ${String(payload.tokensBefore)} tokens summarized`);
116
118
  } else if (type === "turn.input-steered" && mode !== "tools") {
117
119
  lines.push(`[${event.sequence}] STEERING -> ${actor}: ${String(payload.inputId ?? "")} in ${String(payload.turnId ?? "")}`);
118
120
  } else if (type.startsWith("tool.call.") && mode !== "chat") {
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { compareVersions, nextVersion, readVersion, versionLine, writeHostPackageVersion, writeVersion } from "../publish-version.ts";
4
+ import { compareVersions, readVersion, releaseVersion, versionLine, writeHostPackageVersion, writeVersion } from "../publish-version.ts";
5
5
  import { buildPackage, PACKAGE_FOLDER, PACKAGE_NAME } from "./build-package.ts";
6
6
 
7
7
  const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
@@ -121,11 +121,12 @@ const main = async (): Promise<void> => {
121
121
  if (!token) throw new Error(`npm_key fehlt: der npm-Token mit Schreibrecht auf ${PACKAGE_NAME}.\n${usage}`);
122
122
  const manifestFile = path.join(repositoryRoot, "package.json");
123
123
  const published = publishedVersions(PACKAGE_NAME, runNpm);
124
- const next = nextVersion(readVersion(manifestFile), published);
125
- console.log(versionLine(next));
126
124
  const extensionManifestFile = path.join(repositoryRoot, "apps", "vscode", "package.json");
125
+ const next = releaseVersion([readVersion(manifestFile), readVersion(extensionManifestFile)], published);
126
+ console.log(versionLine(next));
127
127
  if (!dryRun) {
128
128
  writeVersion(manifestFile, next.version);
129
+ writeVersion(extensionManifestFile, next.version);
129
130
  writeHostPackageVersion(extensionManifestFile, next.version);
130
131
  }
131
132
  const built = await buildPackage(path.join(repositoryRoot, "dist", PACKAGE_FOLDER));
@@ -1,33 +0,0 @@
1
- import type { AgentSession } from "./agent-session.ts";
2
- import type { AgentSessionServices } from "./agent-session-services.ts";
3
- import type { ExtensionFactorySettlementObserver } from "./extensions/index.ts";
4
- import type { CreateAgentSessionResult } from "./sdk.ts";
5
- import type { SessionManager } from "./session-manager.ts";
6
- /** Result returned by runtime creation: the created session and its cwd-bound services. */
7
- export interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {
8
- services: AgentSessionServices;
9
- }
10
- /** Creates the services and the AgentSession for a target cwd and session manager. */
11
- export type CreateAgentSessionRuntimeFactory = (options: {
12
- cwd: string;
13
- sessionManager: SessionManager;
14
- signal: AbortSignal;
15
- onExtensionFactorySettlement?: ExtensionFactorySettlementObserver;
16
- }) => Promise<CreateAgentSessionRuntimeResult>;
17
- /** Owns one AgentSession plus its cwd-bound services. */
18
- export declare class AgentSessionRuntime {
19
- readonly session: AgentSession;
20
- readonly services: AgentSessionServices;
21
- constructor(session: AgentSession, services: AgentSessionServices);
22
- waitForSettlement(): Promise<void>;
23
- dispose(): Promise<void>;
24
- }
25
- /** Create the runtime from a runtime factory; an abort during creation disposes the late session. */
26
- export declare function createAgentSessionRuntime(createRuntime: CreateAgentSessionRuntimeFactory, options: {
27
- cwd: string;
28
- sessionManager: SessionManager;
29
- signal?: AbortSignal;
30
- onExtensionFactorySettlement?: ExtensionFactorySettlementObserver;
31
- }): Promise<AgentSessionRuntime>;
32
- export { type AgentSessionServices, type CreateAgentSessionFromServicesOptions, type CreateAgentSessionServicesOptions, createAgentSessionFromServices, createAgentSessionServices, } from "./agent-session-services.ts";
33
- //# sourceMappingURL=agent-session-runtime.d.ts.map
@@ -1,35 +0,0 @@
1
- import type { ThinkingLevel } from "../loop/index.ts";
2
- import type { Model } from "@ragents/ai";
3
- import type { ExtensionFactorySettlementObserver, ToolDefinition } from "./extensions/index.ts";
4
- import type { ModelRuntime } from "./model-runtime.ts";
5
- import { type DefaultResourceLoaderOptions, type ResourceLoader } from "./resource-loader.ts";
6
- import { type CreateAgentSessionResult } from "./sdk.ts";
7
- import type { SessionManager } from "./session-manager.ts";
8
- /** Inputs for creating the services of one session: its cwd, model runtime and loaded resources. */
9
- export interface CreateAgentSessionServicesOptions {
10
- cwd: string;
11
- signal?: AbortSignal;
12
- modelRuntime: ModelRuntime;
13
- onExtensionFactorySettlement?: ExtensionFactorySettlementObserver;
14
- resourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, "onExtensionFactorySettlement">;
15
- }
16
- /** Inputs for creating an AgentSession from already-created services. */
17
- export interface CreateAgentSessionFromServicesOptions {
18
- services: AgentSessionServices;
19
- sessionManager: SessionManager;
20
- model: Model<any>;
21
- thinkingLevel?: ThinkingLevel;
22
- tools?: string[];
23
- customTools?: ToolDefinition[];
24
- }
25
- /** The services of one session; the AgentSession itself is created separately. */
26
- export interface AgentSessionServices {
27
- cwd: string;
28
- modelRuntime: ModelRuntime;
29
- resourceLoader: ResourceLoader;
30
- }
31
- /** Create the services of one session and load its extensions; it does not create an AgentSession. */
32
- export declare function createAgentSessionServices(options: CreateAgentSessionServicesOptions): Promise<AgentSessionServices>;
33
- /** Create an AgentSession from previously created services. */
34
- export declare function createAgentSessionFromServices(options: CreateAgentSessionFromServicesOptions): Promise<CreateAgentSessionResult>;
35
- //# sourceMappingURL=agent-session-services.d.ts.map
@@ -1,234 +0,0 @@
1
- /** One agent: model and thinking level, prompts, persistence, auto-compaction and retry, extension hooks and tools. */
2
- import type { Agent, AgentEvent, AgentMessage, ThinkingLevel } from "../loop/index.ts";
3
- import type { Model, UserAttachment } from "@ragents/ai";
4
- import { type CompactionResult } from "./compaction/index.ts";
5
- import { type ExtensionErrorListener, ExtensionRunner, type ToolDefinition, type ToolInfo } from "./extensions/index.ts";
6
- import type { ModelRuntime } from "./model-runtime.ts";
7
- import type { ResourceLoader } from "./resource-loader.ts";
8
- import type { SessionManager } from "./session-manager.ts";
9
- import type { AgentSettings } from "./agent-settings.ts";
10
- /** Session-specific events that extend the core AgentEvent */
11
- export type AgentSessionEvent = Exclude<AgentEvent, {
12
- type: "agent_end";
13
- }> | {
14
- type: "agent_end";
15
- messages: AgentMessage[];
16
- willRetry: boolean;
17
- } | {
18
- type: "agent_settled";
19
- } | {
20
- type: "compaction_start";
21
- reason: "threshold" | "overflow";
22
- } | {
23
- type: "thinking_level_changed";
24
- level: ThinkingLevel;
25
- } | {
26
- type: "compaction_end";
27
- reason: "threshold" | "overflow";
28
- result: CompactionResult | undefined;
29
- aborted: boolean;
30
- willRetry: boolean;
31
- errorMessage?: string;
32
- } | {
33
- type: "auto_retry_start";
34
- attempt: number;
35
- maxAttempts: number;
36
- delayMs: number;
37
- errorMessage: string;
38
- } | {
39
- type: "auto_retry_end";
40
- success: boolean;
41
- attempt: number;
42
- finalError?: string;
43
- };
44
- /** Listener function for agent session events */
45
- export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
46
- export interface AgentSessionConfig {
47
- agent: Agent;
48
- sessionManager: SessionManager;
49
- settings: AgentSettings;
50
- cwd: string;
51
- /** Resource loader for extensions, skills and the system prompt */
52
- resourceLoader: ResourceLoader;
53
- /** SDK custom tools registered outside extensions */
54
- customTools?: ToolDefinition[];
55
- /** Canonical model/auth runtime. */
56
- modelRuntime: ModelRuntime;
57
- /** Optional allowlist of tool names. When provided, only these tool names are exposed. */
58
- allowedToolNames?: string[];
59
- /** Mutable ref used by Agent to access the current ExtensionRunner */
60
- extensionRunnerRef?: {
61
- current?: ExtensionRunner;
62
- };
63
- }
64
- export interface ExtensionBindings {
65
- onError?: ExtensionErrorListener;
66
- }
67
- /** Options for AgentSession.prompt() */
68
- export interface PromptOptions {
69
- attachments?: UserAttachment[];
70
- /** Observes whether the prompt was accepted or rejected before the agent run starts. */
71
- preflightResult?: (success: boolean) => void;
72
- }
73
- export declare class AgentSession {
74
- readonly agent: Agent;
75
- readonly sessionManager: SessionManager;
76
- readonly settings: AgentSettings;
77
- private _unsubscribeAgent?;
78
- private _eventListeners;
79
- private _isAgentRunActive;
80
- private _disposed;
81
- private _idleWaitPromise;
82
- private _resolveIdleWait;
83
- private _autoCompactionAbortController;
84
- private _overflowRecoveryAttempted;
85
- private _retryAbortController;
86
- private _retryAttempt;
87
- private _extensionRunner;
88
- private _resourceLoader;
89
- private _customTools;
90
- private _cwd;
91
- private _extensionRunnerRef?;
92
- private _allowedToolNames?;
93
- private _extensionErrorUnsubscriber?;
94
- private _modelRuntime;
95
- private _toolRegistry;
96
- private _toolDefinitions;
97
- private _toolPromptSnippets;
98
- private _toolPromptGuidelines;
99
- private _baseSystemPrompt;
100
- private _baseSystemPromptOptions;
101
- private _systemPromptOverride?;
102
- constructor(config: AgentSessionConfig);
103
- private _getRequiredRequestAuth;
104
- private _getSummarizationRequestAuth;
105
- /** The tool result hook reads `this._extensionRunner` at execution time. */
106
- private _installAgentToolHooks;
107
- private _installAgentNextTurnRefresh;
108
- /** Emit an event to all listeners */
109
- private _emit;
110
- private _getIdleWaitPromise;
111
- private _resolveIdleWaitIfIdle;
112
- private _emitAgentSettled;
113
- private _lastAssistantMessage;
114
- /** Internal handler for agent events - shared by subscribe and reconnect */
115
- private _handleAgentEvent;
116
- private _willRetryAfterAgentEnd;
117
- /** Find the last assistant message in agent state (including aborted ones) */
118
- private _findLastAssistantMessage;
119
- /**
120
- * Subscribe to agent events.
121
- * Session persistence is handled internally (saves messages on message_end).
122
- * Multiple listeners can be added. Returns unsubscribe function for this listener.
123
- */
124
- subscribe(listener: AgentSessionEventListener): () => void;
125
- /**
126
- * Remove all listeners and disconnect from agent.
127
- * Call this when completely done with the session.
128
- */
129
- dispose(): void;
130
- waitForSettlement(): Promise<void>;
131
- /** Current model (may be undefined if not yet selected) */
132
- get model(): Model<any> | undefined;
133
- /** Current thinking level */
134
- get thinkingLevel(): ThinkingLevel;
135
- /** Whether the session is currently processing an agent run or post-run continuation. */
136
- get isStreaming(): boolean;
137
- /** Whether the session has no active agent run, retry, auto-compaction, or queued continuation. */
138
- get isIdle(): boolean;
139
- /** Replace the custom system prompt and rebuild the effective prompt for the next model call. */
140
- setSystemPrompt(prompt: string): void;
141
- /**
142
- * Get the names of currently active tools.
143
- * Returns the names of tools currently set on the agent.
144
- */
145
- getActiveToolNames(): string[];
146
- /**
147
- * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
148
- */
149
- getAllTools(): ToolInfo[];
150
- /**
151
- * Set active tools by name.
152
- * Only tools in the registry can be enabled. Unknown tool names are ignored.
153
- * Also rebuilds the system prompt to reflect the new tool set.
154
- * Changes take effect on the next agent turn.
155
- */
156
- setActiveToolsByName(toolNames: string[]): void;
157
- /** All messages including custom types */
158
- get messages(): AgentMessage[];
159
- /** Current session file path, or undefined if sessions are disabled */
160
- get sessionFile(): string | undefined;
161
- /** Current session ID */
162
- get sessionId(): string;
163
- private _normalizePromptSnippet;
164
- private _normalizePromptGuidelines;
165
- private _rebuildSystemPrompt;
166
- private _runAgentPrompt;
167
- private _handlePostAgentRun;
168
- /** Run a prompt; while the agent runs, or without model or key, it throws. */
169
- prompt(text: string, options?: PromptOptions): Promise<void>;
170
- private _assertNotDisposed;
171
- /**
172
- * Abort current operation and wait for agent to become idle.
173
- */
174
- abort(): Promise<void>;
175
- waitForIdle(): Promise<void>;
176
- /**
177
- * Set model directly.
178
- * Validates that auth is configured, saves to session and settings.
179
- * @throws Error if no auth is configured for the model
180
- */
181
- setModel(model: Model<any>): Promise<void>;
182
- /**
183
- * Set thinking level.
184
- * Clamps to model capabilities based on available thinking levels.
185
- * Saves to session and settings only if the level actually changes.
186
- */
187
- setThinkingLevel(level: ThinkingLevel): void;
188
- /**
189
- * Get available thinking levels for current model.
190
- * The provider will clamp to what the specific model supports internally.
191
- */
192
- getAvailableThinkingLevels(): ThinkingLevel[];
193
- /**
194
- * Check if current model supports thinking/reasoning.
195
- */
196
- private supportsThinking;
197
- private _getThinkingLevelForModelSwitch;
198
- private _clampThinkingLevel;
199
- /**
200
- * Check if compaction is needed and run it.
201
- * Called after agent_end and before prompt submission.
202
- *
203
- * Two cases:
204
- * 1. Overflow: LLM returned context overflow error, remove error message from agent state, compact, auto-retry
205
- * 2. Threshold: Context over threshold, compact, NO auto-retry (user continues manually)
206
- *
207
- * @param assistantMessage The assistant message to check
208
- * @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
209
- */
210
- private _checkCompaction;
211
- /**
212
- * Internal: Run auto-compaction with events.
213
- */
214
- private _runAutoCompaction;
215
- bindExtensions(bindings: ExtensionBindings): Promise<void>;
216
- private _bindExtensionCore;
217
- private _refreshToolRegistry;
218
- private _buildRuntime;
219
- /**
220
- * Check if an error is retryable (overloaded, rate limit, server errors).
221
- * Context overflow errors are NOT retryable (handled by compaction instead).
222
- */
223
- private _isRetryableError;
224
- /**
225
- * Prepare a retryable error for continuation with exponential backoff.
226
- * @returns true if the caller should continue the agent, false otherwise
227
- */
228
- private _prepareRetry;
229
- /**
230
- * Cancel in-progress retry.
231
- */
232
- abortRetry(): void;
233
- }
234
- //# sourceMappingURL=agent-session.d.ts.map
@@ -1,4 +0,0 @@
1
- export declare function getProviderLoginHelp(): string;
2
- export declare function formatNoModelSelectedMessage(): string;
3
- export declare function formatNoApiKeyFoundMessage(provider: string): string;
4
- //# sourceMappingURL=auth-guidance.d.ts.map