@schlenkr/ragents 0.1.7 → 0.1.9

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 (187) hide show
  1. package/apps/server/src/config-definition.ts +24 -2
  2. package/apps/server/src/config.ts +0 -6
  3. package/apps/server/src/host-api.json +3 -10
  4. package/apps/server/src/host-api.ts +6 -7
  5. package/apps/server/src/plugin-build/build.ts +28 -5
  6. package/apps/server/src/plugin-build/plugin-description.ts +1 -1
  7. package/apps/server/src/plugin-build/typecheck.ts +2 -2
  8. package/apps/server/src/plugin-support/language-server/plugin.ts +8 -7
  9. package/apps/server/src/plugin-support/language-server/tools.ts +7 -6
  10. package/apps/server/src/plugin-support/model-aliases.ts +55 -25
  11. package/apps/server/src/plugin-support/plugin-folder.ts +2 -1
  12. package/apps/server/src/plugin-support/product-relay.ts +10 -2
  13. package/apps/server/src/plugin-support/workspace-sandbox-host.ts +18 -9
  14. package/apps/server/src/profile/bundle-manifest.ts +7 -3
  15. package/apps/server/src/profile/compose.ts +6 -0
  16. package/apps/server/src/profile/plugin-discovery.ts +6 -1
  17. package/apps/server/src/profile/provisioning.ts +6 -5
  18. package/apps/server/src/ragents/engine.ts +18 -12
  19. package/apps/server/src/ragents/host-services.ts +4 -0
  20. package/apps/server/src/ragents/session.ts +1 -1
  21. package/apps/server/src/server.ts +1 -0
  22. package/apps/server/tsconfig.json +2 -0
  23. package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-CFhTJEmH.js → highlighted-body-KPVGNVTW-xXXhTDbh.js} +1 -1
  24. package/apps/web/dist/assets/{main-DlzW4t4c.js → main-C7JeZFjs.js} +1 -1
  25. package/apps/web/dist/assets/{mermaid-HWGCJPDP-kxkB991i.js → mermaid-HWGCJPDP-DfsU5ofC.js} +2 -2
  26. package/apps/web/dist/assets/{runPanel-BJEFQ__w.js → runPanel-ZT6TPDLM.js} +1 -1
  27. package/apps/web/dist/help/guide-clients.html +14 -6
  28. package/apps/web/dist/help/guide-clients.md +14 -6
  29. package/apps/web/dist/help/guide-distributed.html +12 -4
  30. package/apps/web/dist/help/guide-distributed.md +12 -4
  31. package/apps/web/dist/help/guide-getting-started.html +12 -8
  32. package/apps/web/dist/help/guide-getting-started.md +12 -8
  33. package/apps/web/dist/help/guide-plugins.html +6 -2
  34. package/apps/web/dist/help/guide-plugins.md +6 -2
  35. package/apps/web/dist/help/guide-runtime.html +2 -1
  36. package/apps/web/dist/help/guide-runtime.md +2 -1
  37. package/apps/web/dist/help/index.html +3328 -1135
  38. package/apps/web/dist/host-web.json +4 -4
  39. package/apps/web/dist/index.html +2 -2
  40. package/apps/web/dist/run-panel.html +2 -2
  41. package/apps/web/src/StartTiles.tsx +1 -1
  42. package/bundles/ragents.activity/ragents-bundle.json +3 -3
  43. package/bundles/ragents.actor-programs/ragents-bundle.json +3 -3
  44. package/bundles/ragents.ask/ragents-bundle.json +4 -4
  45. package/bundles/ragents.ask/server/index.js +42 -11
  46. package/bundles/ragents.ask/server/index.js.map +3 -3
  47. package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js +2 -0
  48. package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js.map +7 -0
  49. package/bundles/ragents.ask/web/classes.json +1 -1
  50. package/bundles/ragents.ask/web/exports/ask-payload.js +1 -1
  51. package/bundles/ragents.ask/web/index.js +1 -1
  52. package/bundles/ragents.ask/web/index.js.map +3 -3
  53. package/bundles/ragents.browser/executor/index.mjs +357 -0
  54. package/bundles/ragents.browser/executor/index.mjs.map +7 -0
  55. package/bundles/ragents.browser/ragents-bundle.json +5 -8
  56. package/bundles/ragents.browser/server/chunks/{chunk-2GKLLCBE.js → chunk-CWLX4VA5.js} +1 -1
  57. package/bundles/ragents.browser/server/chunks/chunk-CWLX4VA5.js.map +7 -0
  58. package/bundles/ragents.browser/server/exports/server/contract.js +1 -1
  59. package/bundles/ragents.browser/server/index.js +20 -9
  60. package/bundles/ragents.browser/server/index.js.map +4 -4
  61. package/bundles/ragents.documents/ragents-bundle.json +3 -3
  62. package/bundles/ragents.lsp-fsharp/executor/index.mjs +68 -0
  63. package/bundles/ragents.lsp-fsharp/executor/index.mjs.map +7 -0
  64. package/bundles/ragents.lsp-fsharp/ragents-bundle.json +5 -9
  65. package/bundles/ragents.lsp-fsharp/server/index.js +21 -6
  66. package/bundles/ragents.lsp-fsharp/server/index.js.map +4 -4
  67. package/bundles/ragents.lsp-roslyn/executor/index.mjs +68 -0
  68. package/bundles/ragents.lsp-roslyn/executor/index.mjs.map +7 -0
  69. package/bundles/ragents.lsp-roslyn/ragents-bundle.json +6 -8
  70. package/bundles/ragents.lsp-roslyn/server/index.js +54 -15
  71. package/bundles/ragents.lsp-roslyn/server/index.js.map +4 -4
  72. package/bundles/ragents.lsp-typescript/executor/index.mjs +49 -0
  73. package/bundles/ragents.lsp-typescript/executor/index.mjs.map +7 -0
  74. package/bundles/ragents.lsp-typescript/ragents-bundle.json +5 -7
  75. package/bundles/ragents.lsp-typescript/server/index.js +22 -2
  76. package/bundles/ragents.lsp-typescript/server/index.js.map +3 -3
  77. package/bundles/ragents.model-relay/ragents-bundle.json +4 -4
  78. package/bundles/ragents.model-relay/server/index.js +3 -2
  79. package/bundles/ragents.model-relay/server/index.js.map +2 -2
  80. package/bundles/ragents.orchestration/ragents-bundle.json +3 -3
  81. package/bundles/ragents.overseer/ragents-bundle.json +3 -3
  82. package/bundles/ragents.processes/ragents-bundle.json +3 -3
  83. package/bundles/ragents.product/ragents-bundle.json +3 -3
  84. package/bundles/ragents.profile-distribution/ragents-bundle.json +4 -4
  85. package/bundles/ragents.profile-distribution/server/index.js +1 -1
  86. package/bundles/ragents.profile-distribution/server/index.js.map +2 -2
  87. package/bundles/ragents.reference/ragents-bundle.json +3 -3
  88. package/bundles/ragents.todo/ragents-bundle.json +3 -3
  89. package/bundles/ragents.transcript/ragents-bundle.json +3 -3
  90. package/bundles/ragents.watch/ragents-bundle.json +3 -3
  91. package/bundles/ragents.workspace/ragents-bundle.json +11 -5
  92. package/bundles/ragents.workspace/server/index.js +101 -28
  93. package/bundles/ragents.workspace/server/index.js.map +3 -3
  94. package/bundles/ragents.workspace/web/classes.json +1 -1
  95. package/bundles/ragents.workspace/web/index.js +1 -1
  96. package/bundles/ragents.workspace/web/index.js.map +3 -3
  97. package/package.json +2 -2
  98. package/packages/agent/dist/core/agent-settings.d.ts +1 -7
  99. package/packages/agent/dist/core/compaction/compaction.d.ts +17 -13
  100. package/packages/agent/dist/core/model-runtime.d.ts +5 -4
  101. package/packages/agent/dist/core/provider-composer.d.ts +2 -1
  102. package/packages/agent/dist/core/tools/bash.d.ts +9 -3
  103. package/packages/agent/dist/index.d.ts +1 -1
  104. package/packages/agent/src/core/agent-settings.ts +1 -4
  105. package/packages/agent/src/core/compaction/compaction.ts +68 -30
  106. package/packages/agent/src/core/model-runtime.ts +12 -5
  107. package/packages/agent/src/core/provider-composer.ts +5 -0
  108. package/packages/agent/src/core/tools/bash.ts +36 -30
  109. package/packages/agent/src/index.ts +3 -0
  110. package/packages/ai/dist/types.d.ts +11 -0
  111. package/packages/ai/src/types.ts +12 -0
  112. package/packages/ragents/src/agents/plugins.ts +5 -0
  113. package/packages/ragents/src/domain/event-semantics.ts +3 -0
  114. package/packages/ragents/src/domain/event-validation.ts +15 -2
  115. package/packages/ragents/src/domain/events.ts +3 -0
  116. package/packages/ragents/src/domain/model.ts +2 -0
  117. package/packages/ragents/src/domain/projection.ts +1 -0
  118. package/packages/ragents/src/drivers/agent-runtime.ts +1 -1
  119. package/packages/ragents/src/drivers/agent-turn.ts +8 -6
  120. package/packages/ragents/src/index.ts +1 -0
  121. package/packages/ragents/src/plugin-host.ts +58 -10
  122. package/packages/ragents/src/plugin-types.ts +7 -2
  123. package/packages/ragents/src/runtime/decisions/inputs.ts +6 -2
  124. package/packages/ragents/src/runtime/journal-storage.ts +5 -4
  125. package/packages/workspace-executor/package.json +0 -1
  126. package/packages/workspace-executor/src/bash-launch.ts +56 -10
  127. package/packages/workspace-executor/src/context.ts +4 -0
  128. package/packages/workspace-executor/src/contributions.ts +150 -0
  129. package/packages/workspace-executor/src/executor.ts +1 -1
  130. package/packages/workspace-executor/src/index.ts +16 -19
  131. package/packages/workspace-executor/src/language-server/host.ts +3 -0
  132. package/packages/workspace-executor/src/language-server/module.ts +12 -2
  133. package/packages/workspace-executor/src/language-server/roots.ts +0 -5
  134. package/packages/workspace-executor/src/modules.ts +7 -6
  135. package/packages/workspace-executor/src/sandbox-tools.ts +3 -9
  136. package/packages/workspace-executor/src/shell-platform.ts +14 -3
  137. package/packages/workspace-executor/src/tools.ts +0 -3
  138. package/plugins/ragents.ask/ask-payload.ts +9 -0
  139. package/plugins/ragents.ask/server/ask-service.ts +53 -13
  140. package/plugins/ragents.ask/web/AskActionView.tsx +3 -2
  141. package/plugins/ragents.browser/executor/index.ts +5 -0
  142. package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/module.ts +25 -31
  143. package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/playwright.ts +9 -23
  144. package/plugins/ragents.browser/provision.ts +1 -1
  145. package/plugins/ragents.browser/server/browser.ts +3 -3
  146. package/plugins/ragents.browser/server/contract.ts +2 -2
  147. package/plugins/ragents.browser/server/index.ts +1 -1
  148. package/plugins/ragents.lsp-fsharp/executor.ts +80 -0
  149. package/plugins/ragents.lsp-fsharp/provision.ts +1 -1
  150. package/plugins/ragents.lsp-fsharp/server/index.ts +2 -2
  151. package/plugins/ragents.lsp-roslyn/executor.ts +64 -0
  152. package/plugins/ragents.lsp-roslyn/provision.ts +1 -1
  153. package/plugins/ragents.lsp-roslyn/server/index.ts +28 -5
  154. package/plugins/ragents.lsp-roslyn/server/solution-on-start.ts +18 -6
  155. package/plugins/ragents.lsp-typescript/executor.ts +50 -0
  156. package/plugins/ragents.lsp-typescript/server/index.ts +2 -2
  157. package/plugins/ragents.model-relay/server/config.ts +1 -1
  158. package/plugins/ragents.model-relay/server/relay.ts +4 -2
  159. package/plugins/ragents.profile-distribution/server/archive.ts +2 -1
  160. package/plugins/ragents.workspace/client/workspace-client.ts +111 -28
  161. package/plugins/ragents.workspace/contract.ts +33 -2
  162. package/plugins/ragents.workspace/server/binding.ts +10 -4
  163. package/plugins/ragents.workspace/server/clients.ts +56 -9
  164. package/plugins/ragents.workspace/server/config.ts +9 -0
  165. package/plugins/ragents.workspace/server/index.ts +13 -4
  166. package/plugins/ragents.workspace/server/runtime.ts +10 -0
  167. package/plugins/ragents.workspace/server/shell-platform.ts +6 -5
  168. package/plugins/ragents.workspace/web/WorkspaceBinding.tsx +1 -1
  169. package/ragents.config.core.ts +4 -1
  170. package/ragents.config.showcase.ts +4 -1
  171. package/scripts/agent/journal.ts +3 -1
  172. package/scripts/package/build-package.ts +3 -1
  173. package/scripts/package/publish-package.ts +4 -3
  174. package/scripts/provision/run-provision.ts +2 -2
  175. package/scripts/workspace-client/run-workspace-client.ts +7 -4
  176. package/apps/web/dist/help/screenshots/release-checklist-vscode.png +0 -0
  177. package/apps/web/dist/help/screenshots/release-checklist-web.png +0 -0
  178. package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js +0 -2
  179. package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js.map +0 -7
  180. package/bundles/ragents.browser/server/chunks/chunk-2GKLLCBE.js.map +0 -7
  181. package/packages/workspace-executor/src/language-server/adapters/fsharp.ts +0 -60
  182. package/packages/workspace-executor/src/language-server/adapters/index.ts +0 -7
  183. package/packages/workspace-executor/src/language-server/adapters/roslyn.ts +0 -56
  184. package/packages/workspace-executor/src/language-server/adapters/typescript.ts +0 -74
  185. package/packages/workspace-executor/src/language-server/solution.ts +0 -13
  186. /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/contract.ts +0 -0
  187. /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/pages.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.processes",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -78,7 +78,7 @@
78
78
  }
79
79
  },
80
80
  "stand": "987603befb33bb6cbdf130bf48c606f09549cfcce8811ffcef62a235640d79f5",
81
- "sourceStand": "8c4a54ab7237c74d3fc000b6e0fcc400a7a9b2f9b53219a3b78587f37f978abe",
81
+ "sourceStand": "b20b106082b28d9bf7abcee5e45584220f512422310923eb2977bfa142346e0a",
82
82
  "server": "server/index.js",
83
83
  "web": {
84
84
  "entry": "web/index.js",
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.product",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -76,7 +76,7 @@
76
76
  }
77
77
  },
78
78
  "stand": "83bcb0d455b8559983cc7811b8c3ba4a9ec5d2d595c7489c322d8a7e193a2f0c",
79
- "sourceStand": "5a31a5884bbdecb161987cea6fb768a81fdb6bf774a3d6687ad725f2667bd53e",
79
+ "sourceStand": "59844fc6fb1c2e36dfb4d854bc75ed6a678de7dbe97e5d5a20c059a038098a4d",
80
80
  "server": "server/index.js",
81
81
  "web": {
82
82
  "entry": "web/index.js",
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.profile-distribution",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -52,8 +52,8 @@
52
52
  },
53
53
  "web": {}
54
54
  },
55
- "stand": "bfbd7567f9d0fe8aa6b6600c5e9750caab844053d93fbce389e02a169d151b18",
56
- "sourceStand": "31d397812908e9f38efe5ba5923ba6f6f53624607453b41ffd7d62e688685cbb",
55
+ "stand": "8894e98d0ae19da1b57689c3434e69a04ccbb6d4ead9e6a2003e9b7f4a20f3cf",
56
+ "sourceStand": "fbb33591b3ef32d6b62d2af2e38fc0da5556b4711e2e011d5a14fa695cff93eb",
57
57
  "server": "server/index.js",
58
58
  "exports": {
59
59
  "server": {},
@@ -70,7 +70,7 @@ var checkSections = (source, raw, pluginIds) => {
70
70
  if (section === "host" && !hostConfigKeys.includes(key)) throw new Error(`${source}: host.${key} ist kein Host-Schl\xFCssel`);
71
71
  if (isEnvironmentReference(entry) || isProvisionedReference(entry)) continue;
72
72
  if (SECRET_KEY_PATTERN.test(key)) throw new Error(`${source}: ${section}.${key} ist ein Secret und muss als env("...") stehen`);
73
- const valid = typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean" || Array.isArray(entry) && entry.every((item) => typeof item === "string");
73
+ const valid = typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean" || Array.isArray(entry) && entry.every((item) => typeof item === "string") || Array.isArray(entry) && entry.every((item) => !!item && typeof item === "object" && !Array.isArray(item));
74
74
  if (!valid) throw new Error(`${source}: ${section}.${key} hat keinen g\xFCltigen Wert`);
75
75
  if (typeof entry === "string" && /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(entry)) throw new Error(`${source}: ${section}.${key} verweist als Text auf die Umgebung; env("...") verwenden`);
76
76
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../plugins/ragents.profile-distribution/server/index.ts", "../../../plugins/ragents.profile-distribution/contract.ts", "../../../plugins/ragents.profile-distribution/server/archive.ts", "../../../plugins/ragents.profile-distribution/server/config.ts"],
4
- "sourcesContent": ["import { DomainError, implement, type HttpRouteContribution, type RAgentsPlugin } from \"@ragents/engine\";\nimport { readHostApiVersion, readHostVersion, readPackageVersion } from \"@ragents/host/host-version.js\";\nimport type { PluginModule } from \"@ragents/host/plugin-support/plugin-module.js\";\nimport { writeJson } from \"@ragents/host/plugin-support/http.js\";\nimport { profileArchivePath, profileDistributionContracts, type ClientProfileDescription } from \"../contract.js\";\nimport { inspectClientProfile, packClientProfile } from \"./archive.js\";\nimport { profileDistributionConfig, profileDistributionConfigDescriptors } from \"./config.js\";\n\ninterface DistributionState {\n readonly description: ClientProfileDescription;\n readonly archive: Buffer;\n}\n\nconst archivePattern = /^\\/profile\\/([0-9a-f]{64})\\.tar\\.gz$/;\n\nconst archiveRoute = (state: () => DistributionState): HttpRouteContribution => ({\n id: \"ragents.profile-distribution.archive\",\n isApiPath: (pathname) => pathname.startsWith(\"/profile/\"),\n matches: (request, url) => request.method === \"GET\" && archivePattern.test(url.pathname),\n requiredRights: [\"profile.fetch\"],\n handle: ({ response, url }) => {\n const current = state();\n const version = archivePattern.exec(url.pathname)?.[1];\n if (version !== current.description.version) {\n writeJson(response, 404, { error: `Der Stand ${version} wird nicht mehr angeboten; aktuell ist ${current.description.version}` });\n return;\n }\n response.writeHead(200, {\n \"Content-Type\": \"application/gzip\",\n \"Content-Length\": current.archive.byteLength,\n \"Cache-Control\": \"no-store\",\n });\n response.end(current.archive);\n },\n});\n\nconst profileDistributionPlugin: RAgentsPlugin = {\n manifest: { id: \"ragents.profile-distribution\" },\n register: (host) => {\n host.config(...profileDistributionConfigDescriptors);\n const file = profileDistributionConfig.clientProfileFile();\n if (!file) {\n host.lifecycle({\n id: \"ragents.profile-distribution\",\n initialize: () => console.log(\"Profilverteilung: CLIENT_PROFILE_FILE ist nicht gesetzt, dieser Server bietet kein Client-Profil an\"),\n });\n return;\n }\n let ready: DistributionState | undefined;\n const state = (): DistributionState => {\n if (!ready) throw new DomainError(\"profile-not-ready\", \"Das Client-Profil ist noch nicht gepackt.\", 503);\n return ready;\n };\n host.lifecycle({\n id: \"ragents.profile-distribution\",\n initialize: async () => {\n const hostVersion = profileDistributionConfig.hostVersion() ?? readHostVersion();\n const packageVersion = readPackageVersion();\n const hostApi = readHostApiVersion();\n const inspected = await inspectClientProfile(file);\n const packed = await packClientProfile(inspected);\n ready = {\n archive: packed.archive,\n description: {\n profile: inspected.profile,\n version: packed.version,\n hostApi,\n hostVersion,\n packageVersion,\n file: inspected.file,\n size: packed.archive.byteLength,\n archivePath: profileArchivePath(packed.version),\n plugins: inspected.plugins.map((plugin) => ({ id: plugin.id, source: plugin.source })),\n },\n };\n console.log(`Profilverteilung: ${inspected.profile} Stand ${packed.version.slice(0, 12)} (${packed.entries.length} Dateien, ${packed.archive.byteLength} Byte, Host-API ${hostApi}, Host ${hostVersion.slice(0, 12)}, Paket ${packageVersion})`);\n },\n });\n host.methods(implement(profileDistributionContracts.describe, () => state().description));\n host.http(archiveRoute(state));\n },\n};\n\nexport const plugin: PluginModule = {\n create: () => profileDistributionPlugin,\n};\n", "import { Type, type Static } from \"typebox\";\nimport { defineOperation } from \"@ragents/engine/src/rpc/contract\";\n\nconst pluginEntry = Type.Object({\n id: Type.String({ minLength: 1 }),\n source: Type.Union([Type.Literal(\"host\"), Type.Literal(\"archive\")], {\n description: \"host: der Client nimmt das eingebaute Bundle seines Hosts; archive: das Bundle liegt im Archiv\",\n }),\n}, { additionalProperties: false });\n\nconst description = Type.Object({\n profile: Type.String({ minLength: 1, description: \"Profilname; die Datei hei\u00DFt ragents.config.<profil>.ts\" }),\n version: Type.String({ minLength: 64, maxLength: 64, description: \"Stand des Archivs als SHA-256\" }),\n hostApi: Type.Integer({ minimum: 1, description: \"Nummer der Host-API, gegen die die Bundles im Archiv gebaut sind; der Host des Clients muss genau diese bieten\" }),\n hostVersion: Type.String({ minLength: 40, maxLength: 40, description: \"Git-Commit des Hosts dieses Servers; ein Checkout mit anderer Host-API kommt damit zu einer passenden\" }),\n packageVersion: Type.String({ minLength: 1, description: \"Fassung des npm-Pakets, die diesen Commit tr\u00E4gt; eine Installation mit anderer Host-API kommt damit zu einer passenden\" }),\n file: Type.String({ minLength: 1, description: \"Pfad der Profildatei innerhalb des Archivs\" }),\n size: Type.Integer({ minimum: 0, description: \"Archivgr\u00F6\u00DFe in Byte\" }),\n archivePath: Type.String({ minLength: 1, description: \"HTTP-Pfad des Archivs auf diesem Server\" }),\n plugins: Type.Array(pluginEntry),\n}, { additionalProperties: false });\n\nexport type ClientProfileDescription = Static<typeof description>;\n\nexport const profileArchivePath = (version: string): string => `/profile/${version}.tar.gz`;\n\nexport const profileDistributionContracts = {\n describe: defineOperation({\n id: \"ragents.profile.describe\",\n description: \"Das Client-Profil dieses Servers: Name, Stand, verlangte Host-API, Host- und Paketfassung, Plugins und Archiv. Recht: profile.fetch.\",\n rights: [\"profile.fetch\"],\n input: Type.Object({}, { additionalProperties: false }),\n result: description,\n }),\n};\n", "import { createHash } from \"node:crypto\";\nimport { readdirSync, statSync, lstatSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { create as createTar } from \"tar\";\nimport { hostConfigKeys } from \"@ragents/host/config.js\";\nimport { isEnvironmentReference, isProvisionedReference } from \"@ragents/host/config-definition.js\";\nimport { resolveAnonymousUser, resolveProfileUsers, SECRET_KEY_PATTERN } from \"@ragents/host/config-file.js\";\nimport { discoverPluginIds, resolvePluginEntries, type ResolvedPlugin } from \"@ragents/host/profile/plugin-discovery.js\";\nimport { bundlesRoot, isPluginPath } from \"@ragents/host/plugin-support/plugins-root.js\";\n\nexport interface ClientProfilePlugin extends ResolvedPlugin {\n readonly source: \"host\" | \"archive\";\n}\n\nexport interface InspectedClientProfile {\n readonly profile: string;\n readonly source: string;\n readonly root: string;\n readonly file: string;\n readonly plugins: readonly ClientProfilePlugin[];\n}\n\nexport interface PackedClientProfile {\n readonly archive: Buffer;\n readonly version: string;\n readonly entries: readonly string[];\n}\n\nconst PROFILE_FILE = /^ragents\\.config\\.([a-z0-9]+(?:-[a-z0-9]+)*)\\.ts$/;\n\nconst commonRoot = (first: string, others: readonly string[]): string => {\n let root = first;\n for (const folder of others) {\n while (folder !== root && !folder.startsWith(root + path.sep)) {\n const parent = path.dirname(root);\n if (parent === root) throw new Error(`Profildatei und Plugin ${folder} haben keinen gemeinsamen Ordner`);\n root = parent;\n }\n }\n return root;\n};\n\nconst posixRelative = (root: string, target: string): string => path.relative(root, target).split(path.sep).join(\"/\");\n\n// Jeder Name ist frei, damit ein Passwort- oder Token-Verweis auch ohne die Client-Umgebung pr\u00FCfbar ist.\nconst placeholderEnvironment: Readonly<Record<string, string | undefined>> = new Proxy({}, { get: () => \"client-placeholder-value\" });\n\nconst checkSections = (source: string, raw: Record<string, unknown>, pluginIds: ReadonlySet<string>): void => {\n for (const [section, value] of Object.entries(raw)) {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${source}: die Sektion ${section} ist kein Objekt`);\n if (section !== \"host\" && !pluginIds.has(section)) throw new Error(`${source}: die Sektion ${section} geh\u00F6rt zu keinem Plugin aus host.PLUGINS`);\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (section === \"host\" && !hostConfigKeys.includes(key)) throw new Error(`${source}: host.${key} ist kein Host-Schl\u00FCssel`);\n if (isEnvironmentReference(entry) || isProvisionedReference(entry)) continue;\n if (SECRET_KEY_PATTERN.test(key)) throw new Error(`${source}: ${section}.${key} ist ein Secret und muss als env(\"...\") stehen`);\n const valid = typeof entry === \"string\" || typeof entry === \"number\" || typeof entry === \"boolean\"\n || (Array.isArray(entry) && entry.every((item) => typeof item === \"string\"));\n if (!valid) throw new Error(`${source}: ${section}.${key} hat keinen g\u00FCltigen Wert`);\n if (typeof entry === \"string\" && /^\\$\\{[A-Za-z_][A-Za-z0-9_]*\\}$/.test(entry)) throw new Error(`${source}: ${section}.${key} verweist als Text auf die Umgebung; env(\"...\") verwenden`);\n }\n }\n};\n\n/** Pr\u00FCft die Client-Profildatei ohne ihre Umgebung und bestimmt, welche Plugins ins Archiv geh\u00F6ren. */\nexport const inspectClientProfile = async (source: string, root = bundlesRoot): Promise<InspectedClientProfile> => {\n const name = PROFILE_FILE.exec(path.basename(source));\n if (!name) throw new Error(`Die Client-Profildatei muss ragents.config.<profil>.ts hei\u00DFen: ${source}`);\n if (!statSync(source, { throwIfNoEntry: false })?.isFile()) throw new Error(`Die Client-Profildatei ${source} fehlt`);\n const profile = name[1]!;\n const module = await import(pathToFileURL(source).href) as Record<string, unknown>;\n const raw = module.config;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) throw new Error(`${source} exportiert keine Konstante config`);\n const host = (raw as Record<string, unknown>).host as Record<string, unknown> | undefined;\n const entries = host?.PLUGINS;\n if (!Array.isArray(entries) || entries.length === 0 || !entries.every((entry) => typeof entry === \"string\" && entry)) {\n throw new Error(`${source}: host.PLUGINS muss eine nicht leere Liste sein`);\n }\n if (host?.PRODUCT_PROFILE !== profile) throw new Error(`${source}: host.PRODUCT_PROFILE muss ${profile} sein`);\n const directory = path.dirname(source);\n const unportable = (entries as string[]).filter((entry) => isPluginPath(entry) && !/^\\.{1,2}\\//.test(entry));\n if (unportable.length > 0) {\n throw new Error(`${source}: ${unportable.join(\", \")} nennt ein Bundle absolut oder mit ~/; der Client l\u00F6st diesen Pfad auf seinem eigenen Rechner auf und f\u00E4nde dort nicht das gelieferte Bundle. Im Client-Profil jedes Bundle relativ zur Profildatei nennen (./ oder ../)`);\n }\n const plugins = ((): readonly ClientProfilePlugin[] => {\n try {\n return resolvePluginEntries(entries as string[], directory, root)\n .map((plugin, index) => ({ ...plugin, source: isPluginPath((entries as string[])[index]!) ? \"archive\" : \"host\" }));\n } catch (cause) {\n throw new Error(`${source}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });\n }\n })();\n checkSections(source, raw as Record<string, unknown>, new Set([...discoverPluginIds(root), ...plugins.map((plugin) => plugin.id)]));\n const users = resolveProfileUsers(source, module.users, placeholderEnvironment);\n const anonymous = resolveAnonymousUser(source, module.anonymousUser);\n if (users && anonymous) throw new Error(`${source}: users und anonymousUser schlie\u00DFen einander aus`);\n const archived = plugins.filter((plugin) => plugin.source === \"archive\").map((plugin) => plugin.folder);\n const commonDirectory = commonRoot(directory, archived);\n return { profile, source, root: commonDirectory, file: posixRelative(commonDirectory, source), plugins };\n};\n\nconst collectFiles = (folder: string, root: string): string[] => {\n const files: string[] = [];\n for (const entry of readdirSync(folder, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name, \"en\"))) {\n const absolute = path.join(folder, entry.name);\n if (entry.isSymbolicLink()) throw new Error(`Das Client-Profil enth\u00E4lt einen symbolischen Link, den das Archiv nicht abbildet: ${absolute}`);\n if (entry.isDirectory()) {\n files.push(...collectFiles(absolute, root));\n } else if (entry.isFile()) {\n files.push(posixRelative(root, absolute));\n }\n }\n return files;\n};\n\n/** Die Eintr\u00E4ge des Archivs: die Profildatei und die Dateien der Bundles, die sie per Pfad nennt; das Web hat der Client selbst. */\nexport const clientProfileEntries = (inspected: InspectedClientProfile): readonly string[] => {\n const entries = [inspected.file, ...inspected.plugins.filter((plugin) => plugin.source === \"archive\").flatMap((plugin) => collectFiles(plugin.folder, inspected.root))];\n for (const entry of entries) {\n if (!lstatSync(path.join(inspected.root, entry)).isFile()) throw new Error(`Der Archiveintrag ${entry} ist keine Datei`);\n }\n return entries;\n};\n\n/** Packt die Eintr\u00E4ge deterministisch aus ihrem gemeinsamen Ordner; der Stand ist der SHA-256 des Archivs. */\nexport const packClientProfile = async (inspected: InspectedClientProfile): Promise<PackedClientProfile> => {\n const entries = clientProfileEntries(inspected);\n const chunks: Buffer[] = [];\n for await (const chunk of createTar({ gzip: { level: 9 }, cwd: inspected.root, portable: true, noMtime: true }, [...entries])) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const archive = Buffer.concat(chunks);\n return { archive, version: createHash(\"sha256\").update(archive).digest(\"hex\"), entries };\n};\n", "import path from \"node:path\";\nimport { configFilePath } from \"@ragents/host/config-file.js\";\nimport { declaredEnvironment } from \"@ragents/host/plugin-support/plugin-config.js\";\n\nexport const profileDistributionConfigDescriptors = [\n { key: \"CLIENT_PROFILE_FILE\", source: \"environment\" },\n { key: \"HOST_VERSION\", source: \"environment\" },\n] as const;\n\nconst env = declaredEnvironment(profileDistributionConfigDescriptors);\n\n/** Der Pfad gilt relativ zur Server-Profildatei, damit beide Dateien nebeneinander liegen k\u00F6nnen. */\nconst resolveClientProfileFile = (): string | undefined => {\n const value = env.optional(\"CLIENT_PROFILE_FILE\");\n if (!value) return undefined;\n const profile = configFilePath();\n return path.resolve(profile ? path.dirname(profile) : process.cwd(), value);\n};\n\nexport const profileDistributionConfig = Object.freeze({\n clientProfileFile: resolveClientProfileFile,\n hostVersion: () => {\n const value = env.optional(\"HOST_VERSION\");\n if (value !== undefined && !/^[0-9a-f]{40}$/.test(value)) throw new Error(`HOST_VERSION muss ein vollst\u00E4ndiger Git-Commit sein, nicht \"${value}\"`);\n return value;\n },\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { DomainError, implement, type HttpRouteContribution, type RAgentsPlugin } from \"@ragents/engine\";\nimport { readHostApiVersion, readHostVersion, readPackageVersion } from \"@ragents/host/host-version.js\";\nimport type { PluginModule } from \"@ragents/host/plugin-support/plugin-module.js\";\nimport { writeJson } from \"@ragents/host/plugin-support/http.js\";\nimport { profileArchivePath, profileDistributionContracts, type ClientProfileDescription } from \"../contract.js\";\nimport { inspectClientProfile, packClientProfile } from \"./archive.js\";\nimport { profileDistributionConfig, profileDistributionConfigDescriptors } from \"./config.js\";\n\ninterface DistributionState {\n readonly description: ClientProfileDescription;\n readonly archive: Buffer;\n}\n\nconst archivePattern = /^\\/profile\\/([0-9a-f]{64})\\.tar\\.gz$/;\n\nconst archiveRoute = (state: () => DistributionState): HttpRouteContribution => ({\n id: \"ragents.profile-distribution.archive\",\n isApiPath: (pathname) => pathname.startsWith(\"/profile/\"),\n matches: (request, url) => request.method === \"GET\" && archivePattern.test(url.pathname),\n requiredRights: [\"profile.fetch\"],\n handle: ({ response, url }) => {\n const current = state();\n const version = archivePattern.exec(url.pathname)?.[1];\n if (version !== current.description.version) {\n writeJson(response, 404, { error: `Der Stand ${version} wird nicht mehr angeboten; aktuell ist ${current.description.version}` });\n return;\n }\n response.writeHead(200, {\n \"Content-Type\": \"application/gzip\",\n \"Content-Length\": current.archive.byteLength,\n \"Cache-Control\": \"no-store\",\n });\n response.end(current.archive);\n },\n});\n\nconst profileDistributionPlugin: RAgentsPlugin = {\n manifest: { id: \"ragents.profile-distribution\" },\n register: (host) => {\n host.config(...profileDistributionConfigDescriptors);\n const file = profileDistributionConfig.clientProfileFile();\n if (!file) {\n host.lifecycle({\n id: \"ragents.profile-distribution\",\n initialize: () => console.log(\"Profilverteilung: CLIENT_PROFILE_FILE ist nicht gesetzt, dieser Server bietet kein Client-Profil an\"),\n });\n return;\n }\n let ready: DistributionState | undefined;\n const state = (): DistributionState => {\n if (!ready) throw new DomainError(\"profile-not-ready\", \"Das Client-Profil ist noch nicht gepackt.\", 503);\n return ready;\n };\n host.lifecycle({\n id: \"ragents.profile-distribution\",\n initialize: async () => {\n const hostVersion = profileDistributionConfig.hostVersion() ?? readHostVersion();\n const packageVersion = readPackageVersion();\n const hostApi = readHostApiVersion();\n const inspected = await inspectClientProfile(file);\n const packed = await packClientProfile(inspected);\n ready = {\n archive: packed.archive,\n description: {\n profile: inspected.profile,\n version: packed.version,\n hostApi,\n hostVersion,\n packageVersion,\n file: inspected.file,\n size: packed.archive.byteLength,\n archivePath: profileArchivePath(packed.version),\n plugins: inspected.plugins.map((plugin) => ({ id: plugin.id, source: plugin.source })),\n },\n };\n console.log(`Profilverteilung: ${inspected.profile} Stand ${packed.version.slice(0, 12)} (${packed.entries.length} Dateien, ${packed.archive.byteLength} Byte, Host-API ${hostApi}, Host ${hostVersion.slice(0, 12)}, Paket ${packageVersion})`);\n },\n });\n host.methods(implement(profileDistributionContracts.describe, () => state().description));\n host.http(archiveRoute(state));\n },\n};\n\nexport const plugin: PluginModule = {\n create: () => profileDistributionPlugin,\n};\n", "import { Type, type Static } from \"typebox\";\nimport { defineOperation } from \"@ragents/engine/src/rpc/contract\";\n\nconst pluginEntry = Type.Object({\n id: Type.String({ minLength: 1 }),\n source: Type.Union([Type.Literal(\"host\"), Type.Literal(\"archive\")], {\n description: \"host: der Client nimmt das eingebaute Bundle seines Hosts; archive: das Bundle liegt im Archiv\",\n }),\n}, { additionalProperties: false });\n\nconst description = Type.Object({\n profile: Type.String({ minLength: 1, description: \"Profilname; die Datei hei\u00DFt ragents.config.<profil>.ts\" }),\n version: Type.String({ minLength: 64, maxLength: 64, description: \"Stand des Archivs als SHA-256\" }),\n hostApi: Type.Integer({ minimum: 1, description: \"Nummer der Host-API, gegen die die Bundles im Archiv gebaut sind; der Host des Clients muss genau diese bieten\" }),\n hostVersion: Type.String({ minLength: 40, maxLength: 40, description: \"Git-Commit des Hosts dieses Servers; ein Checkout mit anderer Host-API kommt damit zu einer passenden\" }),\n packageVersion: Type.String({ minLength: 1, description: \"Fassung des npm-Pakets, die diesen Commit tr\u00E4gt; eine Installation mit anderer Host-API kommt damit zu einer passenden\" }),\n file: Type.String({ minLength: 1, description: \"Pfad der Profildatei innerhalb des Archivs\" }),\n size: Type.Integer({ minimum: 0, description: \"Archivgr\u00F6\u00DFe in Byte\" }),\n archivePath: Type.String({ minLength: 1, description: \"HTTP-Pfad des Archivs auf diesem Server\" }),\n plugins: Type.Array(pluginEntry),\n}, { additionalProperties: false });\n\nexport type ClientProfileDescription = Static<typeof description>;\n\nexport const profileArchivePath = (version: string): string => `/profile/${version}.tar.gz`;\n\nexport const profileDistributionContracts = {\n describe: defineOperation({\n id: \"ragents.profile.describe\",\n description: \"Das Client-Profil dieses Servers: Name, Stand, verlangte Host-API, Host- und Paketfassung, Plugins und Archiv. Recht: profile.fetch.\",\n rights: [\"profile.fetch\"],\n input: Type.Object({}, { additionalProperties: false }),\n result: description,\n }),\n};\n", "import { createHash } from \"node:crypto\";\nimport { readdirSync, statSync, lstatSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { create as createTar } from \"tar\";\nimport { hostConfigKeys } from \"@ragents/host/config.js\";\nimport { isEnvironmentReference, isProvisionedReference } from \"@ragents/host/config-definition.js\";\nimport { resolveAnonymousUser, resolveProfileUsers, SECRET_KEY_PATTERN } from \"@ragents/host/config-file.js\";\nimport { discoverPluginIds, resolvePluginEntries, type ResolvedPlugin } from \"@ragents/host/profile/plugin-discovery.js\";\nimport { bundlesRoot, isPluginPath } from \"@ragents/host/plugin-support/plugins-root.js\";\n\nexport interface ClientProfilePlugin extends ResolvedPlugin {\n readonly source: \"host\" | \"archive\";\n}\n\nexport interface InspectedClientProfile {\n readonly profile: string;\n readonly source: string;\n readonly root: string;\n readonly file: string;\n readonly plugins: readonly ClientProfilePlugin[];\n}\n\nexport interface PackedClientProfile {\n readonly archive: Buffer;\n readonly version: string;\n readonly entries: readonly string[];\n}\n\nconst PROFILE_FILE = /^ragents\\.config\\.([a-z0-9]+(?:-[a-z0-9]+)*)\\.ts$/;\n\nconst commonRoot = (first: string, others: readonly string[]): string => {\n let root = first;\n for (const folder of others) {\n while (folder !== root && !folder.startsWith(root + path.sep)) {\n const parent = path.dirname(root);\n if (parent === root) throw new Error(`Profildatei und Plugin ${folder} haben keinen gemeinsamen Ordner`);\n root = parent;\n }\n }\n return root;\n};\n\nconst posixRelative = (root: string, target: string): string => path.relative(root, target).split(path.sep).join(\"/\");\n\n// Jeder Name ist frei, damit ein Passwort- oder Token-Verweis auch ohne die Client-Umgebung pr\u00FCfbar ist.\nconst placeholderEnvironment: Readonly<Record<string, string | undefined>> = new Proxy({}, { get: () => \"client-placeholder-value\" });\n\nconst checkSections = (source: string, raw: Record<string, unknown>, pluginIds: ReadonlySet<string>): void => {\n for (const [section, value] of Object.entries(raw)) {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${source}: die Sektion ${section} ist kein Objekt`);\n if (section !== \"host\" && !pluginIds.has(section)) throw new Error(`${source}: die Sektion ${section} geh\u00F6rt zu keinem Plugin aus host.PLUGINS`);\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (section === \"host\" && !hostConfigKeys.includes(key)) throw new Error(`${source}: host.${key} ist kein Host-Schl\u00FCssel`);\n if (isEnvironmentReference(entry) || isProvisionedReference(entry)) continue;\n if (SECRET_KEY_PATTERN.test(key)) throw new Error(`${source}: ${section}.${key} ist ein Secret und muss als env(\"...\") stehen`);\n const valid = typeof entry === \"string\" || typeof entry === \"number\" || typeof entry === \"boolean\"\n || (Array.isArray(entry) && entry.every((item) => typeof item === \"string\"))\n || (Array.isArray(entry) && entry.every((item) => !!item && typeof item === \"object\" && !Array.isArray(item)));\n if (!valid) throw new Error(`${source}: ${section}.${key} hat keinen g\u00FCltigen Wert`);\n if (typeof entry === \"string\" && /^\\$\\{[A-Za-z_][A-Za-z0-9_]*\\}$/.test(entry)) throw new Error(`${source}: ${section}.${key} verweist als Text auf die Umgebung; env(\"...\") verwenden`);\n }\n }\n};\n\n/** Pr\u00FCft die Client-Profildatei ohne ihre Umgebung und bestimmt, welche Plugins ins Archiv geh\u00F6ren. */\nexport const inspectClientProfile = async (source: string, root = bundlesRoot): Promise<InspectedClientProfile> => {\n const name = PROFILE_FILE.exec(path.basename(source));\n if (!name) throw new Error(`Die Client-Profildatei muss ragents.config.<profil>.ts hei\u00DFen: ${source}`);\n if (!statSync(source, { throwIfNoEntry: false })?.isFile()) throw new Error(`Die Client-Profildatei ${source} fehlt`);\n const profile = name[1]!;\n const module = await import(pathToFileURL(source).href) as Record<string, unknown>;\n const raw = module.config;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) throw new Error(`${source} exportiert keine Konstante config`);\n const host = (raw as Record<string, unknown>).host as Record<string, unknown> | undefined;\n const entries = host?.PLUGINS;\n if (!Array.isArray(entries) || entries.length === 0 || !entries.every((entry) => typeof entry === \"string\" && entry)) {\n throw new Error(`${source}: host.PLUGINS muss eine nicht leere Liste sein`);\n }\n if (host?.PRODUCT_PROFILE !== profile) throw new Error(`${source}: host.PRODUCT_PROFILE muss ${profile} sein`);\n const directory = path.dirname(source);\n const unportable = (entries as string[]).filter((entry) => isPluginPath(entry) && !/^\\.{1,2}\\//.test(entry));\n if (unportable.length > 0) {\n throw new Error(`${source}: ${unportable.join(\", \")} nennt ein Bundle absolut oder mit ~/; der Client l\u00F6st diesen Pfad auf seinem eigenen Rechner auf und f\u00E4nde dort nicht das gelieferte Bundle. Im Client-Profil jedes Bundle relativ zur Profildatei nennen (./ oder ../)`);\n }\n const plugins = ((): readonly ClientProfilePlugin[] => {\n try {\n return resolvePluginEntries(entries as string[], directory, root)\n .map((plugin, index) => ({ ...plugin, source: isPluginPath((entries as string[])[index]!) ? \"archive\" : \"host\" }));\n } catch (cause) {\n throw new Error(`${source}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });\n }\n })();\n checkSections(source, raw as Record<string, unknown>, new Set([...discoverPluginIds(root), ...plugins.map((plugin) => plugin.id)]));\n const users = resolveProfileUsers(source, module.users, placeholderEnvironment);\n const anonymous = resolveAnonymousUser(source, module.anonymousUser);\n if (users && anonymous) throw new Error(`${source}: users und anonymousUser schlie\u00DFen einander aus`);\n const archived = plugins.filter((plugin) => plugin.source === \"archive\").map((plugin) => plugin.folder);\n const commonDirectory = commonRoot(directory, archived);\n return { profile, source, root: commonDirectory, file: posixRelative(commonDirectory, source), plugins };\n};\n\nconst collectFiles = (folder: string, root: string): string[] => {\n const files: string[] = [];\n for (const entry of readdirSync(folder, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name, \"en\"))) {\n const absolute = path.join(folder, entry.name);\n if (entry.isSymbolicLink()) throw new Error(`Das Client-Profil enth\u00E4lt einen symbolischen Link, den das Archiv nicht abbildet: ${absolute}`);\n if (entry.isDirectory()) {\n files.push(...collectFiles(absolute, root));\n } else if (entry.isFile()) {\n files.push(posixRelative(root, absolute));\n }\n }\n return files;\n};\n\n/** Die Eintr\u00E4ge des Archivs: die Profildatei und die Dateien der Bundles, die sie per Pfad nennt; das Web hat der Client selbst. */\nexport const clientProfileEntries = (inspected: InspectedClientProfile): readonly string[] => {\n const entries = [inspected.file, ...inspected.plugins.filter((plugin) => plugin.source === \"archive\").flatMap((plugin) => collectFiles(plugin.folder, inspected.root))];\n for (const entry of entries) {\n if (!lstatSync(path.join(inspected.root, entry)).isFile()) throw new Error(`Der Archiveintrag ${entry} ist keine Datei`);\n }\n return entries;\n};\n\n/** Packt die Eintr\u00E4ge deterministisch aus ihrem gemeinsamen Ordner; der Stand ist der SHA-256 des Archivs. */\nexport const packClientProfile = async (inspected: InspectedClientProfile): Promise<PackedClientProfile> => {\n const entries = clientProfileEntries(inspected);\n const chunks: Buffer[] = [];\n for await (const chunk of createTar({ gzip: { level: 9 }, cwd: inspected.root, portable: true, noMtime: true }, [...entries])) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const archive = Buffer.concat(chunks);\n return { archive, version: createHash(\"sha256\").update(archive).digest(\"hex\"), entries };\n};\n", "import path from \"node:path\";\nimport { configFilePath } from \"@ragents/host/config-file.js\";\nimport { declaredEnvironment } from \"@ragents/host/plugin-support/plugin-config.js\";\n\nexport const profileDistributionConfigDescriptors = [\n { key: \"CLIENT_PROFILE_FILE\", source: \"environment\" },\n { key: \"HOST_VERSION\", source: \"environment\" },\n] as const;\n\nconst env = declaredEnvironment(profileDistributionConfigDescriptors);\n\n/** Der Pfad gilt relativ zur Server-Profildatei, damit beide Dateien nebeneinander liegen k\u00F6nnen. */\nconst resolveClientProfileFile = (): string | undefined => {\n const value = env.optional(\"CLIENT_PROFILE_FILE\");\n if (!value) return undefined;\n const profile = configFilePath();\n return path.resolve(profile ? path.dirname(profile) : process.cwd(), value);\n};\n\nexport const profileDistributionConfig = Object.freeze({\n clientProfileFile: resolveClientProfileFile,\n hostVersion: () => {\n const value = env.optional(\"HOST_VERSION\");\n if (value !== undefined && !/^[0-9a-f]{40}$/.test(value)) throw new Error(`HOST_VERSION muss ein vollst\u00E4ndiger Git-Commit sein, nicht \"${value}\"`);\n return value;\n },\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["plugin", "path", "plugin"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.reference",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {},
7
7
  "web": {
@@ -21,7 +21,7 @@
21
21
  }
22
22
  },
23
23
  "stand": "b3fa5275dc209c315f26ec832458603d442d2a56974471ee83292e7d26079a12",
24
- "sourceStand": "6db28f060bf31d72dc73f716a86c7122ce25d67e6b9c81ceba034e96fe735fd9",
24
+ "sourceStand": "a6ac0a9bec2e9929d8b11737f505dfe8f4905d26ed7cf53fcf5fc1aa0bf642bc",
25
25
  "server": "server/index.js",
26
26
  "web": {
27
27
  "entry": "web/index.js",
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.todo",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -33,7 +33,7 @@
33
33
  }
34
34
  },
35
35
  "stand": "3dd3347780b8ddbe369e9024096d5da94ba34cf37b1003b55e03e3cbc8cd4779",
36
- "sourceStand": "dfb507ba9b2a9f99023f75cdb676872db58dcd0f33fab1d1e468c3f09bdebebe",
36
+ "sourceStand": "5176b6fe21a1fcac3e38a74ad59e29a68c5dfe1ae2b1bc829ade65add91206ad",
37
37
  "server": "server/index.js",
38
38
  "web": {
39
39
  "entry": "web/index.js",
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.transcript",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -23,7 +23,7 @@
23
23
  "web": {}
24
24
  },
25
25
  "stand": "98d8ba054df383ac3d2d13e25de7f1930a7e4301654e188847cfc1fcf135490b",
26
- "sourceStand": "047848b91abec440121b9d392fd4c268799e674198b9497cd9ad842d32522025",
26
+ "sourceStand": "04596bd6ff61db0f6f956bec63fc8783f329a03f32e80366fb5beed4e1bdf55d",
27
27
  "server": "server/index.js",
28
28
  "exports": {
29
29
  "server": {},
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.watch",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -25,7 +25,7 @@
25
25
  "web": {}
26
26
  },
27
27
  "stand": "f5cade80192041cee54457035b293425a10f1de42b49f1d804117ad7951c1b00",
28
- "sourceStand": "9b701a2a9708f14452ca7548677c735f70b6d013e1e0438bbd7a19c38bc96545",
28
+ "sourceStand": "0515fbdf8c4bf2859a4c09d2d1c0feb9ebf502af2f164cc6337f9d44d0463cc4",
29
29
  "server": "server/index.js",
30
30
  "exports": {
31
31
  "server": {
@@ -1,7 +1,7 @@
1
1
  {
2
- "format": 3,
2
+ "format": 4,
3
3
  "id": "ragents.workspace",
4
- "api": 6,
4
+ "api": 7,
5
5
  "hostNames": {
6
6
  "server": {
7
7
  "@ragents/engine": [
@@ -9,7 +9,8 @@
9
9
  "RPC_ERROR_CODES",
10
10
  "RpcError",
11
11
  "implement",
12
- "implementChannel"
12
+ "implementChannel",
13
+ "schemaComplaints"
13
14
  ],
14
15
  "@ragents/engine/src/http/contracts": [
15
16
  "openJson"
@@ -41,6 +42,7 @@
41
42
  "documentStoreToken"
42
43
  ],
43
44
  "@ragents/host/ragents/host-services": [
45
+ "executorContributionsToken",
44
46
  "hostAddressToken",
45
47
  "runGuardToken",
46
48
  "runWorkspaceProviderToken",
@@ -61,12 +63,16 @@
61
63
  "WORKSPACE_EXECUTOR_VERSION",
62
64
  "listDirectory",
63
65
  "readTextFile",
66
+ "ripgrepAvailable",
64
67
  "sandboxRunEnvironment",
65
68
  "shellPlatformText",
66
69
  "watchDirectory"
67
70
  ],
68
71
  "typebox": [
69
72
  "Type"
73
+ ],
74
+ "typebox/value": [
75
+ "Value"
70
76
  ]
71
77
  },
72
78
  "web": {
@@ -130,8 +136,8 @@
130
136
  ]
131
137
  }
132
138
  },
133
- "stand": "014f6c3e925196716315c4827b73e71a9b98579e620f0cc1beeb3bec763520a8",
134
- "sourceStand": "dabaf431c288a40f14c521ca52da35a66e80e1a5352b5486d464b91a7cbecd5e",
139
+ "stand": "3c8b0a3987ba2d958b91f944a88898e53dab2c89c977e5e50d44ad2ad77f9900",
140
+ "sourceStand": "d8ec60ed343831c7b32192a9d681350af375365fcf692366bc55e35d2850dcf9",
135
141
  "server": "server/index.js",
136
142
  "web": {
137
143
  "entry": "web/index.js",
@@ -8,6 +8,7 @@ import { documentStoreToken } from "@ragents/host/ragents/document-store.js";
8
8
  import { workspaceResolverToken, workspaceRuntimeToken } from "@ragents/host/ragents/workspace-runtime.js";
9
9
  import { sandboxServicesToken } from "@ragents/host/plugin-support/workspace-sandbox-host.js";
10
10
  import {
11
+ executorContributionsToken,
11
12
  hostAddressToken,
12
13
  runtimeProviderToken,
13
14
  runGuardToken,
@@ -16,19 +17,20 @@ import {
16
17
  } from "@ragents/host/ragents/host-services.js";
17
18
  import { pluginAsset } from "@ragents/host/plugin-support/plugin-folder.js";
18
19
  import { ServerProcessSandbox } from "@ragents/host/plugin-support/process-sandbox.js";
20
+ import { ripgrepAvailable } from "@ragents/workspace-executor";
19
21
  import { boundToTools as boundToTools2, handlebarsPrompt } from "@ragents/host/plugin-support/prompt.js";
20
22
 
21
23
  // server/shell-platform.ts
22
24
  import { shellPlatformText } from "@ragents/workspace-executor";
23
25
  import { boundToTools } from "@ragents/host/plugin-support/prompt.js";
24
- var shellPlatformChapter = (platform) => `## Shell platform
26
+ var shellPlatformChapter = (platform, tools) => `## Shell platform
25
27
 
26
- ${shellPlatformText(platform)}`;
27
- var shellPlatformPrompt = (id, order, chapterFor) => boundToTools({
28
+ ${shellPlatformText(platform, tools)}`;
29
+ var shellPlatformPrompt = (id, order, serverTools, chapterFor) => boundToTools({
28
30
  id,
29
31
  order,
30
32
  delivery: "initial",
31
- render: () => shellPlatformChapter(process.platform),
33
+ render: () => shellPlatformChapter(process.platform, serverTools),
32
34
  ...chapterFor ? { renderForRun: chapterFor } : {}
33
35
  }, "bash");
34
36
 
@@ -60,17 +62,32 @@ var freshServerBinding = () => ({ machine: "server", folder: "fresh" });
60
62
  var WORKSPACE_CLIENT_ID_PATTERN = /^[A-Za-z0-9_-]{8,64}$/;
61
63
  var clientId = Type.String({ pattern: "^[A-Za-z0-9_-]{8,64}$", description: "Stabile Kennung des Arbeitsplatzes" });
62
64
  var executorVersion = Type.String({ minLength: 1, maxLength: 64, description: "Stand des Executors, den der Arbeitsplatz mitbringt" });
65
+ var PLUGIN_ID_PATTERN = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
66
+ var executorContributions = Type.Array(Type.Object({
67
+ plugin: Type.String({ pattern: PLUGIN_ID_PATTERN.source, maxLength: 128, description: "Kennung des Plugins" }),
68
+ stand: Type.String({ pattern: "^[0-9a-f]{64}$", description: "SHA-256 der Datei des Beitrags" })
69
+ }, { additionalProperties: false }), { maxItems: 64, description: "Die Beitr\xE4ge der Plugins zum Executor, in der Reihenfolge der Pluginliste des Servers" });
63
70
  var clientDescription = {
64
71
  label: Type.String({ minLength: 1, maxLength: 120 }),
65
72
  hostname: Type.String({ minLength: 1 }),
66
73
  platform: Type.String({ minLength: 1 }),
67
74
  folders: Type.Array(Type.String({ minLength: 1 }), { maxItems: 32 }),
68
- runsDirectory: Type.String({ minLength: 1, description: "Absoluter Ordner, unter dem der Arbeitsplatz die neuen Ordner je Run anlegt" })
75
+ runsDirectory: Type.String({ minLength: 1, description: "Absoluter Ordner, unter dem der Arbeitsplatz die neuen Ordner je Run anlegt" }),
76
+ ripgrep: Type.Boolean({ description: "Ob die Bash des Arbeitsplatzes rg findet" })
69
77
  };
70
78
  var clientInfoSchema = Type.Object({
71
79
  id: Type.String(),
72
80
  ...clientDescription
73
81
  }, { additionalProperties: false });
82
+ var clientRegistrationSchema = Type.Object({
83
+ id: clientId,
84
+ ...clientDescription,
85
+ executor: executorVersion,
86
+ contributions: executorContributions
87
+ }, { additionalProperties: false });
88
+ var otherExecutorRegistration = Type.Object({ label: clientDescription.label, executor: executorVersion }, {
89
+ description: "Anmeldung mit einem anderen Executor-Stand in beliebiger Form; der Server lehnt sie mit workspace-executor-version ab"
90
+ });
74
91
  var absolutePath = Type.String({ minLength: 1, description: "Absoluter Pfad im gebundenen Ordner" });
75
92
  var WORKSPACE_CLIENT_STOP_OPERATION = "stop";
76
93
  var workspaceClientContracts = {
@@ -128,11 +145,18 @@ var workspaceContracts = {
128
145
  input: Type.Object({}, { additionalProperties: false }),
129
146
  result: Type.Array(clientInfoSchema)
130
147
  }),
148
+ contributions: defineOperation({
149
+ id: "ragents.workspace.clients.contributions",
150
+ description: "Die Beitr\xE4ge der Plugins zum Executor, die ein Arbeitsplatz vor der Anmeldung l\xE4dt und mit ihr zur\xFCckmeldet. Ein Arbeitsplatz mit anderem Executor-Stand scheitert an seinem Stand; weitere Felder z\xE4hlen nicht.",
151
+ rights: ["runs.write"],
152
+ input: Type.Object({ label: clientDescription.label, executor: executorVersion }),
153
+ result: executorContributions
154
+ }),
131
155
  register: defineOperation({
132
156
  id: "ragents.workspace.clients.register",
133
- description: "Einen Arbeitsplatz anmelden oder seine Ordner erneuern; die Verbindung dieser Anfrage wird sein R\xFCckweg und braucht einen Ereignisstrom.",
157
+ description: "Einen Arbeitsplatz anmelden oder seine Ordner erneuern; die Verbindung dieser Anfrage wird sein R\xFCckweg und braucht einen Ereignisstrom. Ein Arbeitsplatz mit anderem Executor-Stand scheitert an seinem Stand, bevor die \xFCbrige Form z\xE4hlt.",
134
158
  rights: ["runs.write"],
135
- input: Type.Object({ id: clientId, ...clientDescription, executor: executorVersion }, { additionalProperties: false }),
159
+ input: Type.Union([clientRegistrationSchema, otherExecutorRegistration]),
136
160
  result: clientInfoSchema
137
161
  }),
138
162
  unregister: defineOperation({
@@ -228,11 +252,11 @@ var serverDirectoryFolder = (directory) => {
228
252
  }
229
253
  return { path: resolved };
230
254
  };
231
- var executorShellChapter = (registry, owner, binding) => {
255
+ var executorShellChapter = (registry, owner, binding, serverTools) => {
232
256
  const { machine } = binding;
233
- if (machine === "server") return shellPlatformChapter(process.platform);
257
+ if (machine === "server") return shellPlatformChapter(process.platform, serverTools);
234
258
  const client = registry.info(owner, machine.client);
235
- return client ? shellPlatformChapter(client.platform) : `## Shell platform
259
+ return client ? shellPlatformChapter(client.platform, { ripgrep: client.ripgrep }) : `## Shell platform
236
260
 
237
261
  The workstation ${machine.label} that holds this project is not registered right now, so the platform of its shell is unknown; the workspace tools fail until it connects again.`;
238
262
  };
@@ -386,11 +410,13 @@ var createBrowseChannel = (options) => implementChannel(workspaceContracts.chann
386
410
  });
387
411
 
388
412
  // server/clients.ts
413
+ import { Value } from "typebox/value";
389
414
  import {
390
415
  DomainError as DomainError2,
391
416
  RPC_ERROR_CODES,
392
417
  RpcError,
393
- implement as implement2
418
+ implement as implement2,
419
+ schemaComplaints
394
420
  } from "@ragents/engine";
395
421
  import {
396
422
  WORKSPACE_EXECUTOR_VERSION,
@@ -420,6 +446,26 @@ var withClientCause = (cause, label) => {
420
446
  var unreached = (cause) => cause instanceof DomainError2 && (cause.code === "workspace-client-disconnected" || cause.code === "workspace-client-timeout");
421
447
  var messageOf = (cause) => cause instanceof Error ? cause.message : String(cause);
422
448
  var keyOf = (owner, id) => JSON.stringify([owner, id]);
449
+ var assertExecutor = (label, executor) => {
450
+ if (executor === WORKSPACE_EXECUTOR_VERSION) return;
451
+ const action = Number(executor) > Number(WORKSPACE_EXECUTOR_VERSION) ? "Den Server auf die Fassung des Arbeitsplatzes aktualisieren." : "Die RAgents-Erweiterung in VS Code beziehungsweise das Paket @schlenkr/ragents auf dem Arbeitsplatz aktualisieren.";
452
+ throw new DomainError2(
453
+ "workspace-executor-version",
454
+ `Der Arbeitsplatz ${label} bringt den Executor ${executor} mit, der Server verlangt ${WORKSPACE_EXECUTOR_VERSION}. ${action}`,
455
+ 409
456
+ );
457
+ };
458
+ var described = (contributions) => contributions.map(({ plugin: plugin2, stand }) => `${plugin2} (${stand.slice(0, 12)})`).join(", ") || "keine";
459
+ var assertContributions = (label, expected, given) => {
460
+ const key = (entry) => `${entry.plugin}\0${entry.stand}`;
461
+ const same = expected.length === given.length && expected.every((entry) => given.some((other) => key(other) === key(entry)));
462
+ if (same) return;
463
+ throw new DomainError2(
464
+ "workspace-executor-contributions",
465
+ `Der Arbeitsplatz ${label} bringt die Executor-Beitr\xE4ge ${described(given)} mit, der Server verlangt ${described(expected)}. Der Arbeitsplatz fragt sie mit ragents.workspace.clients.contributions ab und meldet sich danach erneut an.`,
466
+ 409
467
+ );
468
+ };
423
469
  var assertMayRegister = (access, local) => {
424
470
  if (local || access.enabled && access.user !== null) return;
425
471
  throw new DomainError2(
@@ -429,21 +475,21 @@ var assertMayRegister = (access, local) => {
429
475
  );
430
476
  };
431
477
  var WorkspaceClientRegistry = class {
478
+ /** Was die Plugins des Servers zum Executor beitragen; jeder Arbeitsplatz muss genau diese Beiträge tragen. */
479
+ contributions;
432
480
  #clients = /* @__PURE__ */ new Map();
433
481
  /** Stopps, die den Arbeitsplatz noch nicht erreicht haben, je Arbeitsplatz und Run mit dem Ordner der Bindung. */
434
482
  #pendingStops = /* @__PURE__ */ new Map();
435
483
  #stopRetries = /* @__PURE__ */ new Map();
436
- async register(id, description, executor, connection) {
484
+ constructor(contributions) {
485
+ this.contributions = contributions.map(({ plugin: plugin2, stand }) => ({ plugin: plugin2, stand }));
486
+ }
487
+ async register(id, description, executor, contributions, connection) {
437
488
  if (connection.streamless) {
438
489
  throw new DomainError2("stream-required", "Die Anmeldung eines Arbeitsplatzes braucht einen Ereignisstrom.", 409);
439
490
  }
440
- if (executor !== WORKSPACE_EXECUTOR_VERSION) {
441
- throw new DomainError2(
442
- "workspace-executor-version",
443
- `Der Arbeitsplatz ${description.label} bringt den Executor ${executor} mit, der Server verlangt ${WORKSPACE_EXECUTOR_VERSION}.`,
444
- 409
445
- );
446
- }
491
+ assertExecutor(description.label, executor);
492
+ assertContributions(description.label, this.contributions, contributions);
447
493
  const owner = connection.userId;
448
494
  const key = keyOf(owner, id);
449
495
  const previous = this.#clients.get(key);
@@ -624,9 +670,22 @@ var WorkspaceClientRegistry = class {
624
670
  };
625
671
  var clientMethods = (registry) => [
626
672
  implement2(workspaceContracts.clients.list, (_input, { access }) => registry.list(ownerOf(access))),
627
- implement2(workspaceContracts.clients.register, ({ id, executor, ...description }, { access, connection, local }) => {
673
+ implement2(workspaceContracts.clients.contributions, ({ label, executor }, { access, local }) => {
628
674
  assertMayRegister(access, local);
629
- return registry.register(id, description, executor, connection);
675
+ assertExecutor(label, executor);
676
+ return registry.contributions.map((entry) => ({ ...entry }));
677
+ }),
678
+ implement2(workspaceContracts.clients.register, (input, { access, connection, local }) => {
679
+ assertMayRegister(access, local);
680
+ assertExecutor(input.label, input.executor);
681
+ if (!Value.Check(clientRegistrationSchema, input)) {
682
+ throw new RpcError(
683
+ RPC_ERROR_CODES.invalidParams,
684
+ `Ung\xFCltige Eingabe f\xFCr ${workspaceContracts.clients.register.id}: ${schemaComplaints(clientRegistrationSchema, input, "params")}`
685
+ );
686
+ }
687
+ const { id, executor, contributions, ...description } = input;
688
+ return registry.register(id, description, executor, contributions, connection);
630
689
  }),
631
690
  implement2(workspaceContracts.clients.unregister, ({ id }, { access, connection }) => {
632
691
  registry.unregister(ownerOf(access), id, connection);
@@ -640,7 +699,9 @@ import { PROCESS_SANDBOX_DEFAULT_NETWORK } from "@ragents/host/plugin-support/pr
640
699
  var workspaceConfigDescriptors = [
641
700
  { key: "PROCESS_SANDBOX", source: "environment" },
642
701
  { key: "PROCESS_SANDBOX_NETWORK", source: "environment" },
643
- { key: "RAGENTS_BASH", source: "environment" }
702
+ { key: "RAGENTS_BASH", source: "environment" },
703
+ { key: "RAGENTS_RG", source: "environment" },
704
+ { key: "RAGENTS_BASH_TIMEOUT_SECONDS", source: "environment" }
644
705
  ];
645
706
  var env = declaredEnvironment(workspaceConfigDescriptors);
646
707
  var processSandboxSetting = () => {
@@ -652,6 +713,8 @@ var processSandboxSetting = () => {
652
713
  return { enabled: mode === "on", network };
653
714
  };
654
715
  var bashSetting = () => env.optional("RAGENTS_BASH") || void 0;
716
+ var rgSetting = () => env.optional("RAGENTS_RG") || void 0;
717
+ var bashTimeoutSetting = () => env.optional("RAGENTS_BASH_TIMEOUT_SECONDS") ? env.positiveNumber("RAGENTS_BASH_TIMEOUT_SECONDS", "") : void 0;
655
718
 
656
719
  // server/runtime.ts
657
720
  import { mkdir, realpath } from "node:fs/promises";
@@ -727,6 +790,7 @@ var RunWorkspaceRuntime = class {
727
790
  this.#nugetCacheDirectory = path2.join(options.globalDirectory, "nuget-cache");
728
791
  this.sandbox = new WorkspaceSandboxHost({
729
792
  contributorName: "ragents.workspace.sandbox",
793
+ contributions: options.contributions,
730
794
  workspaceFor: options.sessionWorkspaceFor,
731
795
  identFor: () => Promise.resolve(void 0),
732
796
  skillPaths: options.skillPaths,
@@ -735,7 +799,9 @@ var RunWorkspaceRuntime = class {
735
799
  executorFor: (runId) => Promise.resolve(this.#executorFor(runId)),
736
800
  serverDirectoryFor: (runId) => this.#serverDirectoryFor(runId),
737
801
  ...options.processSandbox ? { processSandbox: options.processSandbox } : {},
738
- ...options.bash === void 0 ? {} : { bash: options.bash }
802
+ ...options.bash === void 0 ? {} : { bash: options.bash },
803
+ ...options.rg === void 0 ? {} : { rg: options.rg },
804
+ ...options.bashTimeoutSeconds === void 0 ? {} : { bashTimeoutSeconds: options.bashTimeoutSeconds }
739
805
  });
740
806
  }
741
807
  /** Arbeit eines Runs, die auf dem Server läuft, während sein Arbeitsbereich auf einem Arbeitsplatz liegt. */
@@ -815,8 +881,8 @@ var RunWorkspaceRuntime = class {
815
881
  async #withRoots(workspace, onWorkstation) {
816
882
  const roots = await this.sandbox.serverRoots();
817
883
  if (roots.length === 0) return workspace;
818
- const described = onWorkstation ? workstationRootsDescription(roots) : serverRootsDescription(roots);
819
- return { ...workspace, description: [workspace.description, described].filter(Boolean).join("\n\n") };
884
+ const described2 = onWorkstation ? workstationRootsDescription(roots) : serverRootsDescription(roots);
885
+ return { ...workspace, description: [workspace.description, described2].filter(Boolean).join("\n\n") };
820
886
  }
821
887
  placementOf(runId) {
822
888
  const { machine, folder } = bindingOf(this.#options.runState(runId));
@@ -970,7 +1036,8 @@ var ragentsWorkspacePlugin = (skillPaths) => ({
970
1036
  if (!directory) throw new Error("In diesem Profil gibt es keine Dateiablage; das Plugin ragents.documents fehlt");
971
1037
  return directory;
972
1038
  };
973
- const clients = new WorkspaceClientRegistry();
1039
+ const contributions = host.service(executorContributionsToken);
1040
+ const clients = new WorkspaceClientRegistry(contributions);
974
1041
  const contribution = () => host.optionalService(workspaceResolverToken);
975
1042
  host.config(...workspaceConfigDescriptors);
976
1043
  const sandboxSetting = processSandboxSetting();
@@ -980,10 +1047,16 @@ var ragentsWorkspacePlugin = (skillPaths) => ({
980
1047
  dataDirectory: path3.dirname(host.storage.sessionsRoot)
981
1048
  }) : void 0;
982
1049
  const bash = bashSetting();
1050
+ const rg = rgSetting();
1051
+ const bashTimeoutSeconds = bashTimeoutSetting();
1052
+ const serverTools = { ripgrep: ripgrepAvailable(rg, process.env) };
983
1053
  const runtime = new RunWorkspaceRuntime({
984
1054
  clients,
1055
+ contributions: contributions.map((contribution2) => contribution2.parts),
985
1056
  ...processSandbox ? { processSandbox } : {},
986
1057
  ...bash === void 0 ? {} : { bash },
1058
+ ...rg === void 0 ? {} : { rg },
1059
+ ...bashTimeoutSeconds === void 0 ? {} : { bashTimeoutSeconds },
987
1060
  globalDirectory: host.storage.root(),
988
1061
  sessionDirectory: (runId, ...segments) => host.storage.session(runId, ...segments),
989
1062
  storageRootFor: (runId) => path3.join(host.storage.sessionsRoot, runId),
@@ -1012,9 +1085,9 @@ var ragentsWorkspacePlugin = (skillPaths) => ({
1012
1085
  // Die Regeln gelten für die Arbeitsbereiche des Hosts; eine beigesteuerte Art beschreibt ihre eigenen.
1013
1086
  render: (context) => contribution()?.kind ? "" : rules.render(context)
1014
1087
  }, ...agentWorkspaceToolNames),
1015
- shellPlatformPrompt("ragents.workspace.shell.prompt", 102, (runId) => {
1088
+ shellPlatformPrompt("ragents.workspace.shell.prompt", 102, serverTools, (runId) => {
1016
1089
  const state = runState(runId);
1017
- return executorShellChapter(clients, workspaceOwnerOf(state), bindingOf(state));
1090
+ return executorShellChapter(clients, workspaceOwnerOf(state), bindingOf(state), serverTools);
1018
1091
  })
1019
1092
  );
1020
1093
  const browseOptions = {