@schlenkr/ragents 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/apps/server/package.json +1 -1
  2. package/apps/server/src/access-projection.ts +6 -36
  3. package/apps/server/src/api/contracts.ts +5 -2
  4. package/apps/server/src/api/core-methods.ts +5 -3
  5. package/apps/server/src/config-file.ts +1 -1
  6. package/apps/server/src/host-api.json +2 -0
  7. package/apps/server/src/plugin-support/process-sandbox.ts +16 -15
  8. package/apps/server/src/provider.ts +2 -2
  9. package/apps/server/src/ragents/engine.ts +2 -1
  10. package/apps/server/src/ragents/global-chat.ts +7 -1
  11. package/apps/server/src/server.ts +3 -1
  12. package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-xXXhTDbh.js → highlighted-body-KPVGNVTW-BO4wLQtE.js} +1 -1
  13. package/apps/web/dist/assets/main-DnnqWHkH.js +11 -0
  14. package/apps/web/dist/assets/mermaid-HWGCJPDP-BLLeth5_.js +568 -0
  15. package/apps/web/dist/assets/{runPanel-ZT6TPDLM.js → runPanel-DPm7s3KM.js} +2 -2
  16. package/apps/web/dist/help/guide-clients.html +17 -7
  17. package/apps/web/dist/help/guide-clients.md +18 -7
  18. package/apps/web/dist/help/index.html +1911 -908
  19. package/apps/web/dist/help/mini-app.css +24 -0
  20. package/apps/web/dist/host-web.json +2 -2
  21. package/apps/web/dist/index.html +2 -2
  22. package/apps/web/dist/run-panel.html +2 -2
  23. package/apps/web/package.json +1 -1
  24. package/apps/web/src/panel/ConnectionsPage.tsx +3 -0
  25. package/apps/web/src/panel/StartPage.tsx +3 -0
  26. package/apps/web/src/panel/contract.ts +7 -0
  27. package/bundles/ragents.activity/ragents-bundle.json +1 -1
  28. package/bundles/ragents.actor-programs/ragents-bundle.json +2 -2
  29. package/bundles/ragents.actor-programs/server/index.js +31 -3
  30. package/bundles/ragents.actor-programs/server/index.js.map +4 -4
  31. package/bundles/ragents.actor-programs/web/index.js.map +1 -1
  32. package/bundles/ragents.ask/ragents-bundle.json +2 -4
  33. package/bundles/ragents.ask/web/chunks/{chunk-V7W3QDVS.js → chunk-MBRPS477.js} +2 -2
  34. package/bundles/ragents.ask/web/chunks/{chunk-V7W3QDVS.js.map → chunk-MBRPS477.js.map} +4 -4
  35. package/bundles/ragents.ask/web/classes.json +1 -1
  36. package/bundles/ragents.ask/web/exports/web/QuestionCard.js +1 -1
  37. package/bundles/ragents.ask/web/index.js +1 -1
  38. package/bundles/ragents.ask/web/index.js.map +4 -4
  39. package/bundles/ragents.browser/ragents-bundle.json +1 -1
  40. package/bundles/ragents.documents/ragents-bundle.json +1 -1
  41. package/bundles/ragents.lsp-fsharp/ragents-bundle.json +1 -1
  42. package/bundles/ragents.lsp-roslyn/ragents-bundle.json +1 -1
  43. package/bundles/ragents.lsp-typescript/ragents-bundle.json +1 -1
  44. package/bundles/ragents.model-relay/ragents-bundle.json +1 -1
  45. package/bundles/ragents.orchestration/ragents-bundle.json +2 -2
  46. package/bundles/ragents.orchestration/web/classes.json +1 -1
  47. package/bundles/ragents.orchestration/web/index.js +6 -6
  48. package/bundles/ragents.orchestration/web/index.js.map +3 -3
  49. package/bundles/ragents.overseer/ragents-bundle.json +2 -2
  50. package/bundles/ragents.overseer/server/index.js +1 -1
  51. package/bundles/ragents.overseer/server/index.js.map +2 -2
  52. package/bundles/ragents.processes/ragents-bundle.json +1 -1
  53. package/bundles/ragents.product/ragents-bundle.json +1 -1
  54. package/bundles/ragents.profile-distribution/ragents-bundle.json +1 -1
  55. package/bundles/ragents.reference/ragents-bundle.json +1 -1
  56. package/bundles/ragents.todo/ragents-bundle.json +1 -1
  57. package/bundles/ragents.transcript/ragents-bundle.json +1 -1
  58. package/bundles/ragents.watch/ragents-bundle.json +1 -1
  59. package/bundles/ragents.workspace/ragents-bundle.json +2 -2
  60. package/bundles/ragents.workspace/server/index.js +4 -2
  61. package/bundles/ragents.workspace/server/index.js.map +2 -2
  62. package/package.json +3 -3
  63. package/packages/agent/dist/core/tools/bash.d.ts +1 -1
  64. package/packages/agent/src/core/tools/bash.ts +1 -1
  65. package/packages/ragents/src/index.ts +1 -0
  66. package/packages/ragents/src/plugin-host.ts +46 -0
  67. package/packages/ragents/src/plugin-types.ts +19 -0
  68. package/packages/workspace-executor/src/managed-process.ts +28 -0
  69. package/packages/workspace-executor/src/sandbox-tools.ts +9 -3
  70. package/plugins/ragents.actor-programs/server/access-projections.ts +31 -0
  71. package/plugins/ragents.actor-programs/server/index.ts +2 -0
  72. package/plugins/ragents.ask/web/index.tsx +0 -6
  73. package/plugins/ragents.orchestration/web/ActorTile.tsx +1 -1
  74. package/plugins/ragents.orchestration/web/run-panel/RunPanel.tsx +8 -7
  75. package/plugins/ragents.orchestration/web/run-panel/sheet-status.ts +3 -3
  76. package/plugins/ragents.overseer/server/api.ts +2 -2
  77. package/plugins/ragents.workspace/client/workspace-client.ts +19 -6
  78. package/plugins/ragents.workspace/server/config.ts +3 -0
  79. package/plugins/ragents.workspace/server/index.ts +3 -2
  80. package/apps/web/dist/assets/main-C7JeZFjs.js +0 -6
  81. package/apps/web/dist/assets/mermaid-HWGCJPDP-DfsU5ofC.js +0 -478
  82. package/plugins/ragents.ask/web/QuestionSection.tsx +0 -48
@@ -19,7 +19,7 @@
19
19
  "@ragents/engine": "workspace:*",
20
20
  "@ragents/workspace-executor": "workspace:*",
21
21
  "handlebars": "^4.7.9",
22
- "quassel": "^0.2.2",
22
+ "quassel": "^0.3.0",
23
23
  "tsx": "^4.20.0",
24
24
  "typebox": "^1.3.13",
25
25
  "vscode-jsonrpc": "^9.0.2"
@@ -1,37 +1,9 @@
1
- import { emptyUsage, type AccessContext, type JsonValue, type PluginState, type RunView } from "@ragents/engine";
1
+ import { emptyUsage, type AccessContext, type AccessProjectionRegistry, type RunView } from "@ragents/engine";
2
2
  import type { ChatEvent, Message } from "quassel/events";
3
3
  import type { ActorConversations } from "./ragents/actor-chat-history.js";
4
4
 
5
- const record = (value: JsonValue | undefined): Record<string, JsonValue | undefined> | undefined =>
6
- value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
7
-
8
- const hiddenStates = new Set(["ragents.system-prompt", "ragents.model", "ragents.start-options"]);
9
-
10
- const visibleState = (entry: PluginState): PluginState | undefined => {
11
- if (hiddenStates.has(entry.pluginId)) return undefined;
12
- if (entry.pluginId === "ragents.actor-programs.invocations") return { ...entry, state: { version: 1, revision: entry.updatedAt } };
13
- if (entry.pluginId !== "ragents.actor-programs") return entry;
14
- const state = record(entry.state);
15
- const program = state?.program ? record(state.program) : undefined;
16
- if (!program) return entry;
17
- const views = Array.isArray(program.views) ? program.views.map((value) => {
18
- const view = record(value);
19
- return view ? { id: view.id, key: view.key, title: view.title, visible: view.visible, placements: view.placements } : value;
20
- }) : [];
21
- return { ...entry, state: {
22
- version: 1,
23
- program: {
24
- name: program.name,
25
- title: program.title,
26
- actorId: program.actorId,
27
- actorHandle: program.actorHandle,
28
- revision: program.revision,
29
- views,
30
- },
31
- } };
32
- };
33
-
34
- export const accessibleRunView = (view: RunView, access: AccessContext): RunView => access.can("runs.inspect") ? view : {
5
+ /** Plugin-Zustände und Plugin-Ereignisse zeigt jedes Plugin selbst über seine Zugriffsprojektion (docs/spec/plugins.md, Registrierungen des PluginHost). */
6
+ export const accessibleRunView = (view: RunView, access: AccessContext, projections: AccessProjectionRegistry): RunView => access.can("runs.inspect") ? view : {
35
7
  ...view,
36
8
  actors: view.actors.map((actor) => actor.kind === "human" ? { ...actor, grants: [] } : {
37
9
  ...actor,
@@ -53,12 +25,12 @@ export const accessibleRunView = (view: RunView, access: AccessContext): RunView
53
25
  turns: view.turns.map((turn) => ({ ...turn, usage: emptyUsage(), toolCalls: [], reason: turn.reason ? "Die Verarbeitung wurde beendet." : null })),
54
26
  subscriptions: [],
55
27
  pluginStates: view.pluginStates.flatMap((entry) => {
56
- const state = visibleState(entry);
28
+ const state = projections.state(entry, access);
57
29
  return state ? [state] : [];
58
30
  }),
59
31
  };
60
32
 
61
- export const accessibleChatEvent = (event: ChatEvent, access: AccessContext): ChatEvent | undefined => {
33
+ export const accessibleChatEvent = (event: ChatEvent, access: AccessContext, projections: AccessProjectionRegistry): ChatEvent | undefined => {
62
34
  if (access.can("runs.inspect")) return event;
63
35
  if (event.kind === "status" && event.startup?.status === "failed") return {
64
36
  ...event,
@@ -70,9 +42,7 @@ export const accessibleChatEvent = (event: ChatEvent, access: AccessContext): Ch
70
42
  if (event.kind === "tool-result") return trace ? event : { kind: "tool-result", id: event.id, result: "", isError: event.isError };
71
43
  if (event.kind === "system") return { ...event, text: "Hinweis zur Verarbeitung. Bei Fragen wende Dich an den zuständigen Agenten." };
72
44
  if (event.kind !== "plugin") return event;
73
- if (hiddenStates.has(event.pluginId)) return undefined;
74
- if (event.pluginId === "ragents.actor-programs" || event.pluginId === "ragents.actor-programs.invocations") return undefined;
75
- return event;
45
+ return projections.chatEvent(event.pluginId, event, access);
76
46
  };
77
47
 
78
48
  const visibleMessage = (message: Message, actorId: string, trace: boolean): Message[] => {
@@ -25,6 +25,9 @@ const attachment = Type.Object({
25
25
  const sessionInfo = openJson<SessionInfo>("SessionInfo");
26
26
 
27
27
  /** Rechte je Run prüft der Host dynamisch; Verträge ohne `rights` nennen ihre Regel in der Beschreibung. */
28
+ /** Was eine Oberfläche beim Start vom Server bekommt: das Profil der Plugins und die RAgents-Fassung des Servers, gegen die sie ihre eigene prüft. */
29
+ export type HostBootstrap = PublicPluginProfile & { readonly version: string };
30
+
28
31
  export const coreContracts = {
29
32
  runs: {
30
33
  list: defineOperation({
@@ -161,9 +164,9 @@ export const coreContracts = {
161
164
  plugins: {
162
165
  bootstrap: defineOperation({
163
166
  id: "ragents.plugins.bootstrap",
164
- description: "Produkt, aktive Plugins mit Web-Konfiguration und freigegebene Vorlagen für die Oberfläche.",
167
+ description: "Produkt, aktive Plugins mit Web-Konfiguration, freigegebene Vorlagen und die RAgents-Fassung des Servers für die Oberfläche.",
165
168
  input: Type.Object({}, { additionalProperties: false }),
166
- result: openJson<PublicPluginProfile>("PublicPluginProfile"),
169
+ result: openJson<HostBootstrap>("HostBootstrap"),
167
170
  }),
168
171
  },
169
172
  external: {
@@ -25,6 +25,8 @@ export interface CoreMethodSources {
25
25
  saveTitleModelSettings: (value: unknown) => Promise<TitleModelSettings>;
26
26
  };
27
27
  plugins: PluginHost;
28
+ /** Die RAgents-Fassung dieses Servers; eine Oberfläche mit anderer Fassung zeigt den Unterschied. */
29
+ version: string;
28
30
  global: GlobalRunPolicy | undefined;
29
31
  /** Der Benutzer eines Runs: null ohne Eigentümer, undefined für eine Kennung ohne Run. */
30
32
  runOwner: (runId: string) => string | null | undefined;
@@ -146,7 +148,7 @@ export const coreMethods = (sources: CoreMethodSources): MethodContribution[] =>
146
148
  implement(coreContracts.settings.skill, ({ id }, { local }) => { assertSettingsReachable(local); return sessions.skill(id); }),
147
149
  implement(coreContracts.settings.titlesRead, (_input, { local }) => { assertSettingsReachable(local); return sessions.titleModelSettings(); }),
148
150
  implement(coreContracts.settings.titlesSave, ({ value }, { local }) => { assertSettingsReachable(local); return sessions.saveTitleModelSettings(value); }),
149
- implement(coreContracts.plugins.bootstrap, (_input, { access }) => sources.plugins.publicProfile(access)),
151
+ implement(coreContracts.plugins.bootstrap, (_input, { access }) => ({ ...sources.plugins.publicProfile(access), version: sources.version })),
150
152
  implement(coreContracts.external.set, async ({ state }, { local }) => {
151
153
  if (!local) throw new DomainError("local-only", "Nur lokal schaltbar", 403);
152
154
  await sources.external.set(state === "on");
@@ -155,7 +157,7 @@ export const coreMethods = (sources: CoreMethodSources): MethodContribution[] =>
155
157
  ];
156
158
  };
157
159
 
158
- export const coreChannels = (sources: Pick<CoreMethodSources, "sessions" | "global" | "runOwner" | "runOwnerOnly">): ChannelContribution[] => {
160
+ export const coreChannels = (sources: Pick<CoreMethodSources, "sessions" | "plugins" | "global" | "runOwner" | "runOwnerOnly">): ChannelContribution[] => {
159
161
  const { sessions, global } = sources;
160
162
  const policy: RunAccessPolicy = { global, ownerOf: sources.runOwner, ownerOnly: sources.runOwnerOnly };
161
163
  return [
@@ -174,7 +176,7 @@ export const coreChannels = (sources: Pick<CoreMethodSources, "sessions" | "glob
174
176
  assertRunRights(access, runId, "read", policy);
175
177
  const current = await sessions.get(runId);
176
178
  return current.subscribe((event) => {
177
- const visible = accessibleChatEvent(event, access);
179
+ const visible = accessibleChatEvent(event, access, sources.plugins.accessProjections);
178
180
  if (visible) emit(visible);
179
181
  });
180
182
  }),
@@ -106,7 +106,7 @@ export const resolveAnonymousUser = (source: string, raw: unknown): AccessUser |
106
106
  export const resolveDefaultStartEntry = (source: string, raw: unknown): string | undefined => {
107
107
  if (raw === undefined) return undefined;
108
108
  if (typeof raw !== "string" || !START_ENTRY_ID.test(raw)) {
109
- throw new Error(`${source}: defaultStartEntry braucht eine Vorlagenkennung als String, etwa "ragents.reference.word-game"`);
109
+ throw new Error(`${source}: defaultStartEntry braucht eine Vorlagenkennung als String, etwa "acme.tasks.setup"`);
110
110
  }
111
111
  return raw;
112
112
  };
@@ -884,6 +884,7 @@
884
884
  "encodeAttachment",
885
885
  "fillText",
886
886
  "formatAttachmentSize",
887
+ "formatElapsed",
887
888
  "markdownPlainText",
888
889
  "messageDate",
889
890
  "prettyJson",
@@ -891,6 +892,7 @@
891
892
  "timestampDay",
892
893
  "timestampLabel",
893
894
  "useChatAction",
895
+ "useElapsed",
894
896
  "useQuasselComponents",
895
897
  "useQuasselPortalContainer",
896
898
  "validateAttachmentSelection"
@@ -35,6 +35,8 @@ export interface ServerProcessSandboxOptions {
35
35
  /** Die Adresse dieses Servers, etwa http://127.0.0.1:4710; ohne HTTP keine. */
36
36
  readonly serverAddress: string | undefined;
37
37
  readonly dataDirectory: string;
38
+ /** Wie der Betreiber die Sandbox abschaltet, so wie er es in die Profildatei schreibt; jede Meldung, die den Start verhindert, nennt es. */
39
+ readonly disableSetting: string;
38
40
  readonly hostRoot?: string;
39
41
  readonly platform?: NodeJS.Platform;
40
42
  readonly environment?: NodeJS.ProcessEnv;
@@ -213,39 +215,38 @@ class SharedSandboxRuntime {
213
215
 
214
216
  const sharedRuntime = new SharedSandboxRuntime();
215
217
 
216
- const unsupported = (platform: NodeJS.Platform): Error => new Error(platform === "win32"
218
+ const unsupported = (platform: NodeJS.Platform, disableSetting: string): Error => new Error(platform === "win32"
217
219
  ? "Die Prozess-Sandbox gibt es auf einem Windows-Server nicht: dort lassen sich die Ordnerregeln je Run nicht setzen. "
218
- + "Wer den Server trotzdem unter Windows betreibt, schaltet sie in der Profildatei ausdrücklich ab: "
219
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace."
220
+ + `Wer den Server trotzdem unter Windows betreibt, schaltet sie in der Profildatei ausdrücklich ab: ${disableSetting}.`
220
221
  : `Die Prozess-Sandbox kennt die Plattform ${platform} nicht; unterstützt sind macOS und Linux. `
221
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace schaltet sie ausdrücklich ab.");
222
+ + `${disableSetting} schaltet sie ausdrücklich ab.`);
222
223
 
223
- const missingDependencies = (errors: readonly string[]): Error => new Error(
224
+ const missingDependencies = (errors: readonly string[], disableSetting: string): Error => new Error(
224
225
  `Die Prozess-Sandbox kann nicht starten: ${errors.join("; ")}. `
225
226
  + "Unter Linux braucht sie bubblewrap, socat und ripgrep (Debian/Ubuntu: apt-get install bubblewrap socat ripgrep). "
226
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace schaltet sie ausdrücklich ab.");
227
+ + `${disableSetting} schaltet sie ausdrücklich ab.`);
227
228
 
228
- const failedSelfTest = (detail: string): Error => new Error(
229
+ const failedSelfTest = (detail: string, disableSetting: string): Error => new Error(
229
230
  `Die Prozess-Sandbox lässt sich auf diesem Rechner nicht starten: ${detail.trim() || "ohne Ausgabe"}. `
230
231
  + "Unter Linux braucht bubblewrap Benutzer-Namensräume; in einem Container muss das Profil des Containers sie erlauben. "
231
- + "PROCESS_SANDBOX: \"off\" in der Sektion ragents.workspace schaltet sie ausdrücklich ab.");
232
+ + `${disableSetting} schaltet sie ausdrücklich ab.`);
232
233
 
233
- const runSelfTest = (launch: ProcessLaunch, environment: NodeJS.ProcessEnv): Promise<void> => new Promise((resolve, reject) => {
234
+ const runSelfTest = (launch: ProcessLaunch, environment: NodeJS.ProcessEnv, disableSetting: string): Promise<void> => new Promise((resolve, reject) => {
234
235
  const child = spawn(launch.command, [...launch.args], { stdio: ["ignore", "ignore", "pipe"], env: environment });
235
236
  let stderr = "";
236
237
  const timer = setTimeout(() => {
237
238
  child.kill("SIGKILL");
238
- reject(failedSelfTest(`keine Antwort nach ${SELF_TEST_TIMEOUT_MS / 1000} Sekunden`));
239
+ reject(failedSelfTest(`keine Antwort nach ${SELF_TEST_TIMEOUT_MS / 1000} Sekunden`, disableSetting));
239
240
  }, SELF_TEST_TIMEOUT_MS);
240
241
  child.stderr.on("data", (chunk: Buffer) => { stderr = (stderr + chunk.toString("utf8")).slice(-2_000); });
241
242
  child.once("error", (error) => {
242
243
  clearTimeout(timer);
243
- reject(failedSelfTest(error.message));
244
+ reject(failedSelfTest(error.message, disableSetting));
244
245
  });
245
246
  child.once("close", (code) => {
246
247
  clearTimeout(timer);
247
248
  if (code === 0) resolve();
248
- else reject(failedSelfTest(`Code ${code ?? "Signal"}: ${stderr}`));
249
+ else reject(failedSelfTest(`Code ${code ?? "Signal"}: ${stderr}`, disableSetting));
249
250
  });
250
251
  });
251
252
 
@@ -260,7 +261,7 @@ export class ServerProcessSandbox implements RunProcessSandboxes {
260
261
  constructor(options: ServerProcessSandboxOptions) {
261
262
  this.#options = options;
262
263
  this.#platform = options.platform ?? process.platform;
263
- if (this.#platform !== "darwin" && this.#platform !== "linux") throw unsupported(this.#platform);
264
+ if (this.#platform !== "darwin" && this.#platform !== "linux") throw unsupported(this.#platform, options.disableSetting);
264
265
  this.#protected = protectedRoots(options, this.#platform);
265
266
  this.#readable = [options.hostRoot ?? hostRoot(), ...toolchainDirectories(options, this.#protected)];
266
267
  this.#searchPath = resolvedSearchPath(options.environment ?? process.env);
@@ -269,14 +270,14 @@ export class ServerProcessSandbox implements RunProcessSandboxes {
269
270
  /** Prüft die Voraussetzungen, startet den Netz-Proxy und startet einmal einen Prozess in der Sandbox; jedes Scheitern ist ein Startfehler. */
270
271
  async start(): Promise<void> {
271
272
  const { errors } = SandboxManager.checkDependencies();
272
- if (errors.length > 0) throw missingDependencies(errors);
273
+ if (errors.length > 0) throw missingDependencies(errors, this.#options.disableSetting);
273
274
  await sharedRuntime.acquire(this, {
274
275
  network: [...this.#options.network, ...serverTarget(this.#options.serverAddress)],
275
276
  unixSockets: socketRoots(this.#options.dataDirectory, this.#platform),
276
277
  });
277
278
  try {
278
279
  const probe = this.forRun({ writable: [], readable: [], temporary: path.join(this.#options.dataDirectory, "sandbox-self-test") });
279
- await runSelfTest(await probe.wrap({ command: "true", args: [] }), this.#options.environment ?? process.env);
280
+ await runSelfTest(await probe.wrap({ command: "true", args: [] }), this.#options.environment ?? process.env, this.#options.disableSetting);
280
281
  } catch (error) {
281
282
  await sharedRuntime.release(this);
282
283
  throw error;
@@ -366,7 +366,7 @@ export class RunSessionProvider implements ChatSessionProvider {
366
366
  else if (start.kind === "package") {
367
367
  if (!local) throw new Error("Das Run-Script-Paket wurde nicht geladen");
368
368
  const { script, ...entry } = local;
369
- await session.startPackageAndWait({ ...script, entry: { ...entry, coordinator: script.coordinator, owner: "ragents.overseer" } }, start.input, user);
369
+ await session.startPackageAndWait({ ...script, entry: { ...entry, coordinator: script.coordinator, owner: start.owner } }, start.input, user);
370
370
  }
371
371
  else await session.sendAndWait(start.message, user);
372
372
  return id;
@@ -398,7 +398,7 @@ export class RunSessionProvider implements ChatSessionProvider {
398
398
 
399
399
  runView(id: string, access: AccessContext = unrestrictedAccess): unknown {
400
400
  this.ensureUsable(id);
401
- return accessibleRunView(this.requireEngine().runtime.view(id), access);
401
+ return accessibleRunView(this.requireEngine().runtime.view(id), access, this.plugins.accessProjections);
402
402
  }
403
403
 
404
404
  hasRun(id: string): boolean {
@@ -32,6 +32,7 @@ import {
32
32
  type PublicPromptSnapshot,
33
33
  type RunStopBoundary,
34
34
  type RunStopOperation,
35
+ type RunView,
35
36
  type StartOptionContributionRegistry,
36
37
  type Workspaces,
37
38
  } from "@ragents/engine";
@@ -397,7 +398,7 @@ export const createEngine = async (options: EngineOptions): Promise<Engine> => {
397
398
  assertAvailable: options.assertAvailable,
398
399
  assertRunUsable: options.assertRunUsable,
399
400
  assertRunRights: (access: AccessContext, runId: string, kind: RunRightsKind) => assertRunRights(access, runId, kind, runAccess),
400
- projectView: accessibleRunView,
401
+ projectView: (view: RunView, access: AccessContext) => accessibleRunView(view, access, options.plugins.accessProjections),
401
402
  hasRun: (runId: string) => journal.stateOf(runId) !== null,
402
403
  };
403
404
  const methods = runtimeMethods({
@@ -31,7 +31,13 @@ export type ManagedRunStart = {
31
31
  /** Wer die Startoptionen wählt und den Run besitzt: der Benutzer der Anfrage, null ohne Anmeldung. */
32
32
  user: ChatUser | null;
33
33
  } & ({ kind: "message"; message: string } | { kind: "script"; entryId: string; input: JsonValue }
34
- | { kind: "package"; directory: string; input: JsonValue });
34
+ | {
35
+ kind: "package";
36
+ directory: string;
37
+ input: JsonValue;
38
+ /** Das Plugin, das das Paket startet; es steht als Besitzer der Vorlage dieses Starts. */
39
+ owner: string;
40
+ });
35
41
 
36
42
  export interface RunManagement {
37
43
  /** Mit einem Zugang bleiben nur dessen eigene Runs übrig; ohne ihn ist es die Liste des Servers. */
@@ -23,7 +23,7 @@ import { Protocol, teeConsole } from "./protocol.js";
23
23
  import { RunSessionProvider } from "./provider.js";
24
24
  import { readHelpResponse } from "./help-files.js";
25
25
  import { watchParentProcess } from "./parent-watch.js";
26
- import { hostRoot } from "./host-version.js";
26
+ import { hostRoot, readPackageVersion } from "./host-version.js";
27
27
  import { hostWebProblem, isCheckout } from "./host-web.js";
28
28
  import { createStylesheet, STYLESHEET_PATH } from "./web-stylesheet.js";
29
29
  import { isBundleSourceMap, isPublicBundleFile, isWebBundlePath, webBundleFile } from "./web-bundles.js";
@@ -214,6 +214,7 @@ provider.plugins.methods.register("host", [
214
214
  ...coreMethods({
215
215
  sessions: provider,
216
216
  plugins: provider.plugins,
217
+ version: readPackageVersion(),
217
218
  global: globalAccess,
218
219
  runOwner: (runId) => provider.runOwner(runId),
219
220
  runOwnerOnly: (runId) => provider.runOwnerOnly(runId),
@@ -223,6 +224,7 @@ provider.plugins.methods.register("host", [
223
224
  ]);
224
225
  provider.plugins.channels.register("host", coreChannels({
225
226
  sessions: provider,
227
+ plugins: provider.plugins,
226
228
  global: globalAccess,
227
229
  runOwner: (runId) => provider.runOwner(runId),
228
230
  runOwnerOnly: (runId) => provider.runOwnerOnly(runId),
@@ -1 +1 @@
1
- import{r,S as d,E as p,j as E,c as f}from"./mermaid-HWGCJPDP-DfsU5ofC.js";var j=({code:i,language:e,maxHeight:o,raw:a,className:u,startLine:m,lineNumbers:n,...h})=>{let{shikiTheme:l}=r.useContext(d),t=p(),[c,s]=r.useState(a);return r.useEffect(()=>{if(!t){s(a);return}let g=t.highlight({code:i,language:e,themes:l},x=>{s(x)});g&&s(g)},[i,e,l,t,a]),E.jsx(f,{className:u,language:e,lineNumbers:n,maxHeight:o,result:c,startLine:m,...h})};export{j as HighlightedCodeBlockBody};
1
+ import{r,S as d,E as p,j as E,c as f}from"./mermaid-HWGCJPDP-BLLeth5_.js";var j=({code:i,language:e,maxHeight:o,raw:a,className:u,startLine:m,lineNumbers:n,...h})=>{let{shikiTheme:l}=r.useContext(d),t=p(),[c,s]=r.useState(a);return r.useEffect(()=>{if(!t){s(a);return}let g=t.highlight({code:i,language:e,themes:l},x=>{s(x)});g&&s(g)},[i,e,l,t,a]),E.jsx(f,{className:u,language:e,lineNumbers:n,maxHeight:o,result:c,startLine:m,...h})};export{j as HighlightedCodeBlockBody};
@@ -0,0 +1,11 @@
1
+ import{a as oe,r as t,j as e,D as ce,b as de,d as G,B as g,X as Le,M as Pe,C as ue,e as Oe,f as Ie,g as He,h as _e,u as Be,i as Fe,k as Ue,l as qe,m as Ke,A as Te,n as $e,o as We,U as Qe,P as Ve,W as Ge,R as Xe,p as ae,q as V,s as Je,t as Ye,v as Ze,w as et,x as tt,y as st,z as nt,Q as rt,F as at,G as it}from"./mermaid-HWGCJPDP-BLLeth5_.js";/**
2
+ * @license lucide-react v1.46.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const fe={name:"circle-question-mark",size:24,node:[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],aliases:["help-circle","circle-help"]};fe.node;const lt=oe(fe);/**
7
+ * @license lucide-react v1.46.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const he={name:"sparkles",size:24,node:[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],aliases:["stars"]};he.node;const ot=oe(he);function ct(n,r,a,u){if(!r||n.source!==r||n.origin!==a)return;const i=n.data;if(!(!i||typeof i!="object"||Array.isArray(i))&&"type"in i){if(i.type==="ragents:help-ready")return{type:"ready"};if(i.type==="ragents:start-sample"&&"entry"in i&&typeof i.entry=="string"&&u.includes(i.entry))return{type:"start",entry:i.entry}}}function dt({onClose:n,sampleEntries:r,onStartSample:a}){const u=t.useRef(null),i=t.useRef(null),h=t.useRef(void 0),x=t.useRef(!1);t.useEffect(()=>()=>{var l;return(l=h.current)==null?void 0:l.call(h)},[]),t.useEffect(()=>{var j;const l=(j=i.current)==null?void 0:j.contentWindow;if(!l)return;const o=()=>l.postMessage({type:"ragents:help-context",canStartSamples:r.length>0,entries:r},window.location.origin),p=C=>{const c=ct(C,l,window.location.origin,r);(c==null?void 0:c.type)==="ready"&&o(),(c==null?void 0:c.type)==="start"&&!x.current&&(x.current=!0,a(c.entry))};return window.addEventListener("message",p),o(),()=>window.removeEventListener("message",p)},[a,r]);const m=()=>{var C;(C=h.current)==null||C.call(h);const l=i.current,o=l==null?void 0:l.contentDocument,p=o==null?void 0:o.defaultView;if(!l||!o||!p)return;o.documentElement.dataset.helpEmbedded="true";for(const c of o.querySelectorAll("a[href]"))new URL(c.href).origin!==window.location.origin&&(c.target="_blank",c.rel="noopener noreferrer");const j=c=>{var v;if(!c.defaultPrevented){if(c.key==="Escape")c.preventDefault(),n();else if(c.key==="Tab"){const b=[...o.querySelectorAll("a[href], button, input, select, textarea, summary, [tabindex]")].filter(y=>y.tabIndex>=0&&!y.matches(":disabled")&&y.getClientRects().length>0),O=c.shiftKey?b[0]:b.at(-1);if(!b.length||o.activeElement===O||o.activeElement===o.body){if(!c.shiftKey&&o.activeElement===o.body&&b.length)return;c.preventDefault(),(v=u.current)==null||v.focus()}}}};p.addEventListener("keydown",j),h.current=()=>p.removeEventListener("keydown",j)};return e.jsx(ce,{open:!0,onOpenChange:l=>{l||n()},children:e.jsxs(de,{className:"gap-0 p-0",initialFocus:u,scope:"page",showCloseButton:!1,size:"full",children:[e.jsx(G,{className:"sr-only",children:"Hilfe"}),e.jsx(g,{"aria-label":"Hilfe schließen",className:"absolute top-3 right-4.5 z-1 rounded-full",onClick:n,ref:u,size:"icon",variant:"outline",children:e.jsx(Le,{})}),e.jsx("iframe",{className:"min-h-0 w-full min-w-0 flex-[1_1_0] bg-background",onLoad:m,ref:i,src:"/help/index.html",tabIndex:0,title:"RAgents: Homepage und Dokumentation"})]})})}const ut="button:not([disabled]), a[href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex='-1'])",me="pointer-events-auto shadow-pop";function ft({onBusy:n,onClose:r,onOpen:a,open:u,panels:i,registry:h,runs:x}){const m=t.useRef(null);return t.useEffect(()=>{if(!u)return;const l=requestAnimationFrame(()=>{var p;const o=m.current;!o||o.contains(document.activeElement)||(p=o.querySelector(ut))==null||p.focus({preventScroll:!0})});return()=>cancelAnimationFrame(l)},[u]),e.jsxs(Pe,{className:"pointer-events-none flex h-[min(900px,100%)] w-[min(1440px,100%)] flex-col rounded-none bg-transparent p-0 ring-0",keepMounted:!0,onClose:r,open:u,scope:"workspace",size:"full",children:[e.jsx(G,{className:"sr-only",children:"Übersicht"}),e.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1 gap-4 max-[900px]:flex-col",id:"app-overview",ref:m,children:[i.map(({id:l,Panel:o})=>e.jsx(ht,{id:l,onBusy:n,onClose:r,onOpen:a,open:u,Panel:o,registry:h},l)),x&&e.jsx(mt,{...x})]})]})}function ht({id:n,onBusy:r,onClose:a,onOpen:u,open:i,Panel:h,registry:x}){const m=t.useCallback(l=>r(n,l),[n,r]);return t.useEffect(()=>()=>r(n,!1),[n,r]),e.jsx(ue,{className:`${me} min-h-0 min-w-0 flex-1 gap-0 p-0`,children:e.jsx(h,{onBusy:m,onClose:a,onOpen:u,open:i,registry:x})})}function mt({activeId:n,canCreate:r,canDelete:a,onCreate:u,onDelete:i,onOpen:h,registry:x,sessions:m,seenRevisions:l,unreachable:o}){const[p,j]=t.useState(),[C,c]=t.useState(!1),[v,b]=t.useState(()=>new Set),[O,y]=t.useState(!1),[N,_]=t.useState(!1),B=()=>{c(!1),b(new Set)},w=f=>{b(z=>{const I=new Set(z);return I.delete(f)||I.add(f),I})},E=async f=>{_(!0),j(void 0);try{await i(f)}catch(z){j(z instanceof Error?z.message:String(z))}finally{_(!1)}},k=async()=>{await E(m.filter(f=>v.has(f.id)).map(f=>f.id)),y(!1),B()};return e.jsx("section",{"aria-labelledby":"overview-runs-title",className:"flex min-h-0 min-w-0 flex-1 flex-col max-[900px]:flex-[1_1_50%]",children:e.jsxs(ue,{className:`${me} min-h-0 flex-1 gap-workspace-inset overflow-y-auto overscroll-contain pt-workspace-inset pr-6 pb-6 pl-6 max-[900px]:px-3 max-[900px]:pt-3.5 max-[900px]:pb-4`,children:[e.jsxs("header",{className:"flex flex-wrap items-center gap-x-3.5 gap-y-2.5",children:[e.jsxs("h2",{className:"text-[0.95rem] font-semibold",id:"overview-runs-title",children:["Runs ",e.jsx("span",{className:"ml-1 text-[0.8rem] font-medium tabular-nums text-muted-foreground",children:m.length})]}),o&&e.jsx("span",{className:"text-[0.72rem] font-medium text-destructive",role:"alert",children:"Server nicht erreichbar"}),a&&m.length>0&&e.jsx("div",{className:"ml-auto flex flex-wrap items-center gap-1",children:C?e.jsxs(e.Fragment,{children:[e.jsx(g,{onClick:()=>b(new Set(m.map(f=>f.id))),size:"sm",variant:"ghost",children:"Alle"}),e.jsx(g,{onClick:()=>b(new Set),size:"sm",variant:"ghost",children:"Keine"}),e.jsxs(g,{className:"ml-auto",disabled:v.size===0||N,onClick:()=>y(!0),size:"sm",variant:"destructive",children:["Löschen (",v.size,")"]}),e.jsx(g,{onClick:B,size:"sm",variant:"ghost",children:"Fertig"})]}):e.jsx(g,{onClick:()=>c(!0),size:"sm",variant:"ghost",children:"Auswählen"})})]}),p&&e.jsx("p",{className:"text-[0.72rem] font-medium text-destructive",role:"alert",children:p}),e.jsx("p",{className:"mb-5.5 text-[0.75rem] text-muted-foreground",children:"Nach letzter Aktivität im Run. Neue Aktivität ist seit Deinem letzten Ansehen hinzugekommen."}),e.jsx(Oe,{seenRevisions:l,activeId:n,onCreate:r?u:void 0,onDelete:a?f=>void E([f]):void 0,onSelect:h,onToggleSelected:w,registry:x,selectMode:C,selectedIds:v,sessions:m}),O&&e.jsx(ce,{open:!0,onOpenChange:f=>{!f&&!N&&y(!1)},children:e.jsxs(de,{scope:"page",showCloseButton:!1,size:"small",children:[e.jsxs(Ie,{children:[e.jsx(G,{children:"Runs löschen"}),e.jsx(He,{children:v.size===1?"Ein Run wird endgültig gelöscht.":`${v.size} Runs werden endgültig gelöscht.`})]}),e.jsxs(_e,{children:[e.jsx(g,{disabled:N,onClick:()=>y(!1),variant:"outline",children:"Abbrechen"}),e.jsx(g,{disabled:N,onClick:()=>void k(),children:N?"Löscht ...":`Löschen (${v.size})`})]})]})})]})})}const ie="flex min-h-0 min-w-0 flex-1 flex-col",xt="inline-flex w-header min-h-header items-center justify-center border-r border-border text-primary transition-colors duration-100 not-disabled:cursor-pointer hover:not-disabled:bg-accent focus-visible:outline-2 focus-visible:outline-ring/60 focus-visible:-outline-offset-3 aria-expanded:bg-primary aria-expanded:text-primary-foreground aria-pressed:bg-primary aria-pressed:text-primary-foreground disabled:opacity-45";function pt(){var re;const n=Be(),r=Fe((re=n.user)==null?void 0:re.id),a=n.can("runs.read"),u=a&&n.can("runs.write"),i=n.can("runs.inspect"),h=a&&n.can("runs.delete"),x=Ue(),m=t.useRef(null),l=t.useRef(null),[o,p]=t.useState(null),[j,C]=t.useState(null),[c,v]=t.useState(null),[b,O]=t.useState(null),[y,N]=t.useState(null),[_,B]=t.useState([]),[w,E]=t.useState(),[k,f]=t.useState(),[z,I]=t.useState(),[U,X]=t.useState(!1),[q,K]=t.useState(!1),[D,J]=t.useState(!1),[Y,A]=t.useState(),[pe,ve]=t.useState(!1),[ge,be]=t.useState(()=>new Set),[we,Z]=t.useState(!1),H=t.useRef(void 0),T=t.useRef(!1),L=t.useCallback(()=>{if(!a)return Promise.resolve();if(H.current)return T.current=!0,H.current;const s=async()=>{do{T.current=!1;try{B(await Ye()),Z(!1)}catch{Z(!0)}}while(T.current)};return H.current=s().finally(()=>{H.current=void 0}),H.current},[a]);t.useEffect(()=>{if(!a||w)return;L();const s=qe.subscribe(Ke.channels.runs,{},()=>void L()),d=setInterval(()=>void L(),5e3);return()=>{s(),clearInterval(d)}},[w,a,L]);const M=t.useCallback((s=!1)=>{var d;J(!1),s&&((d=m.current)==null||d.focus({preventScroll:!0}))},[]),$=t.useCallback(()=>{A(void 0),ve(!0),J(!0)},[]),W=t.useCallback(()=>{D?M(!0):$()},[M,$,D]);t.useEffect(()=>{const s=d=>{if(d.defaultPrevented||d.repeat||d.altKey||d.shiftKey||d.key.toLowerCase()!=="i"||d.metaKey===d.ctrlKey)return;const R=m.current;!R||R.closest("[inert]")||(d.preventDefault(),W())};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[W]);const ee=t.useCallback((s,d)=>be(R=>{if(R.has(s)===d)return R;const P=new Set(R);return d?P.add(s):P.delete(s),P}),[]),te=_,je=te.find(s=>s.id===k),ye=t.useCallback(()=>{A(void 0),X(!0)},[]),ke=t.useCallback(()=>K(!1),[]),Se=t.useCallback(()=>{X(!1),requestAnimationFrame(()=>{var s;return(s=l.current)==null?void 0:s.focus()})},[]),Ce=e.jsx(g,{"aria-label":"Einstellungen öffnen",onClick:ye,ref:l,size:"icon-lg",title:"Einstellungen",variant:"ghost",children:e.jsx(Ze,{})}),Re=s=>{f(s),M(!0)},Ne=()=>{A(void 0),M(!0),E({id:crypto.randomUUID(),title:"Neuer Run",updatedAt:Date.now()})},Ee=async s=>{const d=await Promise.allSettled(s.map(F=>et(F))),R=s.filter((F,Me)=>d[Me].status==="fulfilled");k!==void 0&&R.includes(k)&&f(void 0),await L();const P=d.find(F=>F.status==="rejected");if(P)throw P.reason};if(x.status==="loading")return e.jsx("div",{className:"m-auto p-6 text-muted-foreground",children:"Profil wird geladen."});if(x.status==="failed")return e.jsx("div",{className:"flex h-full",children:e.jsx("main",{className:"relative z-1 flex min-h-0 min-w-0 flex-1 bg-[image:var(--surface-backdrop)]",children:e.jsxs("div",{className:ie,children:[e.jsx("header",{className:"flex min-h-[42px] flex-none items-center gap-3 border-b border-border-soft pr-0.5 pb-2 pl-2.5",children:e.jsx("div",{className:"flex min-w-0 flex-1 items-center gap-3 text-[0.82rem] font-semibold text-foreground",children:"Profil nicht verfügbar"})}),e.jsxs(Te,{className:"m-auto max-w-[560px] gap-3 p-6",variant:"destructive",children:[e.jsx("p",{children:x.error}),e.jsx(g,{variant:"outline",onClick:()=>window.location.reload(),children:"Neu laden"})]})]})})});const S=x.registry,se=S.overviewPanels.filter(s=>s.readRight===void 0||n.can(s.readRight)),Q=se.filter(s=>s.placement!=="toolbar"),ze=se.filter(s=>s.placement==="toolbar"),De=a||Q.length>0,ne=Q.some(s=>ge.has(s.id)),Ae=$e(a?k:void 0,D,z);return e.jsxs("div",{className:"flex h-full flex-col",children:[e.jsxs("header",{className:"relative z-[80] flex h-header flex-none items-stretch border-b border-border bg-shell shadow-bar",children:[De&&e.jsx("div",{className:"relative flex flex-none self-stretch",children:e.jsx("button",{"aria-controls":"app-overview","aria-expanded":D,"aria-haspopup":"dialog","aria-keyshortcuts":"Meta+I Control+I","aria-label":D?"Übersicht schließen":"Übersicht öffnen",className:xt,onClick:W,ref:m,title:`Übersicht (Cmd+I / Ctrl+I)${ne?": Bearbeitung läuft":""}`,type:"button",children:ne?e.jsx(We,{"aria-hidden":!0,className:"size-[18px]"}):e.jsx(ot,{size:22})})}),ze.map(({id:s,Panel:d})=>e.jsx(vt,{id:s,onBusy:ee,onClose:()=>A(void 0),onOpen:()=>{!U&&!q&&!w&&(M(),A(s))},open:Y===s,Panel:d,registry:S,userLocation:Ae},s)),e.jsx("div",{"aria-label":"Run-Titelleiste",className:"flex min-w-0 flex-1 items-stretch overflow-x-auto no-scrollbar focus-visible:outline-2 focus-visible:outline-ring/60 focus-visible:-outline-offset-3 max-md:in-[header:has([data-slot=overseer-toolbar][data-open=true])]:flex-[0_1_0]",ref:p,role:"region",tabIndex:0}),e.jsx(Qe,{}),e.jsxs("div",{className:"flex min-w-0 flex-[0_1_auto] items-stretch bg-shell has-data-[workspace-state=expanded]:w-[var(--workspace-panel-width,560px)] has-data-[workspace-state=expanded]:border-l has-data-[workspace-state=expanded]:border-border",children:[e.jsx("div",{className:"flex min-w-0 flex-1 empty:hidden",ref:C}),e.jsxs("div",{className:"flex flex-none items-center gap-1.5 px-2 max-md:gap-0.5 max-md:px-1",children:[n.can("settings.read")&&Ce,i&&e.jsx(g,{"aria-haspopup":"dialog","aria-label":"Hilfe öffnen",onClick:()=>{A(void 0),K(!0)},size:"icon-lg",title:"Hilfe",variant:"ghost",children:e.jsx(lt,{})})]})]})]}),e.jsx(Ve,{failures:x.failures}),e.jsx(Ge.Provider,{value:b,children:e.jsx("div",{className:"relative flex min-h-0 flex-1 flex-col",ref:O,children:e.jsxs(Xe.Provider,{value:y,children:[e.jsxs("div",{className:"relative flex h-auto min-h-0 flex-1",ref:N,children:[e.jsx("main",{className:"relative z-1 flex min-h-0 min-w-0 flex-1 bg-[image:var(--surface-backdrop)] @container/chat-content",children:a&&k?e.jsx(ae,{headerContainer:o,workspaceHeaderContainer:j,statusContainer:c,onLocationChange:I,onViewed:r.markViewed,viewing:!D&&!U&&!q&&!w&&!Y,registry:S,session:je??{id:k,title:"Neuer Run",updatedAt:Date.now()}},k):e.jsx("div",{className:ie,children:e.jsx("div",{className:"m-auto text-center text-muted-foreground",children:a?u?"Öffne oben links die Übersicht, um einen Run zu wählen oder einen neuen zu starten.":"Öffne oben links die Übersicht, um einen Run zu wählen. Du hast Lesezugriff.":"Für dieses Benutzerkonto sind keine Runs freigegeben."})})}),pe&&e.jsx(ft,{onOpen:$,onBusy:ee,onClose:()=>M(!0),open:D,panels:Q,registry:S,runs:a?{activeId:k,canCreate:u&&(n.can("runs.create")||S.scriptEntries.some(s=>V(n,s.id))),canDelete:h,onCreate:Ne,onDelete:Ee,onOpen:Re,registry:S,sessions:te,seenRevisions:r.revisions,unreachable:we}:void 0}),w&&e.jsx(ae,{onStarted:()=>{f(w.id),E(void 0),L()},registry:S,session:w,startDialog:{onClose:()=>E(void 0),initialEntryId:w.startEntryId}},w.id),U&&e.jsx(Je,{onClose:Se,registry:S}),i&&q&&e.jsx(dt,{onClose:ke,sampleEntries:S.scriptEntries.filter(s=>V(n,s.id)).map(s=>s.id),onStartSample:s=>{!V(n,s)||!S.scriptEntries.some(d=>d.id===s)||(K(!1),A(void 0),M(),E({id:crypto.randomUUID(),title:"Neuer Run",updatedAt:Date.now(),startEntryId:s}))}})]}),e.jsx("footer",{"aria-label":"Run-Statusleiste",className:"relative flex h-statusbar w-full flex-none items-stretch pl-3 before:pointer-events-none before:absolute before:inset-0 before:z-[2] before:border-t before:border-border before:bg-shell before:shadow-status before:backdrop-blur-[16px] before:content-['']",ref:v})]})})})]})}function vt({id:n,onBusy:r,Panel:a,...u}){const i=t.useCallback(h=>r(n,h),[n,r]);return t.useEffect(()=>()=>r(n,!1),[n,r]),e.jsx(a,{...u,onBusy:i})}tt();const xe=document.getElementById("root");if(!xe)throw new Error("Root-Element fehlt");const le=st.createRoot(xe);try{const n=nt(window);le.render(e.jsx(t.StrictMode,{children:e.jsx(rt,{children:e.jsx(at,{children:e.jsx(pt,{})})})}))}catch(n){le.render(e.jsxs(it,{children:[e.jsx("h1",{className:"my-3 text-[1.5rem]",children:"Darstellung konnte nicht geladen werden"}),e.jsx("p",{className:"mb-6 leading-normal",role:"alert",children:n instanceof Error?n.message:String(n)}),e.jsx(g,{onClick:()=>window.location.reload(),variant:"outline",children:"Erneut laden"})]}))}