@schlenkr/ragents 0.1.8 → 0.1.10

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 (218) hide show
  1. package/apps/server/package.json +1 -1
  2. package/apps/server/src/access-projection.ts +6 -36
  3. package/apps/server/src/api/contracts.ts +5 -2
  4. package/apps/server/src/api/core-methods.ts +5 -3
  5. package/apps/server/src/config-definition.ts +24 -2
  6. package/apps/server/src/config-file.ts +1 -1
  7. package/apps/server/src/config.ts +0 -6
  8. package/apps/server/src/host-api.json +5 -10
  9. package/apps/server/src/host-api.ts +6 -7
  10. package/apps/server/src/plugin-build/build.ts +28 -5
  11. package/apps/server/src/plugin-build/plugin-description.ts +1 -1
  12. package/apps/server/src/plugin-build/typecheck.ts +2 -2
  13. package/apps/server/src/plugin-support/language-server/plugin.ts +8 -7
  14. package/apps/server/src/plugin-support/language-server/tools.ts +7 -6
  15. package/apps/server/src/plugin-support/model-aliases.ts +55 -25
  16. package/apps/server/src/plugin-support/process-sandbox.ts +16 -15
  17. package/apps/server/src/plugin-support/product-relay.ts +10 -2
  18. package/apps/server/src/plugin-support/workspace-sandbox-host.ts +18 -9
  19. package/apps/server/src/profile/bundle-manifest.ts +7 -3
  20. package/apps/server/src/profile/compose.ts +6 -0
  21. package/apps/server/src/profile/plugin-discovery.ts +6 -1
  22. package/apps/server/src/profile/provisioning.ts +6 -5
  23. package/apps/server/src/provider.ts +2 -2
  24. package/apps/server/src/ragents/engine.ts +2 -2
  25. package/apps/server/src/ragents/global-chat.ts +7 -1
  26. package/apps/server/src/ragents/host-services.ts +4 -0
  27. package/apps/server/src/ragents/session.ts +1 -1
  28. package/apps/server/src/server.ts +4 -1
  29. package/apps/server/tsconfig.json +2 -0
  30. package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-xXXhTDbh.js → highlighted-body-KPVGNVTW-BO4wLQtE.js} +1 -1
  31. package/apps/web/dist/assets/main-DnnqWHkH.js +11 -0
  32. package/apps/web/dist/assets/mermaid-HWGCJPDP-BLLeth5_.js +568 -0
  33. package/apps/web/dist/assets/{runPanel-ZT6TPDLM.js → runPanel-DPm7s3KM.js} +2 -2
  34. package/apps/web/dist/help/guide-clients.html +26 -8
  35. package/apps/web/dist/help/guide-clients.md +27 -8
  36. package/apps/web/dist/help/guide-distributed.html +12 -4
  37. package/apps/web/dist/help/guide-distributed.md +12 -4
  38. package/apps/web/dist/help/guide-getting-started.html +12 -8
  39. package/apps/web/dist/help/guide-getting-started.md +12 -8
  40. package/apps/web/dist/help/guide-plugins.html +6 -2
  41. package/apps/web/dist/help/guide-plugins.md +6 -2
  42. package/apps/web/dist/help/guide-runtime.html +2 -1
  43. package/apps/web/dist/help/guide-runtime.md +2 -1
  44. package/apps/web/dist/help/index.html +4328 -1132
  45. package/apps/web/dist/help/mini-app.css +24 -0
  46. package/apps/web/dist/host-web.json +4 -4
  47. package/apps/web/dist/index.html +2 -2
  48. package/apps/web/dist/run-panel.html +2 -2
  49. package/apps/web/package.json +1 -1
  50. package/apps/web/src/panel/ConnectionsPage.tsx +3 -0
  51. package/apps/web/src/panel/StartPage.tsx +3 -0
  52. package/apps/web/src/panel/contract.ts +7 -0
  53. package/bundles/ragents.activity/ragents-bundle.json +3 -3
  54. package/bundles/ragents.actor-programs/ragents-bundle.json +4 -4
  55. package/bundles/ragents.actor-programs/server/index.js +31 -3
  56. package/bundles/ragents.actor-programs/server/index.js.map +4 -4
  57. package/bundles/ragents.actor-programs/web/index.js.map +1 -1
  58. package/bundles/ragents.ask/ragents-bundle.json +4 -6
  59. package/bundles/ragents.ask/server/index.js +42 -11
  60. package/bundles/ragents.ask/server/index.js.map +3 -3
  61. package/bundles/ragents.ask/web/chunks/{chunk-V7W3QDVS.js → chunk-MBRPS477.js} +2 -2
  62. package/bundles/ragents.ask/web/chunks/{chunk-V7W3QDVS.js.map → chunk-MBRPS477.js.map} +4 -4
  63. package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js +2 -0
  64. package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js.map +7 -0
  65. package/bundles/ragents.ask/web/classes.json +1 -1
  66. package/bundles/ragents.ask/web/exports/ask-payload.js +1 -1
  67. package/bundles/ragents.ask/web/exports/web/QuestionCard.js +1 -1
  68. package/bundles/ragents.ask/web/index.js +1 -1
  69. package/bundles/ragents.ask/web/index.js.map +4 -4
  70. package/bundles/ragents.browser/executor/index.mjs +357 -0
  71. package/bundles/ragents.browser/executor/index.mjs.map +7 -0
  72. package/bundles/ragents.browser/ragents-bundle.json +5 -8
  73. package/bundles/ragents.browser/server/chunks/{chunk-2GKLLCBE.js → chunk-CWLX4VA5.js} +1 -1
  74. package/bundles/ragents.browser/server/chunks/chunk-CWLX4VA5.js.map +7 -0
  75. package/bundles/ragents.browser/server/exports/server/contract.js +1 -1
  76. package/bundles/ragents.browser/server/index.js +20 -9
  77. package/bundles/ragents.browser/server/index.js.map +4 -4
  78. package/bundles/ragents.documents/ragents-bundle.json +3 -3
  79. package/bundles/ragents.lsp-fsharp/executor/index.mjs +68 -0
  80. package/bundles/ragents.lsp-fsharp/executor/index.mjs.map +7 -0
  81. package/bundles/ragents.lsp-fsharp/ragents-bundle.json +5 -9
  82. package/bundles/ragents.lsp-fsharp/server/index.js +21 -6
  83. package/bundles/ragents.lsp-fsharp/server/index.js.map +4 -4
  84. package/bundles/ragents.lsp-roslyn/executor/index.mjs +68 -0
  85. package/bundles/ragents.lsp-roslyn/executor/index.mjs.map +7 -0
  86. package/bundles/ragents.lsp-roslyn/ragents-bundle.json +6 -8
  87. package/bundles/ragents.lsp-roslyn/server/index.js +54 -15
  88. package/bundles/ragents.lsp-roslyn/server/index.js.map +4 -4
  89. package/bundles/ragents.lsp-typescript/executor/index.mjs +49 -0
  90. package/bundles/ragents.lsp-typescript/executor/index.mjs.map +7 -0
  91. package/bundles/ragents.lsp-typescript/ragents-bundle.json +5 -7
  92. package/bundles/ragents.lsp-typescript/server/index.js +22 -2
  93. package/bundles/ragents.lsp-typescript/server/index.js.map +3 -3
  94. package/bundles/ragents.model-relay/ragents-bundle.json +4 -4
  95. package/bundles/ragents.model-relay/server/index.js +3 -2
  96. package/bundles/ragents.model-relay/server/index.js.map +2 -2
  97. package/bundles/ragents.orchestration/ragents-bundle.json +4 -4
  98. package/bundles/ragents.orchestration/web/classes.json +1 -1
  99. package/bundles/ragents.orchestration/web/index.js +6 -6
  100. package/bundles/ragents.orchestration/web/index.js.map +3 -3
  101. package/bundles/ragents.overseer/ragents-bundle.json +4 -4
  102. package/bundles/ragents.overseer/server/index.js +1 -1
  103. package/bundles/ragents.overseer/server/index.js.map +2 -2
  104. package/bundles/ragents.processes/ragents-bundle.json +3 -3
  105. package/bundles/ragents.product/ragents-bundle.json +3 -3
  106. package/bundles/ragents.profile-distribution/ragents-bundle.json +4 -4
  107. package/bundles/ragents.profile-distribution/server/index.js +1 -1
  108. package/bundles/ragents.profile-distribution/server/index.js.map +2 -2
  109. package/bundles/ragents.reference/ragents-bundle.json +3 -3
  110. package/bundles/ragents.todo/ragents-bundle.json +3 -3
  111. package/bundles/ragents.transcript/ragents-bundle.json +3 -3
  112. package/bundles/ragents.watch/ragents-bundle.json +3 -3
  113. package/bundles/ragents.workspace/ragents-bundle.json +11 -5
  114. package/bundles/ragents.workspace/server/index.js +105 -30
  115. package/bundles/ragents.workspace/server/index.js.map +3 -3
  116. package/bundles/ragents.workspace/web/classes.json +1 -1
  117. package/bundles/ragents.workspace/web/index.js +1 -1
  118. package/bundles/ragents.workspace/web/index.js.map +3 -3
  119. package/package.json +3 -3
  120. package/packages/agent/dist/core/agent-settings.d.ts +1 -7
  121. package/packages/agent/dist/core/compaction/compaction.d.ts +17 -13
  122. package/packages/agent/dist/core/model-runtime.d.ts +5 -4
  123. package/packages/agent/dist/core/provider-composer.d.ts +2 -1
  124. package/packages/agent/dist/core/tools/bash.d.ts +9 -3
  125. package/packages/agent/dist/index.d.ts +1 -1
  126. package/packages/agent/src/core/agent-settings.ts +1 -4
  127. package/packages/agent/src/core/compaction/compaction.ts +68 -30
  128. package/packages/agent/src/core/model-runtime.ts +12 -5
  129. package/packages/agent/src/core/provider-composer.ts +5 -0
  130. package/packages/agent/src/core/tools/bash.ts +36 -30
  131. package/packages/agent/src/index.ts +3 -0
  132. package/packages/ai/dist/types.d.ts +11 -0
  133. package/packages/ai/src/types.ts +12 -0
  134. package/packages/ragents/src/domain/event-semantics.ts +3 -0
  135. package/packages/ragents/src/domain/event-validation.ts +15 -2
  136. package/packages/ragents/src/domain/events.ts +3 -0
  137. package/packages/ragents/src/domain/model.ts +2 -0
  138. package/packages/ragents/src/domain/projection.ts +1 -0
  139. package/packages/ragents/src/drivers/agent-runtime.ts +1 -1
  140. package/packages/ragents/src/drivers/agent-turn.ts +8 -6
  141. package/packages/ragents/src/index.ts +1 -0
  142. package/packages/ragents/src/plugin-host.ts +46 -0
  143. package/packages/ragents/src/plugin-types.ts +19 -0
  144. package/packages/ragents/src/runtime/decisions/inputs.ts +6 -2
  145. package/packages/ragents/src/runtime/journal-storage.ts +5 -4
  146. package/packages/workspace-executor/package.json +0 -1
  147. package/packages/workspace-executor/src/bash-launch.ts +56 -10
  148. package/packages/workspace-executor/src/context.ts +4 -0
  149. package/packages/workspace-executor/src/contributions.ts +150 -0
  150. package/packages/workspace-executor/src/executor.ts +1 -1
  151. package/packages/workspace-executor/src/index.ts +16 -19
  152. package/packages/workspace-executor/src/language-server/host.ts +3 -0
  153. package/packages/workspace-executor/src/language-server/module.ts +12 -2
  154. package/packages/workspace-executor/src/language-server/roots.ts +0 -5
  155. package/packages/workspace-executor/src/managed-process.ts +28 -0
  156. package/packages/workspace-executor/src/modules.ts +7 -6
  157. package/packages/workspace-executor/src/sandbox-tools.ts +12 -12
  158. package/packages/workspace-executor/src/shell-platform.ts +14 -3
  159. package/packages/workspace-executor/src/tools.ts +0 -3
  160. package/plugins/ragents.actor-programs/server/access-projections.ts +31 -0
  161. package/plugins/ragents.actor-programs/server/index.ts +2 -0
  162. package/plugins/ragents.ask/ask-payload.ts +9 -0
  163. package/plugins/ragents.ask/server/ask-service.ts +53 -13
  164. package/plugins/ragents.ask/web/AskActionView.tsx +3 -2
  165. package/plugins/ragents.ask/web/index.tsx +0 -6
  166. package/plugins/ragents.browser/executor/index.ts +5 -0
  167. package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/module.ts +25 -31
  168. package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/playwright.ts +9 -23
  169. package/plugins/ragents.browser/provision.ts +1 -1
  170. package/plugins/ragents.browser/server/browser.ts +3 -3
  171. package/plugins/ragents.browser/server/contract.ts +2 -2
  172. package/plugins/ragents.browser/server/index.ts +1 -1
  173. package/plugins/ragents.lsp-fsharp/executor.ts +80 -0
  174. package/plugins/ragents.lsp-fsharp/provision.ts +1 -1
  175. package/plugins/ragents.lsp-fsharp/server/index.ts +2 -2
  176. package/plugins/ragents.lsp-roslyn/executor.ts +64 -0
  177. package/plugins/ragents.lsp-roslyn/provision.ts +1 -1
  178. package/plugins/ragents.lsp-roslyn/server/index.ts +28 -5
  179. package/plugins/ragents.lsp-roslyn/server/solution-on-start.ts +18 -6
  180. package/plugins/ragents.lsp-typescript/executor.ts +50 -0
  181. package/plugins/ragents.lsp-typescript/server/index.ts +2 -2
  182. package/plugins/ragents.model-relay/server/config.ts +1 -1
  183. package/plugins/ragents.model-relay/server/relay.ts +4 -2
  184. package/plugins/ragents.orchestration/web/ActorTile.tsx +1 -1
  185. package/plugins/ragents.orchestration/web/run-panel/RunPanel.tsx +8 -7
  186. package/plugins/ragents.orchestration/web/run-panel/sheet-status.ts +3 -3
  187. package/plugins/ragents.overseer/server/api.ts +2 -2
  188. package/plugins/ragents.profile-distribution/server/archive.ts +2 -1
  189. package/plugins/ragents.workspace/client/workspace-client.ts +128 -32
  190. package/plugins/ragents.workspace/contract.ts +33 -2
  191. package/plugins/ragents.workspace/server/binding.ts +10 -4
  192. package/plugins/ragents.workspace/server/clients.ts +56 -9
  193. package/plugins/ragents.workspace/server/config.ts +12 -0
  194. package/plugins/ragents.workspace/server/index.ts +15 -5
  195. package/plugins/ragents.workspace/server/runtime.ts +10 -0
  196. package/plugins/ragents.workspace/server/shell-platform.ts +6 -5
  197. package/plugins/ragents.workspace/web/WorkspaceBinding.tsx +1 -1
  198. package/ragents.config.core.ts +4 -1
  199. package/ragents.config.showcase.ts +4 -1
  200. package/scripts/agent/journal.ts +3 -1
  201. package/scripts/package/build-package.ts +3 -1
  202. package/scripts/provision/run-provision.ts +2 -2
  203. package/scripts/workspace-client/run-workspace-client.ts +7 -4
  204. package/apps/web/dist/assets/main-C7JeZFjs.js +0 -6
  205. package/apps/web/dist/assets/mermaid-HWGCJPDP-DfsU5ofC.js +0 -478
  206. package/apps/web/dist/help/screenshots/release-checklist-vscode.png +0 -0
  207. package/apps/web/dist/help/screenshots/release-checklist-web.png +0 -0
  208. package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js +0 -2
  209. package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js.map +0 -7
  210. package/bundles/ragents.browser/server/chunks/chunk-2GKLLCBE.js.map +0 -7
  211. package/packages/workspace-executor/src/language-server/adapters/fsharp.ts +0 -60
  212. package/packages/workspace-executor/src/language-server/adapters/index.ts +0 -7
  213. package/packages/workspace-executor/src/language-server/adapters/roslyn.ts +0 -56
  214. package/packages/workspace-executor/src/language-server/adapters/typescript.ts +0 -74
  215. package/packages/workspace-executor/src/language-server/solution.ts +0 -13
  216. package/plugins/ragents.ask/web/QuestionSection.tsx +0 -48
  217. /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/contract.ts +0 -0
  218. /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/pages.ts +0 -0
@@ -1,10 +1,10 @@
1
- import { aliasedModel, type ModelAlias as RuntimeModelAlias } from "@ragents/agent";
1
+ import { aliasedModel, compactionProblem, type ModelAlias as RuntimeModelAlias } from "@ragents/agent";
2
2
  import { getSupportedThinkingLevels, type Api, type Model } from "@ragents/ai";
3
3
  import { getBuiltinModels, type BuiltinProvider } from "@ragents/ai/providers/all";
4
4
  import { isThinkingLevel, type ThinkingLevel } from "@ragents/engine";
5
5
  import { declaredEnvironment } from "./plugin-config.js";
6
6
 
7
- /** Ein Alias des Profils mit seinem Ziel und optional der Denktiefe, die gilt, solange niemand eine andere wählt. */
7
+ /** Ein Alias des Profils mit Ziel und Kompaktierungswerten und optional der Denktiefe, die gilt, solange niemand eine andere wählt. */
8
8
  export interface ModelAlias extends RuntimeModelAlias {
9
9
  readonly thinking?: ThinkingLevel;
10
10
  }
@@ -17,47 +17,77 @@ export const modelAliasEnvDescriptors = [
17
17
  ] as const;
18
18
 
19
19
  const ALIAS = /^[a-z0-9][a-z0-9._-]{0,63}$/;
20
+ const ENTRY_KEYS: readonly string[] = ["alias", "model", "thinking", "compaction"];
20
21
 
21
- /** MODEL_ALIASES: eine Liste "alias=anbieter/modell" oder "alias=anbieter/modell@denktiefe"; der Alias ist der einzige Name, den Oberfläche, Journal und Relay-Clients sehen. */
22
- export const parseModelAliases = (entries: readonly string[]): readonly ModelAlias[] => {
23
- const aliases = entries.map((entry): ModelAlias => {
24
- const separator = entry.indexOf("=");
25
- const alias = separator > 0 ? entry.slice(0, separator).trim() : "";
26
- const rest = separator > 0 ? entry.slice(separator + 1).trim() : "";
27
- const at = rest.lastIndexOf("@");
28
- const target = at < 0 ? rest : rest.slice(0, at);
29
- const thinking = at < 0 ? undefined : rest.slice(at + 1);
30
- const slash = target.indexOf("/");
31
- if (!ALIAS.test(alias) || slash <= 0 || slash === target.length - 1) {
32
- throw new Error(`MODEL_ALIASES: "${entry}" hat nicht das Format "alias=anbieter/modell" oder "alias=anbieter/modell@denktiefe"`);
33
- }
34
- if (thinking !== undefined && !isThinkingLevel(thinking)) throw new Error(`MODEL_ALIASES: "${entry}" nennt die unbekannte Denktiefe "${thinking}"`);
35
- return { alias, upstream: target.slice(0, slash), model: target.slice(slash + 1), ...(thinking === undefined ? {} : { thinking }) };
36
- });
22
+ const aliasOf = (value: unknown, index: number): ModelAlias => {
23
+ const location = `MODEL_ALIASES[${index}]`;
24
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
25
+ throw new Error(`${location} must be an object with alias, model, compaction and optionally thinking`);
26
+ }
27
+ const entry = value as Record<string, unknown>;
28
+ const unknown = Object.keys(entry).find((key) => !ENTRY_KEYS.includes(key));
29
+ if (unknown) throw new Error(`${location}.${unknown} is not supported; allowed are ${ENTRY_KEYS.join(", ")}`);
30
+ if (typeof entry.alias !== "string" || !ALIAS.test(entry.alias)) {
31
+ throw new Error(`${location}.alias needs 1 to 64 lowercase letters, digits, dots, underscores or hyphens`);
32
+ }
33
+ const target = typeof entry.model === "string" ? entry.model : "";
34
+ const slash = target.indexOf("/");
35
+ if (slash <= 0 || slash === target.length - 1) throw new Error(`${location}.model of ${entry.alias} needs the form "provider/model"`);
36
+ if (entry.thinking !== undefined && !isThinkingLevel(entry.thinking)) {
37
+ throw new Error(`${location}.thinking of ${entry.alias} names the unknown thinking level "${String(entry.thinking)}"`);
38
+ }
39
+ const problem = compactionProblem(entry.compaction);
40
+ if (problem) throw new Error(`${location}, ${entry.alias}: ${problem}`);
41
+ return {
42
+ alias: entry.alias,
43
+ upstream: target.slice(0, slash),
44
+ model: target.slice(slash + 1),
45
+ ...(entry.thinking === undefined ? {} : { thinking: entry.thinking }),
46
+ compaction: entry.compaction as ModelAlias["compaction"],
47
+ };
48
+ };
49
+
50
+ /** MODEL_ALIASES: eine Liste von { alias, model: "anbieter/modell", thinking?, compaction }; der Alias ist der einzige Name, den Oberfläche, Journal und Relay-Clients sehen. */
51
+ export const parseModelAliases = (entries: unknown): readonly ModelAlias[] => {
52
+ if (!Array.isArray(entries)) throw new Error("MODEL_ALIASES must be a list of aliases");
53
+ const aliases = entries.map(aliasOf);
37
54
  const duplicate = aliases.find((entry, index) => aliases.findIndex((other) => other.alias === entry.alias) !== index);
38
- if (duplicate) throw new Error(`MODEL_ALIASES nennt den Alias ${duplicate.alias} mehrfach`);
55
+ if (duplicate) throw new Error(`MODEL_ALIASES names the alias ${duplicate.alias} more than once`);
39
56
  return aliases;
40
57
  };
41
58
 
42
59
  const env = declaredEnvironment(modelAliasEnvDescriptors);
43
60
 
44
- export const configuredModelAliases = (): readonly ModelAlias[] => parseModelAliases(env.list("MODEL_ALIASES"));
61
+ /** Die Aliasse des Profils; in der Umgebung steht MODEL_ALIASES als JSON der Liste aus der Profildatei. */
62
+ export const configuredModelAliases = (): readonly ModelAlias[] => {
63
+ const value = env.optional("MODEL_ALIASES");
64
+ if (value === undefined || value === "") return [];
65
+ let parsed: unknown;
66
+ try {
67
+ parsed = JSON.parse(value);
68
+ } catch {
69
+ throw new Error("MODEL_ALIASES is no JSON list of aliases");
70
+ }
71
+ return parseModelAliases(parsed);
72
+ };
45
73
 
46
74
  /** Der Katalog der Aliasse aus den eingebauten Katalogen ihrer Anbieter, so wie die Modelllaufzeit sie anbietet. */
47
75
  export const aliasCatalog = (aliases: readonly ModelAlias[] = configuredModelAliases()): readonly Model<Api>[] => {
48
- if (aliases.length === 0) throw new Error(`Der Anbieter ${ALIAS_PROVIDER} braucht MODEL_ALIASES im Abschnitt host`);
76
+ if (aliases.length === 0) throw new Error(`The provider ${ALIAS_PROVIDER} needs MODEL_ALIASES in the host section`);
49
77
  return aliases.map((entry) => {
50
78
  const target = getBuiltinModels(entry.upstream as BuiltinProvider).find((model) => model.id === entry.model);
51
- if (!target) throw new Error(`MODEL_ALIASES: das Modell ${entry.model} hinter ${entry.alias} fehlt im Katalog von ${entry.upstream}`);
79
+ if (!target) throw new Error(`MODEL_ALIASES: the model ${entry.model} behind ${entry.alias} is missing from the catalog of ${entry.upstream}`);
52
80
  const supported = getSupportedThinkingLevels(target);
53
81
  if (entry.thinking !== undefined && !supported.includes(entry.thinking)) {
54
- throw new Error(`MODEL_ALIASES: die Denktiefe ${entry.thinking} gibt es für ${entry.alias} nicht (gültig: ${supported.join(", ")})`);
82
+ throw new Error(`MODEL_ALIASES: the thinking level ${entry.thinking} does not exist for ${entry.alias} (valid: ${supported.join(", ")})`);
55
83
  }
56
- return aliasedModel(ALIAS_PROVIDER, entry.alias, target);
84
+ const problem = compactionProblem(entry.compaction, target);
85
+ if (problem) throw new Error(`MODEL_ALIASES: ${entry.alias} on ${entry.upstream}/${entry.model}: ${problem}`);
86
+ return aliasedModel(ALIAS_PROVIDER, entry, target);
57
87
  });
58
88
  };
59
89
 
60
- /** Die Aliasse des Profils, geprüft gegen die Kataloge ihrer Ziele samt Denktiefe. */
90
+ /** Die Aliasse des Profils, geprüft gegen die Kataloge ihrer Ziele samt Denktiefe und Kompaktierungswerten. */
61
91
  export const validatedModelAliases = (): readonly ModelAlias[] => {
62
92
  const aliases = configuredModelAliases();
63
93
  if (aliases.length > 0) aliasCatalog(aliases);
@@ -35,6 +35,8 @@ export interface ServerProcessSandboxOptions {
35
35
  /** Die Adresse dieses Servers, etwa http://127.0.0.1:4710; ohne HTTP keine. */
36
36
  readonly serverAddress: string | undefined;
37
37
  readonly dataDirectory: string;
38
+ /** Wie der Betreiber die Sandbox abschaltet, so wie er es in die Profildatei schreibt; jede Meldung, die den Start verhindert, nennt es. */
39
+ readonly disableSetting: string;
38
40
  readonly hostRoot?: string;
39
41
  readonly platform?: NodeJS.Platform;
40
42
  readonly environment?: NodeJS.ProcessEnv;
@@ -213,39 +215,38 @@ class SharedSandboxRuntime {
213
215
 
214
216
  const sharedRuntime = new SharedSandboxRuntime();
215
217
 
216
- const unsupported = (platform: NodeJS.Platform): Error => new Error(platform === "win32"
218
+ const unsupported = (platform: NodeJS.Platform, disableSetting: string): Error => new Error(platform === "win32"
217
219
  ? "Die Prozess-Sandbox gibt es auf einem Windows-Server nicht: dort lassen sich die Ordnerregeln je Run nicht setzen. "
218
- + "Wer den Server trotzdem unter Windows betreibt, schaltet sie in der Profildatei ausdrücklich ab: "
219
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace."
220
+ + `Wer den Server trotzdem unter Windows betreibt, schaltet sie in der Profildatei ausdrücklich ab: ${disableSetting}.`
220
221
  : `Die Prozess-Sandbox kennt die Plattform ${platform} nicht; unterstützt sind macOS und Linux. `
221
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace schaltet sie ausdrücklich ab.");
222
+ + `${disableSetting} schaltet sie ausdrücklich ab.`);
222
223
 
223
- const missingDependencies = (errors: readonly string[]): Error => new Error(
224
+ const missingDependencies = (errors: readonly string[], disableSetting: string): Error => new Error(
224
225
  `Die Prozess-Sandbox kann nicht starten: ${errors.join("; ")}. `
225
226
  + "Unter Linux braucht sie bubblewrap, socat und ripgrep (Debian/Ubuntu: apt-get install bubblewrap socat ripgrep). "
226
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace schaltet sie ausdrücklich ab.");
227
+ + `${disableSetting} schaltet sie ausdrücklich ab.`);
227
228
 
228
- const failedSelfTest = (detail: string): Error => new Error(
229
+ const failedSelfTest = (detail: string, disableSetting: string): Error => new Error(
229
230
  `Die Prozess-Sandbox lässt sich auf diesem Rechner nicht starten: ${detail.trim() || "ohne Ausgabe"}. `
230
231
  + "Unter Linux braucht bubblewrap Benutzer-Namensräume; in einem Container muss das Profil des Containers sie erlauben. "
231
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace schaltet sie ausdrücklich ab.");
232
+ + `${disableSetting} schaltet sie ausdrücklich ab.`);
232
233
 
233
- const runSelfTest = (launch: ProcessLaunch, environment: NodeJS.ProcessEnv): Promise<void> => new Promise((resolve, reject) => {
234
+ const runSelfTest = (launch: ProcessLaunch, environment: NodeJS.ProcessEnv, disableSetting: string): Promise<void> => new Promise((resolve, reject) => {
234
235
  const child = spawn(launch.command, [...launch.args], { stdio: ["ignore", "ignore", "pipe"], env: environment });
235
236
  let stderr = "";
236
237
  const timer = setTimeout(() => {
237
238
  child.kill("SIGKILL");
238
- reject(failedSelfTest(`keine Antwort nach ${SELF_TEST_TIMEOUT_MS / 1000} Sekunden`));
239
+ reject(failedSelfTest(`keine Antwort nach ${SELF_TEST_TIMEOUT_MS / 1000} Sekunden`, disableSetting));
239
240
  }, SELF_TEST_TIMEOUT_MS);
240
241
  child.stderr.on("data", (chunk: Buffer) => { stderr = (stderr + chunk.toString("utf8")).slice(-2_000); });
241
242
  child.once("error", (error) => {
242
243
  clearTimeout(timer);
243
- reject(failedSelfTest(error.message));
244
+ reject(failedSelfTest(error.message, disableSetting));
244
245
  });
245
246
  child.once("close", (code) => {
246
247
  clearTimeout(timer);
247
248
  if (code === 0) resolve();
248
- else reject(failedSelfTest(`Code ${code ?? "Signal"}: ${stderr}`));
249
+ else reject(failedSelfTest(`Code ${code ?? "Signal"}: ${stderr}`, disableSetting));
249
250
  });
250
251
  });
251
252
 
@@ -260,7 +261,7 @@ export class ServerProcessSandbox implements RunProcessSandboxes {
260
261
  constructor(options: ServerProcessSandboxOptions) {
261
262
  this.#options = options;
262
263
  this.#platform = options.platform ?? process.platform;
263
- if (this.#platform !== "darwin" && this.#platform !== "linux") throw unsupported(this.#platform);
264
+ if (this.#platform !== "darwin" && this.#platform !== "linux") throw unsupported(this.#platform, options.disableSetting);
264
265
  this.#protected = protectedRoots(options, this.#platform);
265
266
  this.#readable = [options.hostRoot ?? hostRoot(), ...toolchainDirectories(options, this.#protected)];
266
267
  this.#searchPath = resolvedSearchPath(options.environment ?? process.env);
@@ -269,14 +270,14 @@ export class ServerProcessSandbox implements RunProcessSandboxes {
269
270
  /** Prüft die Voraussetzungen, startet den Netz-Proxy und startet einmal einen Prozess in der Sandbox; jedes Scheitern ist ein Startfehler. */
270
271
  async start(): Promise<void> {
271
272
  const { errors } = SandboxManager.checkDependencies();
272
- if (errors.length > 0) throw missingDependencies(errors);
273
+ if (errors.length > 0) throw missingDependencies(errors, this.#options.disableSetting);
273
274
  await sharedRuntime.acquire(this, {
274
275
  network: [...this.#options.network, ...serverTarget(this.#options.serverAddress)],
275
276
  unixSockets: socketRoots(this.#options.dataDirectory, this.#platform),
276
277
  });
277
278
  try {
278
279
  const probe = this.forRun({ writable: [], readable: [], temporary: path.join(this.#options.dataDirectory, "sandbox-self-test") });
279
- await runSelfTest(await probe.wrap({ command: "true", args: [] }), this.#options.environment ?? process.env);
280
+ await runSelfTest(await probe.wrap({ command: "true", args: [] }), this.#options.environment ?? process.env, this.#options.disableSetting);
280
281
  } catch (error) {
281
282
  await sharedRuntime.release(this);
282
283
  throw error;
@@ -1,4 +1,5 @@
1
- import type { Api, Model } from "@ragents/ai";
1
+ import { compactionProblem } from "@ragents/agent";
2
+ import type { Api, Model, ModelCompaction } from "@ragents/ai";
2
3
  import type { ModelProviderRegistration } from "@ragents/engine";
3
4
 
4
5
  export const RELAY_PROVIDER = "relay";
@@ -9,7 +10,7 @@ export interface RelayConnection {
9
10
  readonly token: string;
10
11
  }
11
12
 
12
- /** Was das Relay je Alias über das dahinterliegende Modell verrät; der echte Name bleibt beim Server. */
13
+ /** Was das Relay je Alias über das dahinterliegende Modell verrät, samt den Kompaktierungswerten des Alias; der echte Name bleibt beim Server. */
13
14
  export interface RelayCatalogEntry {
14
15
  readonly id: string;
15
16
  readonly object: "model";
@@ -19,6 +20,7 @@ export interface RelayCatalogEntry {
19
20
  readonly input: Model<Api>["input"];
20
21
  readonly contextWindow: number;
21
22
  readonly maxTokens: number;
23
+ readonly compaction: ModelCompaction;
22
24
  readonly compat?: Model<Api>["compat"];
23
25
  };
24
26
  }
@@ -61,6 +63,7 @@ const modelOf = (entry: RelayCatalogEntry, baseUrl: string): Model<"openai-compl
61
63
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
62
64
  contextWindow: entry.catalog.contextWindow,
63
65
  maxTokens: entry.catalog.maxTokens,
66
+ compaction: entry.catalog.compaction,
64
67
  ...(entry.catalog.compat ? { compat: entry.catalog.compat as Model<"openai-completions">["compat"] } : {}),
65
68
  });
66
69
 
@@ -83,6 +86,10 @@ export const createRelayCatalog = (connection: RelayConnection, fetchImpl: typeo
83
86
  const body = await response.json() as { data?: unknown };
84
87
  if (!Array.isArray(body.data) || !body.data.every(isEntry)) throw new Error(`Das Modell-Relay ${address} liefert keinen gültigen Aliaskatalog`);
85
88
  if (body.data.length === 0) throw new Error(`Das Modell-Relay ${address} bietet keine Modelle an`);
89
+ for (const entry of body.data) {
90
+ const problem = compactionProblem(entry.catalog.compaction, entry.catalog);
91
+ if (problem) throw new Error(`The model relay ${address} offers ${entry.id} without valid compaction values: ${problem}`);
92
+ }
86
93
  loaded = body.data.map((entry) => modelOf(entry, baseUrl));
87
94
  return loaded;
88
95
  };
@@ -110,6 +117,7 @@ export const createRelayCatalog = (connection: RelayConnection, fetchImpl: typeo
110
117
  cost: model.cost,
111
118
  contextWindow: model.contextWindow,
112
119
  maxTokens: model.maxTokens,
120
+ ...(model.compaction ? { compaction: model.compaction } : {}),
113
121
  ...(model.compat ? { compat: model.compat } : {}),
114
122
  })),
115
123
  },
@@ -1,5 +1,6 @@
1
1
  import { mkdir, realpath } from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { Value } from "typebox/value";
3
4
  import {
4
5
  DomainError,
5
6
  serviceToken,
@@ -28,6 +29,7 @@ import {
28
29
  type SessionIdent,
29
30
  type WorkspaceExecuteOptions,
30
31
  type WorkspaceExecutor,
32
+ type WorkspaceExecutorParts,
31
33
  type WorkspaceProcessContext,
32
34
  } from "@ragents/workspace-executor";
33
35
  import { hostRoot } from "../host-version.js";
@@ -70,6 +72,8 @@ export const sandboxServicesToken = serviceToken<SandboxServices>("ragents.works
70
72
 
71
73
  export interface WorkspaceSandboxHostOptions {
72
74
  contributorName: string;
75
+ /** Was die Plugins des Profils zum Executor dieses Servers beitragen; jeder Arbeitsplatz der Runs trägt dieselben Beiträge. */
76
+ contributions: readonly WorkspaceExecutorParts[];
73
77
  workspaceFor: (runId: string) => Promise<SessionWorkspace>;
74
78
  identFor: (runId: string) => Promise<SessionIdent | undefined>;
75
79
  skillPaths: () => Promise<readonly string[]>;
@@ -83,6 +87,10 @@ export interface WorkspaceSandboxHostOptions {
83
87
  processSandbox?: RunProcessSandboxes;
84
88
  /** Die Bash des Executors dieses Servers; unter Windows Pflicht, sonst ohne Angabe die des Systems. */
85
89
  bash?: string;
90
+ /** Das rg des Executors dieses Servers; ohne Angabe gilt eines im PATH. */
91
+ rg?: string;
92
+ /** Die Zeitgrenze von bash in Sekunden für Aufrufe ohne eigene, auf jeder Maschine der Runs; ohne Angabe die des Werkzeugs. */
93
+ bashTimeoutSeconds?: number;
86
94
  }
87
95
 
88
96
  const sandboxDescriptions: Readonly<Record<string, string>> = {
@@ -98,16 +106,13 @@ const describeSandboxTool = (definition: AgentToolDefinition): AgentToolDefiniti
98
106
  return { ...definition, description, longDescription: definition.description, nativeTool: true };
99
107
  };
100
108
 
101
- const sandboxDescriptorDefinitions = [
109
+ const sandboxDefinitions = (bashTimeoutSeconds: number | undefined): readonly AgentToolDefinition[] => [
102
110
  createReadToolDefinition("."),
103
111
  createEditToolDefinition("."),
104
112
  createWriteToolDefinition("."),
105
- createBashToolDefinition("."),
113
+ createBashToolDefinition(".", bashTimeoutSeconds === undefined ? {} : { defaultTimeoutSeconds: bashTimeoutSeconds }),
106
114
  ] as readonly AgentToolDefinition[];
107
115
 
108
- const sandboxDescriptors = sandboxDescriptorDefinitions.map((definition) =>
109
- toolDescriptorFrom(describeSandboxTool(definition), alwaysAvailable));
110
-
111
116
  const fileToolNames = new Set(["read", "edit", "write"]);
112
117
 
113
118
  interface StableRunParts {
@@ -142,6 +147,7 @@ const existingRoots = async (roots: readonly ResolvedWorkspaceRoot[]): Promise<R
142
147
  /** Der Executor des Servers mit den Wurzeln des Servers; eine Operation mit Alias läuft dort, jede andere beim Executor der Bindung des Runs. */
143
148
  export class WorkspaceSandboxHost implements SandboxServices {
144
149
  readonly #options: WorkspaceSandboxHostOptions;
150
+ readonly #definitions: readonly AgentToolDefinition[];
145
151
  readonly #workspaceRoots: RegisteredWorkspaceRoot[] = [];
146
152
  readonly #local: WorkspaceOperationExecutor;
147
153
  readonly #stable = new Map<string, Promise<StableRunParts>>();
@@ -150,9 +156,10 @@ export class WorkspaceSandboxHost implements SandboxServices {
150
156
 
151
157
  constructor(options: WorkspaceSandboxHostOptions) {
152
158
  this.#options = options;
159
+ this.#definitions = sandboxDefinitions(options.bashTimeoutSeconds);
153
160
  this.#local = new WorkspaceOperationExecutor({
154
161
  contextFor: (runId) => this.serverProcessContextFor(runId),
155
- modules: workspaceExecutorModules(),
162
+ modules: workspaceExecutorModules({ contributions: options.contributions }),
156
163
  });
157
164
  }
158
165
 
@@ -234,6 +241,7 @@ export class WorkspaceSandboxHost implements SandboxServices {
234
241
  runOperation: workspace.runOperation,
235
242
  ...(sandbox ? { sandbox } : {}),
236
243
  ...(this.#options.bash === undefined ? {} : { bash: this.#options.bash }),
244
+ ...(this.#options.rg === undefined ? {} : { rg: this.#options.rg }),
237
245
  });
238
246
  }
239
247
 
@@ -288,7 +296,7 @@ export class WorkspaceSandboxHost implements SandboxServices {
288
296
  workspaceTools(): ToolContributor {
289
297
  return {
290
298
  name: this.#options.contributorName,
291
- descriptors: sandboxDescriptors,
299
+ descriptors: this.#definitions.map((definition) => toolDescriptorFrom(describeSandboxTool(definition), alwaysAvailable)),
292
300
  tools: (context) => this.#workspaceToolsFor(context),
293
301
  };
294
302
  }
@@ -330,12 +338,13 @@ export class WorkspaceSandboxHost implements SandboxServices {
330
338
  }
331
339
 
332
340
  #workspaceToolsFor(context: PluginContext): Promise<RunFunction[]> {
333
- return Promise.resolve(sandboxDescriptorDefinitions.map((definition) => {
341
+ return Promise.resolve(this.#definitions.map((definition) => {
334
342
  const described = describeSandboxTool(definition);
335
343
  const proxy = {
336
344
  ...described,
345
+ // Die Vorgaben des Schemas, etwa die Zeitgrenze von bash, setzt der Server ein; so gilt auf jeder Maschine, was das Modell im Schema sieht.
337
346
  execute: (toolCallId: string, params: unknown, signal: AbortSignal | undefined) =>
338
- this.execute(context.runId, described.name, params, {
347
+ this.execute(context.runId, described.name, Value.Default(described.parameters, structuredClone(params)), {
339
348
  toolCallId,
340
349
  ...(signal ? { signal } : {}),
341
350
  }),
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "node:fs";
3
3
  import path from "node:path";
4
+ import { EXECUTOR_CONTRIBUTION_FILE } from "@ragents/workspace-executor";
4
5
  import { ragentsDataRoot } from "../data-directory.js";
5
6
  import { filesBelow } from "../folder-install.js";
6
7
  import { HOST_API_VERSION, type HostApiHalf } from "../host-api.js";
@@ -9,7 +10,7 @@ import { isCheckout } from "../host-web.js";
9
10
  import { bundlesRoot, pluginIdOf } from "../plugin-support/plugins-root.js";
10
11
 
11
12
  export const BUNDLE_MANIFEST_FILE = "ragents-bundle.json";
12
- export const BUNDLE_FORMAT = 3;
13
+ export const BUNDLE_FORMAT = 4;
13
14
 
14
15
  /** The value names a half imports from each module of the host API. */
15
16
  export type HostNames = Readonly<Record<string, readonly string[]>>;
@@ -27,12 +28,14 @@ export interface BundleManifest {
27
28
  readonly sourceStand: string;
28
29
  readonly server: string;
29
30
  readonly web?: { readonly entry: string; readonly css?: string; readonly classes: string };
31
+ /** The contribution to every executor, a self-contained file that any Node process loads. */
32
+ readonly executor?: typeof EXECUTOR_CONTRIBUTION_FILE;
30
33
  readonly exports: Readonly<Record<HostApiHalf, Readonly<Record<string, string>>>>;
31
34
  readonly uses: readonly string[];
32
35
  readonly assets: readonly string[];
33
36
  }
34
37
 
35
- const MANIFEST_KEYS = new Set(["format", "id", "api", "hostNames", "stand", "sourceStand", "server", "web", "exports", "uses", "assets"]);
38
+ const MANIFEST_KEYS = new Set(["format", "id", "api", "hostNames", "stand", "sourceStand", "server", "web", "executor", "exports", "uses", "assets"]);
36
39
  const SOURCE_MARKERS = ["ragents-plugin.json", "server/index.ts", "server/index.tsx"];
37
40
 
38
41
  const isRecord = (value: unknown): value is Record<string, unknown> =>
@@ -167,6 +170,7 @@ export const readBundleManifest = (folder: string): BundleManifest => {
167
170
  ...(typeof raw.sourceStand === "string" ? [] : ["sourceStand"]),
168
171
  ...(typeof raw.server === "string" ? [] : ["server"]),
169
172
  ...(isWeb(raw.web) ? [] : ["web"]),
173
+ ...(raw.executor === undefined || raw.executor === EXECUTOR_CONTRIBUTION_FILE ? [] : ["executor"]),
170
174
  ...(isRecord(raw.exports) && isPathRecord(raw.exports.server) && isPathRecord(raw.exports.web) ? [] : ["exports"]),
171
175
  ...(isStringList(raw.uses) ? [] : ["uses"]),
172
176
  ...(isStringList(raw.assets) ? [] : ["assets"]),
@@ -176,7 +180,7 @@ export const readBundleManifest = (folder: string): BundleManifest => {
176
180
  const webFiles = web === undefined ? [] : [web.entry, web.classes, ...(web.css === undefined ? [] : [web.css])];
177
181
  const misplaced = webFiles.filter((entry) => !entry.startsWith("web/") || entry.split("/").includes(".."));
178
182
  if (misplaced.length > 0) throw new Error(`${file}: ${misplaced.join(", ")} liegt nicht unter web/; ${rebuildHint(folder)}`);
179
- for (const required of [raw.server as string, ...webFiles]) {
183
+ for (const required of [raw.server as string, ...webFiles, ...(raw.executor === undefined ? [] : [EXECUTOR_CONTRIBUTION_FILE])]) {
180
184
  if (!statSync(path.join(folder, required), { throwIfNoEntry: false })?.isFile()) throw new Error(`Dem Bundle ${id} fehlt ${required}; ${rebuildHint(folder)}`);
181
185
  }
182
186
  return raw as unknown as BundleManifest;
@@ -1,4 +1,5 @@
1
1
  import { PluginHost, type PluginWebAddresses } from "@ragents/engine";
2
+ import { pluginToolsDirectory, prepareExecutorContribution, type LoadedExecutorContribution } from "@ragents/workspace-executor";
2
3
  import { config, HOST_SECRET_ENV_NAMES } from "../config.js";
3
4
  import { SESSION_MODE, SESSIONS_MODE } from "../layout.js";
4
5
  import { withFolderAssets } from "../plugin-support/plugin-folder.js";
@@ -6,6 +7,7 @@ import type { PluginModule } from "../plugin-support/plugin-module.js";
6
7
  import { runManagementToken } from "../ragents/global-chat.js";
7
8
  import { registerTypeScriptFunctions } from "../ragents/typescript-tools.js";
8
9
  import {
10
+ executorContributionsToken,
9
11
  hostAddressToken,
10
12
  runtimeProviderToken,
11
13
  secretEnvNamesToken,
@@ -27,6 +29,8 @@ export interface ProfileComposition {
27
29
  readonly modules: ReadonlyMap<string, PluginModule>;
28
30
  /** The plugins with a web half and where the browser loads it; the web loads exactly these. */
29
31
  readonly web: ReadonlyMap<string, PluginWebAddresses>;
32
+ /** Die Beiträge der Bundles zum Executor; der Server baut sie mit den Werkzeugordnern seines Datenordners. */
33
+ readonly executor: readonly LoadedExecutorContribution[];
30
34
  /** Die Vorlage aus defaultStartEntry der Profildatei; der Host lehnt eine nicht registrierte beim Versiegeln ab. */
31
35
  readonly defaultStartEntry?: string;
32
36
  }
@@ -43,6 +47,8 @@ export const composeProfile = (options: ProfileComposition, bridges: HostBridges
43
47
  host.provideHost(runWorkspaceProviderToken, bridges.sessionWorkspaceFor);
44
48
  host.provideHost(runtimeProviderToken, bridges.runtime);
45
49
  host.provideHost(hostAddressToken, () => bridges.apiBaseUrl);
50
+ host.provideHost(executorContributionsToken, options.executor.map((loaded) =>
51
+ prepareExecutorContribution(loaded, pluginToolsDirectory(config.dataDir, loaded.plugin))));
46
52
  host.provideHost(runManagementToken, () => {
47
53
  if (!bridges.sessions) throw new Error("Der Host stellt keine Sitzungsverwaltung bereit");
48
54
  return bridges.sessions();
@@ -2,6 +2,7 @@ import { existsSync, readdirSync, realpathSync, statSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import type { PluginWebAddresses } from "@ragents/engine";
5
+ import { loadExecutorContribution, type LoadedExecutorContribution } from "@ragents/workspace-executor";
5
6
  import { announceBundles } from "../host-resolution.js";
6
7
  import { checkedHostApiRecord } from "../host-version.js";
7
8
  import { isPluginModule, type PluginModule } from "../plugin-support/plugin-module.js";
@@ -133,6 +134,8 @@ export interface LoadedPlugins {
133
134
  readonly bundles: readonly ResolvedPlugin[];
134
135
  /** The plugins whose bundle carries a web half, with the addresses the browser loads it from. */
135
136
  readonly web: ReadonlyMap<string, PluginWebAddresses>;
137
+ /** The contributions to every executor, in the order of the plugin list; each machine builds them for itself. */
138
+ readonly executor: readonly LoadedExecutorContribution[];
136
139
  }
137
140
 
138
141
  export const loadPlugins = async (
@@ -160,5 +163,7 @@ export const loadPlugins = async (
160
163
  const addresses = webAddressesOf(plugin);
161
164
  return addresses === undefined ? [] : [[plugin.id, addresses] as const];
162
165
  }));
163
- return { known, ids, modules, bundles: plugins, web };
166
+ const executor = await Promise.all(plugins.flatMap((plugin) => plugin.manifest.executor === undefined ? []
167
+ : [loadExecutorContribution(plugin.id, path.join(plugin.folder, plugin.manifest.executor))]));
168
+ return { known, ids, modules, bundles: plugins, web, executor };
164
169
  };
@@ -1,10 +1,7 @@
1
1
  import { mkdir } from "node:fs/promises";
2
2
  import { hostDataDirectory, pluginToolsDirectory } from "@ragents/workspace-executor/src/tools.ts";
3
3
  import { isPluginProvision, type PluginProvision } from "../plugin-support/provision.js";
4
- import { importBundles, resolvePluginEntries, type ResolvedPlugin } from "./plugin-discovery.js";
5
-
6
- /** Die Plugins, deren Werkzeuge jeder Arbeitsplatz-Executor auf seiner Maschine braucht: Sprachserver und Browser. */
7
- export const WORKSPACE_PROVISION_PLUGINS = ["ragents.lsp-roslyn", "ragents.lsp-fsharp", "ragents.browser"] as const;
4
+ import { discoverPluginIds, importBundles, resolvePluginEntries, type ResolvedPlugin } from "./plugin-discovery.js";
8
5
 
9
6
  /** The provisioning a bundle exports next to its plugin, if it brings one. */
10
7
  const provisionOf = (plugin: ResolvedPlugin, exported: Readonly<Record<string, unknown>>): PluginProvision | undefined => {
@@ -81,5 +78,9 @@ const withUsedBundles = (ids: readonly string[]): readonly ResolvedPlugin[] => {
81
78
  return [...resolved.values()];
82
79
  };
83
80
 
81
+ /** Ein Arbeitsplatz hat kein Profil; er provisioniert die eingebauten Plugins seines Hosts, die zum Executor beitragen, denn deren Werkzeuge laufen auf ihm. */
82
+ export const workspaceProvisionPlugins = (): readonly ResolvedPlugin[] => withUsedBundles(
83
+ resolvePluginEntries(discoverPluginIds()).filter((plugin) => plugin.manifest.executor !== undefined).map((plugin) => plugin.id));
84
+
84
85
  export const provisionWorkspace = (log: (line: string) => void): Promise<readonly PluginProvisionReport[]> =>
85
- provisionPlugins(withUsedBundles(WORKSPACE_PROVISION_PLUGINS), hostDataDirectory(), log);
86
+ provisionPlugins(workspaceProvisionPlugins(), hostDataDirectory(), log);
@@ -366,7 +366,7 @@ export class RunSessionProvider implements ChatSessionProvider {
366
366
  else if (start.kind === "package") {
367
367
  if (!local) throw new Error("Das Run-Script-Paket wurde nicht geladen");
368
368
  const { script, ...entry } = local;
369
- await session.startPackageAndWait({ ...script, entry: { ...entry, coordinator: script.coordinator, owner: "ragents.overseer" } }, start.input, user);
369
+ await session.startPackageAndWait({ ...script, entry: { ...entry, coordinator: script.coordinator, owner: start.owner } }, start.input, user);
370
370
  }
371
371
  else await session.sendAndWait(start.message, user);
372
372
  return id;
@@ -398,7 +398,7 @@ export class RunSessionProvider implements ChatSessionProvider {
398
398
 
399
399
  runView(id: string, access: AccessContext = unrestrictedAccess): unknown {
400
400
  this.ensureUsable(id);
401
- return accessibleRunView(this.requireEngine().runtime.view(id), access);
401
+ return accessibleRunView(this.requireEngine().runtime.view(id), access, this.plugins.accessProjections);
402
402
  }
403
403
 
404
404
  hasRun(id: string): boolean {
@@ -32,6 +32,7 @@ import {
32
32
  type PublicPromptSnapshot,
33
33
  type RunStopBoundary,
34
34
  type RunStopOperation,
35
+ type RunView,
35
36
  type StartOptionContributionRegistry,
36
37
  type Workspaces,
37
38
  } from "@ragents/engine";
@@ -206,7 +207,6 @@ export const createEngine = async (options: EngineOptions): Promise<Engine> => {
206
207
  resolveSkills: async (context) => globalChat?.isCoordinator(context.runId) ? []
207
208
  : (await options.plugins.skills.resolve(contributionContextFor(context))).map(skillOfDirectory),
208
209
  resolveHooks: (context) => globalChat?.isCoordinator(context.runId) ? [] : options.plugins.agentRuntime.resolve(contributionContextFor(context)),
209
- settings: { compaction: config.agentCompaction },
210
210
  });
211
211
  const configuredModels = await Promise.all(options.plugins.profiles.models().map(async (model) => {
212
212
  if (model.driver !== "agent") return model;
@@ -398,7 +398,7 @@ export const createEngine = async (options: EngineOptions): Promise<Engine> => {
398
398
  assertAvailable: options.assertAvailable,
399
399
  assertRunUsable: options.assertRunUsable,
400
400
  assertRunRights: (access: AccessContext, runId: string, kind: RunRightsKind) => assertRunRights(access, runId, kind, runAccess),
401
- projectView: accessibleRunView,
401
+ projectView: (view: RunView, access: AccessContext) => accessibleRunView(view, access, options.plugins.accessProjections),
402
402
  hasRun: (runId: string) => journal.stateOf(runId) !== null,
403
403
  };
404
404
  const methods = runtimeMethods({
@@ -31,7 +31,13 @@ export type ManagedRunStart = {
31
31
  /** Wer die Startoptionen wählt und den Run besitzt: der Benutzer der Anfrage, null ohne Anmeldung. */
32
32
  user: ChatUser | null;
33
33
  } & ({ kind: "message"; message: string } | { kind: "script"; entryId: string; input: JsonValue }
34
- | { kind: "package"; directory: string; input: JsonValue });
34
+ | {
35
+ kind: "package";
36
+ directory: string;
37
+ input: JsonValue;
38
+ /** Das Plugin, das das Paket startet; es steht als Besitzer der Vorlage dieses Starts. */
39
+ owner: string;
40
+ });
35
41
 
36
42
  export interface RunManagement {
37
43
  /** Mit einem Zugang bleiben nur dessen eigene Runs übrig; ohne ihn ist es die Liste des Servers. */
@@ -5,6 +5,7 @@ import {
5
5
  type PluginHost,
6
6
  type ServiceToken,
7
7
  } from "@ragents/engine";
8
+ import type { PreparedExecutorContribution } from "@ragents/workspace-executor";
8
9
  import type { SessionWorkspace } from "./workspace-runtime.js";
9
10
  import type { RunManagement } from "./global-chat.js";
10
11
 
@@ -23,6 +24,9 @@ export const runtimeProviderToken: ServiceToken<() => Orchestration> = serviceTo
23
24
  /** Die Adresse, unter der dieser Server seine API anbietet, etwa http://127.0.0.1:4710; ohne HTTP (nur stdio) keine. */
24
25
  export const hostAddressToken: ServiceToken<() => string | undefined> = serviceToken("host.address");
25
26
 
27
+ /** Die Beiträge der Bundles dieses Profils zum Executor, gebaut für den Server; jeder Executor des Servers trägt sie, jeder Arbeitsplatz dieselben. */
28
+ export const executorContributionsToken: ServiceToken<readonly PreparedExecutorContribution[]> = serviceToken("host.executor-contributions");
29
+
26
30
  export interface HostBridges {
27
31
  ensureSession: (runId: string) => void;
28
32
  ensureWorkspaceAccess: (access: AccessContext, runId: string) => void;
@@ -464,7 +464,7 @@ export class RunChatSession implements ChatSessionLike {
464
464
  this.#engine.runtime.enqueueInput(
465
465
  { actorId: state.ownerId, commandId: `chat:${randomUUID()}` },
466
466
  this.id,
467
- { actorId: primaryActorId, content: text, artifactIds, sourceEventIds },
467
+ { actorId: primaryActorId, content: text, artifactIds, sourceEventIds, origin: "human" },
468
468
  );
469
469
  }
470
470
 
@@ -23,7 +23,7 @@ import { Protocol, teeConsole } from "./protocol.js";
23
23
  import { RunSessionProvider } from "./provider.js";
24
24
  import { readHelpResponse } from "./help-files.js";
25
25
  import { watchParentProcess } from "./parent-watch.js";
26
- import { hostRoot } from "./host-version.js";
26
+ import { hostRoot, readPackageVersion } from "./host-version.js";
27
27
  import { hostWebProblem, isCheckout } from "./host-web.js";
28
28
  import { createStylesheet, STYLESHEET_PATH } from "./web-stylesheet.js";
29
29
  import { isBundleSourceMap, isPublicBundleFile, isWebBundlePath, webBundleFile } from "./web-bundles.js";
@@ -170,6 +170,7 @@ const composition: ProfileComposition = {
170
170
  pluginIds: loaded.ids,
171
171
  modules: loaded.modules,
172
172
  web: loaded.web,
173
+ executor: loaded.executor,
173
174
  ...(defaultStartEntry !== undefined ? { defaultStartEntry } : {}),
174
175
  };
175
176
 
@@ -213,6 +214,7 @@ provider.plugins.methods.register("host", [
213
214
  ...coreMethods({
214
215
  sessions: provider,
215
216
  plugins: provider.plugins,
217
+ version: readPackageVersion(),
216
218
  global: globalAccess,
217
219
  runOwner: (runId) => provider.runOwner(runId),
218
220
  runOwnerOnly: (runId) => provider.runOwnerOnly(runId),
@@ -222,6 +224,7 @@ provider.plugins.methods.register("host", [
222
224
  ]);
223
225
  provider.plugins.channels.register("host", coreChannels({
224
226
  sessions: provider,
227
+ plugins: provider.plugins,
225
228
  global: globalAccess,
226
229
  runOwner: (runId) => provider.runOwner(runId),
227
230
  runOwnerOnly: (runId) => provider.runOwnerOnly(runId),
@@ -33,6 +33,8 @@
33
33
  "src",
34
34
  "../../plugins/*/server",
35
35
  "../../plugins/*/contract.ts",
36
+ "../../plugins/*/executor.ts",
37
+ "../../plugins/*/executor",
36
38
  "../../ragents.config.*.ts"
37
39
  ]
38
40
  }
@@ -1 +1 @@
1
- import{r,S as d,E as p,j as E,c as f}from"./mermaid-HWGCJPDP-DfsU5ofC.js";var j=({code:i,language:e,maxHeight:o,raw:a,className:u,startLine:m,lineNumbers:n,...h})=>{let{shikiTheme:l}=r.useContext(d),t=p(),[c,s]=r.useState(a);return r.useEffect(()=>{if(!t){s(a);return}let g=t.highlight({code:i,language:e,themes:l},x=>{s(x)});g&&s(g)},[i,e,l,t,a]),E.jsx(f,{className:u,language:e,lineNumbers:n,maxHeight:o,result:c,startLine:m,...h})};export{j as HighlightedCodeBlockBody};
1
+ import{r,S as d,E as p,j as E,c as f}from"./mermaid-HWGCJPDP-BLLeth5_.js";var j=({code:i,language:e,maxHeight:o,raw:a,className:u,startLine:m,lineNumbers:n,...h})=>{let{shikiTheme:l}=r.useContext(d),t=p(),[c,s]=r.useState(a);return r.useEffect(()=>{if(!t){s(a);return}let g=t.highlight({code:i,language:e,themes:l},x=>{s(x)});g&&s(g)},[i,e,l,t,a]),E.jsx(f,{className:u,language:e,lineNumbers:n,maxHeight:o,result:c,startLine:m,...h})};export{j as HighlightedCodeBlockBody};