@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.
- package/apps/server/src/config-definition.ts +24 -2
- package/apps/server/src/config.ts +0 -6
- package/apps/server/src/host-api.json +3 -10
- package/apps/server/src/host-api.ts +6 -7
- package/apps/server/src/plugin-build/build.ts +28 -5
- package/apps/server/src/plugin-build/plugin-description.ts +1 -1
- package/apps/server/src/plugin-build/typecheck.ts +2 -2
- package/apps/server/src/plugin-support/language-server/plugin.ts +8 -7
- package/apps/server/src/plugin-support/language-server/tools.ts +7 -6
- package/apps/server/src/plugin-support/model-aliases.ts +55 -25
- package/apps/server/src/plugin-support/plugin-folder.ts +2 -1
- package/apps/server/src/plugin-support/product-relay.ts +10 -2
- package/apps/server/src/plugin-support/workspace-sandbox-host.ts +18 -9
- package/apps/server/src/profile/bundle-manifest.ts +7 -3
- package/apps/server/src/profile/compose.ts +6 -0
- package/apps/server/src/profile/plugin-discovery.ts +6 -1
- package/apps/server/src/profile/provisioning.ts +6 -5
- package/apps/server/src/ragents/engine.ts +18 -12
- package/apps/server/src/ragents/host-services.ts +4 -0
- package/apps/server/src/ragents/session.ts +1 -1
- package/apps/server/src/server.ts +1 -0
- package/apps/server/tsconfig.json +2 -0
- package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-CFhTJEmH.js → highlighted-body-KPVGNVTW-xXXhTDbh.js} +1 -1
- package/apps/web/dist/assets/{main-DlzW4t4c.js → main-C7JeZFjs.js} +1 -1
- package/apps/web/dist/assets/{mermaid-HWGCJPDP-kxkB991i.js → mermaid-HWGCJPDP-DfsU5ofC.js} +2 -2
- package/apps/web/dist/assets/{runPanel-BJEFQ__w.js → runPanel-ZT6TPDLM.js} +1 -1
- package/apps/web/dist/help/guide-clients.html +14 -6
- package/apps/web/dist/help/guide-clients.md +14 -6
- package/apps/web/dist/help/guide-distributed.html +12 -4
- package/apps/web/dist/help/guide-distributed.md +12 -4
- package/apps/web/dist/help/guide-getting-started.html +12 -8
- package/apps/web/dist/help/guide-getting-started.md +12 -8
- package/apps/web/dist/help/guide-plugins.html +6 -2
- package/apps/web/dist/help/guide-plugins.md +6 -2
- package/apps/web/dist/help/guide-runtime.html +2 -1
- package/apps/web/dist/help/guide-runtime.md +2 -1
- package/apps/web/dist/help/index.html +3328 -1135
- package/apps/web/dist/host-web.json +4 -4
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/run-panel.html +2 -2
- package/apps/web/src/StartTiles.tsx +1 -1
- package/bundles/ragents.activity/ragents-bundle.json +3 -3
- package/bundles/ragents.actor-programs/ragents-bundle.json +3 -3
- package/bundles/ragents.ask/ragents-bundle.json +4 -4
- package/bundles/ragents.ask/server/index.js +42 -11
- package/bundles/ragents.ask/server/index.js.map +3 -3
- package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js +2 -0
- package/bundles/ragents.ask/web/chunks/chunk-WFN4374U.js.map +7 -0
- package/bundles/ragents.ask/web/classes.json +1 -1
- package/bundles/ragents.ask/web/exports/ask-payload.js +1 -1
- package/bundles/ragents.ask/web/index.js +1 -1
- package/bundles/ragents.ask/web/index.js.map +3 -3
- package/bundles/ragents.browser/executor/index.mjs +357 -0
- package/bundles/ragents.browser/executor/index.mjs.map +7 -0
- package/bundles/ragents.browser/ragents-bundle.json +5 -8
- package/bundles/ragents.browser/server/chunks/{chunk-2GKLLCBE.js → chunk-CWLX4VA5.js} +1 -1
- package/bundles/ragents.browser/server/chunks/chunk-CWLX4VA5.js.map +7 -0
- package/bundles/ragents.browser/server/exports/server/contract.js +1 -1
- package/bundles/ragents.browser/server/index.js +20 -9
- package/bundles/ragents.browser/server/index.js.map +4 -4
- package/bundles/ragents.documents/ragents-bundle.json +3 -3
- package/bundles/ragents.lsp-fsharp/executor/index.mjs +68 -0
- package/bundles/ragents.lsp-fsharp/executor/index.mjs.map +7 -0
- package/bundles/ragents.lsp-fsharp/ragents-bundle.json +5 -9
- package/bundles/ragents.lsp-fsharp/server/index.js +21 -6
- package/bundles/ragents.lsp-fsharp/server/index.js.map +4 -4
- package/bundles/ragents.lsp-roslyn/executor/index.mjs +68 -0
- package/bundles/ragents.lsp-roslyn/executor/index.mjs.map +7 -0
- package/bundles/ragents.lsp-roslyn/ragents-bundle.json +6 -8
- package/bundles/ragents.lsp-roslyn/server/index.js +54 -15
- package/bundles/ragents.lsp-roslyn/server/index.js.map +4 -4
- package/bundles/ragents.lsp-typescript/executor/index.mjs +49 -0
- package/bundles/ragents.lsp-typescript/executor/index.mjs.map +7 -0
- package/bundles/ragents.lsp-typescript/ragents-bundle.json +5 -7
- package/bundles/ragents.lsp-typescript/server/index.js +22 -2
- package/bundles/ragents.lsp-typescript/server/index.js.map +3 -3
- package/bundles/ragents.model-relay/ragents-bundle.json +4 -4
- package/bundles/ragents.model-relay/server/index.js +3 -2
- package/bundles/ragents.model-relay/server/index.js.map +2 -2
- package/bundles/ragents.orchestration/ragents-bundle.json +3 -3
- package/bundles/ragents.overseer/ragents-bundle.json +3 -3
- package/bundles/ragents.processes/ragents-bundle.json +3 -3
- package/bundles/ragents.product/ragents-bundle.json +3 -3
- package/bundles/ragents.profile-distribution/ragents-bundle.json +4 -4
- package/bundles/ragents.profile-distribution/server/index.js +1 -1
- package/bundles/ragents.profile-distribution/server/index.js.map +2 -2
- package/bundles/ragents.reference/ragents-bundle.json +3 -3
- package/bundles/ragents.todo/ragents-bundle.json +3 -3
- package/bundles/ragents.transcript/ragents-bundle.json +3 -3
- package/bundles/ragents.watch/ragents-bundle.json +3 -3
- package/bundles/ragents.workspace/ragents-bundle.json +11 -5
- package/bundles/ragents.workspace/server/index.js +101 -28
- package/bundles/ragents.workspace/server/index.js.map +3 -3
- package/bundles/ragents.workspace/web/classes.json +1 -1
- package/bundles/ragents.workspace/web/index.js +1 -1
- package/bundles/ragents.workspace/web/index.js.map +3 -3
- package/package.json +2 -2
- package/packages/agent/dist/core/agent-settings.d.ts +1 -7
- package/packages/agent/dist/core/compaction/compaction.d.ts +17 -13
- package/packages/agent/dist/core/model-runtime.d.ts +5 -4
- package/packages/agent/dist/core/provider-composer.d.ts +2 -1
- package/packages/agent/dist/core/tools/bash.d.ts +9 -3
- package/packages/agent/dist/index.d.ts +1 -1
- package/packages/agent/src/core/agent-settings.ts +1 -4
- package/packages/agent/src/core/compaction/compaction.ts +68 -30
- package/packages/agent/src/core/model-runtime.ts +12 -5
- package/packages/agent/src/core/provider-composer.ts +5 -0
- package/packages/agent/src/core/tools/bash.ts +36 -30
- package/packages/agent/src/index.ts +3 -0
- package/packages/ai/dist/types.d.ts +11 -0
- package/packages/ai/src/types.ts +12 -0
- package/packages/ragents/src/agents/plugins.ts +5 -0
- package/packages/ragents/src/domain/event-semantics.ts +3 -0
- package/packages/ragents/src/domain/event-validation.ts +15 -2
- package/packages/ragents/src/domain/events.ts +3 -0
- package/packages/ragents/src/domain/model.ts +2 -0
- package/packages/ragents/src/domain/projection.ts +1 -0
- package/packages/ragents/src/drivers/agent-runtime.ts +1 -1
- package/packages/ragents/src/drivers/agent-turn.ts +8 -6
- package/packages/ragents/src/index.ts +1 -0
- package/packages/ragents/src/plugin-host.ts +58 -10
- package/packages/ragents/src/plugin-types.ts +7 -2
- package/packages/ragents/src/runtime/decisions/inputs.ts +6 -2
- package/packages/ragents/src/runtime/journal-storage.ts +5 -4
- package/packages/workspace-executor/package.json +0 -1
- package/packages/workspace-executor/src/bash-launch.ts +56 -10
- package/packages/workspace-executor/src/context.ts +4 -0
- package/packages/workspace-executor/src/contributions.ts +150 -0
- package/packages/workspace-executor/src/executor.ts +1 -1
- package/packages/workspace-executor/src/index.ts +16 -19
- package/packages/workspace-executor/src/language-server/host.ts +3 -0
- package/packages/workspace-executor/src/language-server/module.ts +12 -2
- package/packages/workspace-executor/src/language-server/roots.ts +0 -5
- package/packages/workspace-executor/src/modules.ts +7 -6
- package/packages/workspace-executor/src/sandbox-tools.ts +3 -9
- package/packages/workspace-executor/src/shell-platform.ts +14 -3
- package/packages/workspace-executor/src/tools.ts +0 -3
- package/plugins/ragents.ask/ask-payload.ts +9 -0
- package/plugins/ragents.ask/server/ask-service.ts +53 -13
- package/plugins/ragents.ask/web/AskActionView.tsx +3 -2
- package/plugins/ragents.browser/executor/index.ts +5 -0
- package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/module.ts +25 -31
- package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/playwright.ts +9 -23
- package/plugins/ragents.browser/provision.ts +1 -1
- package/plugins/ragents.browser/server/browser.ts +3 -3
- package/plugins/ragents.browser/server/contract.ts +2 -2
- package/plugins/ragents.browser/server/index.ts +1 -1
- package/plugins/ragents.lsp-fsharp/executor.ts +80 -0
- package/plugins/ragents.lsp-fsharp/provision.ts +1 -1
- package/plugins/ragents.lsp-fsharp/server/index.ts +2 -2
- package/plugins/ragents.lsp-roslyn/executor.ts +64 -0
- package/plugins/ragents.lsp-roslyn/provision.ts +1 -1
- package/plugins/ragents.lsp-roslyn/server/index.ts +28 -5
- package/plugins/ragents.lsp-roslyn/server/solution-on-start.ts +18 -6
- package/plugins/ragents.lsp-typescript/executor.ts +50 -0
- package/plugins/ragents.lsp-typescript/server/index.ts +2 -2
- package/plugins/ragents.model-relay/server/config.ts +1 -1
- package/plugins/ragents.model-relay/server/relay.ts +4 -2
- package/plugins/ragents.profile-distribution/server/archive.ts +2 -1
- package/plugins/ragents.workspace/client/workspace-client.ts +111 -28
- package/plugins/ragents.workspace/contract.ts +33 -2
- package/plugins/ragents.workspace/server/binding.ts +10 -4
- package/plugins/ragents.workspace/server/clients.ts +56 -9
- package/plugins/ragents.workspace/server/config.ts +9 -0
- package/plugins/ragents.workspace/server/index.ts +13 -4
- package/plugins/ragents.workspace/server/runtime.ts +10 -0
- package/plugins/ragents.workspace/server/shell-platform.ts +6 -5
- package/plugins/ragents.workspace/web/WorkspaceBinding.tsx +1 -1
- package/ragents.config.core.ts +4 -1
- package/ragents.config.showcase.ts +4 -1
- package/scripts/agent/journal.ts +3 -1
- package/scripts/package/build-package.ts +3 -1
- package/scripts/package/publish-package.ts +4 -3
- package/scripts/provision/run-provision.ts +2 -2
- package/scripts/workspace-client/run-workspace-client.ts +7 -4
- package/apps/web/dist/help/screenshots/release-checklist-vscode.png +0 -0
- package/apps/web/dist/help/screenshots/release-checklist-web.png +0 -0
- package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js +0 -2
- package/bundles/ragents.ask/web/chunks/chunk-HGFDGTNC.js.map +0 -7
- package/bundles/ragents.browser/server/chunks/chunk-2GKLLCBE.js.map +0 -7
- package/packages/workspace-executor/src/language-server/adapters/fsharp.ts +0 -60
- package/packages/workspace-executor/src/language-server/adapters/index.ts +0 -7
- package/packages/workspace-executor/src/language-server/adapters/roslyn.ts +0 -56
- package/packages/workspace-executor/src/language-server/adapters/typescript.ts +0 -74
- package/packages/workspace-executor/src/language-server/solution.ts +0 -13
- /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/contract.ts +0 -0
- /package/{packages/workspace-executor/src/browser → plugins/ragents.browser/executor}/pages.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"format":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.processes",
|
|
4
|
-
"api":
|
|
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": "
|
|
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":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.product",
|
|
4
|
-
"api":
|
|
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": "
|
|
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":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.profile-distribution",
|
|
4
|
-
"api":
|
|
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": "
|
|
56
|
-
"sourceStand": "
|
|
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":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.reference",
|
|
4
|
-
"api":
|
|
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": "
|
|
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":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.todo",
|
|
4
|
-
"api":
|
|
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": "
|
|
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":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.transcript",
|
|
4
|
-
"api":
|
|
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": "
|
|
26
|
+
"sourceStand": "04596bd6ff61db0f6f956bec63fc8783f329a03f32e80366fb5beed4e1bdf55d",
|
|
27
27
|
"server": "server/index.js",
|
|
28
28
|
"exports": {
|
|
29
29
|
"server": {},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"format":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.watch",
|
|
4
|
-
"api":
|
|
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": "
|
|
28
|
+
"sourceStand": "0515fbdf8c4bf2859a4c09d2d1c0feb9ebf502af2f164cc6337f9d44d0463cc4",
|
|
29
29
|
"server": "server/index.js",
|
|
30
30
|
"exports": {
|
|
31
31
|
"server": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"format":
|
|
2
|
+
"format": 4,
|
|
3
3
|
"id": "ragents.workspace",
|
|
4
|
-
"api":
|
|
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": "
|
|
134
|
-
"sourceStand": "
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
441
|
-
|
|
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.
|
|
673
|
+
implement2(workspaceContracts.clients.contributions, ({ label, executor }, { access, local }) => {
|
|
628
674
|
assertMayRegister(access, local);
|
|
629
|
-
|
|
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
|
|
819
|
-
return { ...workspace, description: [workspace.description,
|
|
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
|
|
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 = {
|