@schlenkr/ragents 0.1.13 → 0.1.15
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/package.json +1 -1
- package/apps/server/src/api/contracts.ts +19 -1
- package/apps/server/src/api/core-methods.ts +12 -0
- package/apps/server/src/chat-handler.ts +19 -0
- package/apps/server/src/host-api.json +2 -0
- package/apps/server/src/host-api.ts +2 -2
- package/apps/server/src/plugin-build/build.ts +1 -1
- package/apps/server/src/plugin-support/actor-programs/app-project.ts +61 -17
- package/apps/server/src/plugin-support/actor-programs/contract.ts +18 -1
- package/apps/server/src/plugin-support/actor-programs/service.ts +22 -1
- package/apps/server/src/plugin-support/plugin-folder.ts +14 -1
- package/apps/server/src/plugin-support/run-scripts.ts +27 -2
- package/apps/server/src/profile/compose.ts +2 -0
- package/apps/server/src/provider.ts +31 -6
- package/apps/server/src/ragents/chat-projection.ts +7 -0
- package/apps/server/src/ragents/global-chat.ts +5 -1
- package/apps/server/src/ragents/run-script-tools.ts +66 -0
- package/apps/server/src/ragents/session.ts +122 -60
- package/apps/server/src/title-compactor.ts +1 -1
- package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-CpPi6QLr.js → highlighted-body-KPVGNVTW-BwD4uYEe.js} +1 -1
- package/apps/web/dist/assets/main-KBrc5Q77.js +11 -0
- package/apps/web/dist/assets/{mermaid-HWGCJPDP-q-mf1kLN.js → mermaid-HWGCJPDP-CSCkaArr.js} +88 -88
- package/apps/web/dist/assets/runPanel-BjG5NBKm.js +26 -0
- package/apps/web/dist/help/guide-clients.html +21 -4
- package/apps/web/dist/help/guide-clients.md +23 -4
- package/apps/web/dist/help/guide-plugins.html +12 -2
- package/apps/web/dist/help/guide-plugins.md +9 -2
- package/apps/web/dist/help/guide-programs.html +8 -2
- package/apps/web/dist/help/guide-programs.md +9 -2
- package/apps/web/dist/help/guide-runtime.html +3 -2
- package/apps/web/dist/help/guide-runtime.md +3 -2
- package/apps/web/dist/help/index.html +1 -1
- package/apps/web/dist/help/mini-app.css +16 -2
- package/apps/web/dist/host-web.json +13 -13
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/run-panel.html +2 -2
- package/apps/web/package.json +1 -1
- package/apps/web/src/App.tsx +12 -1
- package/apps/web/src/PluginRegistry.tsx +2 -2
- package/apps/web/src/SessionList.tsx +7 -6
- package/apps/web/src/SettingsModal.tsx +3 -3
- package/apps/web/src/actor-programs/client-ui/FilePicker.tsx +1 -1
- package/apps/web/src/api.ts +2 -0
- package/apps/web/src/run-overview.ts +1 -1
- package/apps/web/src/run-panel/RunPanelApp.tsx +1 -1
- package/apps/web/src/run-panel/RunPanelMenu.tsx +47 -11
- package/apps/web/src/ui/relative-time.ts +1 -1
- package/bundles/ragents.activity/ragents-bundle.json +1 -1
- package/bundles/ragents.actor-programs/ragents-bundle.json +4 -2
- package/bundles/ragents.actor-programs/server/index.js +437 -24
- package/bundles/ragents.actor-programs/server/index.js.map +4 -4
- package/bundles/ragents.actor-programs/web/index.js.map +1 -1
- package/bundles/ragents.ask/ragents-bundle.json +2 -2
- package/bundles/ragents.ask/server/index.js +1 -0
- package/bundles/ragents.ask/server/index.js.map +2 -2
- package/bundles/ragents.browser/ragents-bundle.json +1 -1
- package/bundles/ragents.documents/ragents-bundle.json +2 -2
- package/bundles/ragents.documents/web/classes.json +1 -1
- package/bundles/ragents.documents/web/index.js +1 -1
- package/bundles/ragents.documents/web/index.js.map +2 -2
- package/bundles/ragents.lsp-fsharp/ragents-bundle.json +1 -1
- package/bundles/ragents.lsp-roslyn/ragents-bundle.json +1 -1
- package/bundles/ragents.lsp-typescript/ragents-bundle.json +1 -1
- package/bundles/ragents.model-relay/ragents-bundle.json +1 -1
- package/bundles/ragents.orchestration/ragents-bundle.json +7 -4
- package/bundles/ragents.orchestration/server/chunks/chunk-QS3WJ3D7.js +11 -0
- package/bundles/ragents.orchestration/server/chunks/chunk-QS3WJ3D7.js.map +7 -0
- package/bundles/ragents.orchestration/server/exports/server/contract.js +9 -0
- package/bundles/ragents.orchestration/server/exports/server/contract.js.map +7 -0
- package/bundles/ragents.orchestration/server/index.js +49 -3
- package/bundles/ragents.orchestration/server/index.js.map +2 -2
- package/bundles/ragents.orchestration/surface.hbs +5 -0
- package/bundles/ragents.orchestration/web/index.js +3 -3
- package/bundles/ragents.orchestration/web/index.js.map +2 -2
- package/bundles/ragents.overseer/ragents-bundle.json +4 -3
- package/bundles/ragents.overseer/web/classes.json +1 -1
- package/bundles/ragents.overseer/web/index.js +1 -1
- package/bundles/ragents.overseer/web/index.js.map +4 -4
- package/bundles/ragents.processes/ragents-bundle.json +2 -2
- package/bundles/ragents.processes/web/classes.json +1 -1
- package/bundles/ragents.processes/web/index.js +1 -1
- package/bundles/ragents.processes/web/index.js.map +2 -2
- package/bundles/ragents.product/ragents-bundle.json +1 -1
- package/bundles/ragents.profile-distribution/ragents-bundle.json +1 -1
- package/bundles/ragents.reference/actors/notebook/package.json +16 -0
- package/bundles/ragents.reference/actors/notebook/src/client.tsx +31 -0
- package/bundles/ragents.reference/actors/notebook/src/server.ts +27 -0
- package/bundles/ragents.reference/actors/notebook/tests/program.test.ts +27 -0
- package/bundles/ragents.reference/ragents-bundle.json +4 -3
- package/bundles/ragents.reference/run-scripts/quick-note/RUN.md +14 -0
- package/bundles/ragents.reference/run-scripts/quick-note/package.json +9 -0
- package/bundles/ragents.reference/run-scripts/quick-note/src/server.ts +29 -0
- package/bundles/ragents.reference/run-scripts/quick-note/tests/program.test.ts +43 -0
- package/bundles/ragents.reference/run-scripts/run-roster/RUN.md +19 -0
- package/bundles/ragents.reference/run-scripts/run-roster/package.json +9 -0
- package/bundles/ragents.reference/run-scripts/run-roster/src/server.ts +26 -0
- package/bundles/ragents.reference/run-scripts/run-roster/tests/program.test.ts +47 -0
- package/bundles/ragents.todo/ragents-bundle.json +1 -1
- package/bundles/ragents.transcript/ragents-bundle.json +1 -1
- package/bundles/ragents.watch/ragents-bundle.json +1 -1
- package/bundles/ragents.workspace/ragents-bundle.json +2 -2
- 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 +2 -2
- package/package.json +3 -3
- package/packages/ragents/src/domain/vocabulary.ts +4 -0
- package/packages/ragents/src/index.ts +3 -1
- package/packages/ragents/src/plugin-host.ts +62 -10
- package/packages/ragents/src/plugin-types.ts +11 -0
- package/packages/ragents/src/runtime/guards.ts +2 -1
- package/packages/ragents/src/typescript/async-compiler.ts +11 -1
- package/plugins/ragents.actor-programs/server/index.ts +3 -0
- package/plugins/ragents.actor-programs/server/runtime.ts +424 -28
- package/plugins/ragents.actor-programs/server/script-state.ts +54 -0
- package/plugins/ragents.actor-programs/server/tool-contributor.ts +2 -0
- package/plugins/ragents.ask/server/ask-tool.ts +1 -0
- package/plugins/ragents.documents/web/DocumentViewer.tsx +2 -2
- package/plugins/ragents.orchestration/ragents-plugin.json +1 -0
- package/plugins/ragents.orchestration/server/contract.ts +14 -0
- package/plugins/ragents.orchestration/server/index.ts +4 -1
- package/plugins/ragents.orchestration/server/surface-tool.ts +58 -2
- package/plugins/ragents.orchestration/surface.hbs +5 -0
- package/plugins/ragents.orchestration/web/ExecutionsPanel.tsx +1 -1
- package/plugins/ragents.orchestration/web/FlowInspector.tsx +1 -1
- package/plugins/ragents.orchestration/web/JournalStatus.tsx +1 -1
- package/plugins/ragents.orchestration/web/format.ts +1 -1
- package/plugins/ragents.overseer/web/index.tsx +51 -3
- package/plugins/ragents.processes/web/processes.ts +1 -1
- package/plugins/ragents.reference/actors/notebook/package.json +16 -0
- package/plugins/ragents.reference/actors/notebook/src/client.tsx +31 -0
- package/plugins/ragents.reference/actors/notebook/src/server.ts +27 -0
- package/plugins/ragents.reference/actors/notebook/tests/program.test.ts +27 -0
- package/plugins/ragents.reference/run-scripts/quick-note/RUN.md +14 -0
- package/plugins/ragents.reference/run-scripts/quick-note/package.json +9 -0
- package/plugins/ragents.reference/run-scripts/quick-note/src/server.ts +29 -0
- package/plugins/ragents.reference/run-scripts/quick-note/tests/program.test.ts +43 -0
- package/plugins/ragents.reference/run-scripts/run-roster/RUN.md +19 -0
- package/plugins/ragents.reference/run-scripts/run-roster/package.json +9 -0
- package/plugins/ragents.reference/run-scripts/run-roster/src/server.ts +26 -0
- package/plugins/ragents.reference/run-scripts/run-roster/tests/program.test.ts +47 -0
- package/plugins/ragents.workspace/web/FileBrowser.tsx +1 -1
- package/scripts/agent/agent-cli.ts +46 -2
- package/scripts/package/ragents.mjs +3 -1
- package/apps/web/dist/assets/main-DJmCHGzM.js +0 -11
- package/apps/web/dist/assets/runPanel-nk_aMxSn.js +0 -21
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { defineRunFunction, defineToolAvailability, holdsUsable, type JsonValue, type PluginHost, type ToolContributor } from "@ragents/engine";
|
|
3
|
+
import { toolDescriptorFrom } from "../plugin-support/agent-tool.js";
|
|
4
|
+
import { runManagementToken, type RunManagement } from "./global-chat.js";
|
|
5
|
+
|
|
6
|
+
const available = defineToolAvailability({
|
|
7
|
+
availability: "conditional",
|
|
8
|
+
availabilityDetail: "Only with the capability script.start, which the coordinator holds and passes to no agent it spawns.",
|
|
9
|
+
requiredCapabilities: ["script.start"],
|
|
10
|
+
}, (actor) => actor.kind !== "human" && holdsUsable(actor, "script.start"));
|
|
11
|
+
|
|
12
|
+
const listMetadata = {
|
|
13
|
+
name: "run_script_list",
|
|
14
|
+
label: "List run scripts",
|
|
15
|
+
description: "The run scripts of this profile that can join this run: entry, title, description, and whether each can start now or why not.",
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
const startMetadata = {
|
|
19
|
+
name: "run_script_start",
|
|
20
|
+
label: "Start run script",
|
|
21
|
+
description: "Start a run script from run_script_list inside this run; returns its actor handle and which start of it this is.",
|
|
22
|
+
longDescription: "entry is the entry from run_script_list; input is the script's start value, if it takes one. The script joins the run "
|
|
23
|
+
+ "without changing the primary actor; a repeated start reuses its actor. When it finishes a start, you receive its summary and result "
|
|
24
|
+
+ "as a message; do not wait or poll for it in the same turn.",
|
|
25
|
+
} as const;
|
|
26
|
+
|
|
27
|
+
const listing = Type.Array(Type.Object({
|
|
28
|
+
entry: Type.String(),
|
|
29
|
+
title: Type.String(),
|
|
30
|
+
description: Type.String(),
|
|
31
|
+
available: Type.Boolean(),
|
|
32
|
+
reason: Type.Optional(Type.String()),
|
|
33
|
+
}, { additionalProperties: false }));
|
|
34
|
+
|
|
35
|
+
export const createRunScriptToolContributor = (management: () => RunManagement): ToolContributor => {
|
|
36
|
+
const list = defineRunFunction({
|
|
37
|
+
...listMetadata,
|
|
38
|
+
schema: Type.Object({}, { additionalProperties: false }),
|
|
39
|
+
resultSchema: listing,
|
|
40
|
+
available,
|
|
41
|
+
run: ({ caller }) => management().scripts(caller.runId).map(({ id, ...script }) => ({ entry: id, ...script })),
|
|
42
|
+
});
|
|
43
|
+
const start = defineRunFunction({
|
|
44
|
+
...startMetadata,
|
|
45
|
+
schema: Type.Object({
|
|
46
|
+
entry: Type.String({ minLength: 1, description: "The entry from run_script_list" }),
|
|
47
|
+
input: Type.Optional(Type.Unknown({ description: "Start value of the script; omit it for none" })),
|
|
48
|
+
}, { additionalProperties: false }),
|
|
49
|
+
resultSchema: Type.Object({ handle: Type.String(), count: Type.Integer({ minimum: 1 }) }, { additionalProperties: false }),
|
|
50
|
+
available,
|
|
51
|
+
run: async ({ caller }, _toolCallId, input) => {
|
|
52
|
+
const started = await management().startScript(caller.runId, input.entry, (input.input ?? null) as JsonValue | null, caller.actorId);
|
|
53
|
+
return { handle: started.handle, count: started.count };
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
name: "ragents.run-scripts",
|
|
58
|
+
descriptors: [toolDescriptorFrom(listMetadata, available), toolDescriptorFrom(startMetadata, available)],
|
|
59
|
+
tools: () => [list, start],
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** The profile registers them once while composing; they act on the caller's own run. */
|
|
64
|
+
export const registerRunScriptFunctions = (host: PluginHost): void => {
|
|
65
|
+
host.tools.register("ragents.runtime", [createRunScriptToolContributor(() => host.service(runManagementToken)())]);
|
|
66
|
+
};
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
2
|
import { isDeepStrictEqual } from "node:util";
|
|
5
3
|
import { parseChatAttachments, type ChatAttachment, type ChatAttachmentInput, type ChatEvent, type ChatStartupStatus } from "quassel/events";
|
|
6
4
|
import { attachmentContentPath } from "../api/contracts.js";
|
|
7
|
-
import type { ChatSessionLike, ChatUser } from "../chat-handler.js";
|
|
5
|
+
import type { ChatSessionLike, ChatUser, RunScriptListing, StartedScript } from "../chat-handler.js";
|
|
8
6
|
import {
|
|
9
7
|
assertJsonValue,
|
|
10
8
|
attachmentInputKind,
|
|
11
9
|
capabilityNames,
|
|
12
10
|
DomainError,
|
|
11
|
+
firstHandCapabilities,
|
|
13
12
|
isThinkingLevel,
|
|
14
13
|
PluginStateProjection,
|
|
15
14
|
resolveExecution,
|
|
@@ -25,7 +24,7 @@ import {
|
|
|
25
24
|
type AgentExecution,
|
|
26
25
|
type ModelSelection,
|
|
27
26
|
} from "@ragents/engine";
|
|
28
|
-
import type { ActorProgramsService } from "../plugin-support/actor-programs/service.js";
|
|
27
|
+
import type { ActivatedActorProgram, ActorProgramsService } from "../plugin-support/actor-programs/service.js";
|
|
29
28
|
import { modelLabel } from "../plugin-support/model-aliases.js";
|
|
30
29
|
import type { StartOptionState } from "../plugin-support/start-options-contract.js";
|
|
31
30
|
import type { Engine } from "./engine.js";
|
|
@@ -59,7 +58,7 @@ const coordinatorGrants = (): CapabilityGrant[] =>
|
|
|
59
58
|
capabilityNames.map((capability) => ({
|
|
60
59
|
capability,
|
|
61
60
|
scope: { kind: "run" as const },
|
|
62
|
-
delegable:
|
|
61
|
+
delegable: !firstHandCapabilities.includes(capability),
|
|
63
62
|
}));
|
|
64
63
|
|
|
65
64
|
const primaryActorOf = (view: RunView) => view.primaryActorId
|
|
@@ -70,6 +69,9 @@ const messageOf = (error: unknown): string => error instanceof Error ? error.mes
|
|
|
70
69
|
|
|
71
70
|
const userIdOf = (user: ChatUser | undefined): string | null => user?.id ?? null;
|
|
72
71
|
|
|
72
|
+
const startValueOf = (input: unknown): JsonValue | null =>
|
|
73
|
+
input === undefined || input === null ? null : (assertJsonValue(input, "Start value of the run script"), input);
|
|
74
|
+
|
|
73
75
|
/** Who starts a run, through which template, and which start options it fixes. */
|
|
74
76
|
interface StartChoice {
|
|
75
77
|
readonly userId: string | null;
|
|
@@ -83,6 +85,8 @@ const freeChoice = (userId: string | null): StartChoice => ({ userId, entry: nul
|
|
|
83
85
|
/** A script template together with the package the host installs when it is clicked. */
|
|
84
86
|
export type RunScriptStart = RunScriptPackage & { entry: PublicStartEntry };
|
|
85
87
|
|
|
88
|
+
export type RunScriptPrograms = Pick<ActorProgramsService, "installScript" | "enqueueStart" | "isScriptActor">;
|
|
89
|
+
|
|
86
90
|
export interface RunChatSessionOptions {
|
|
87
91
|
engine: Engine;
|
|
88
92
|
id: string;
|
|
@@ -99,7 +103,7 @@ export interface RunChatSessionOptions {
|
|
|
99
103
|
started: (id: string, startEntry: SessionStartedContext["startEntry"]) => Promise<void>;
|
|
100
104
|
scriptEntryFor: (entryId: string) => RunScriptStart | undefined;
|
|
101
105
|
startEntryFor: (entryId: string) => PublicStartEntry | undefined;
|
|
102
|
-
actorPrograms:
|
|
106
|
+
actorPrograms: RunScriptPrograms;
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
export class RunChatSession implements ChatSessionLike {
|
|
@@ -117,7 +121,7 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
117
121
|
readonly #started: (id: string, startEntry: SessionStartedContext["startEntry"]) => Promise<void>;
|
|
118
122
|
readonly #scriptEntryFor: (entryId: string) => RunScriptStart | undefined;
|
|
119
123
|
readonly #startEntryFor: (entryId: string) => PublicStartEntry | undefined;
|
|
120
|
-
readonly #actorPrograms:
|
|
124
|
+
readonly #actorPrograms: RunScriptPrograms;
|
|
121
125
|
readonly #events: ChatEvent[] = [];
|
|
122
126
|
readonly #listeners = new Set<(event: ChatEvent) => void>();
|
|
123
127
|
readonly #liveTurns = new Map<string, LiveTurn>();
|
|
@@ -127,6 +131,8 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
127
131
|
#primaryActorId: string | undefined;
|
|
128
132
|
#activeLiveTurnId: string | undefined;
|
|
129
133
|
#starting: Promise<void> | undefined;
|
|
134
|
+
#scriptQueue: Promise<unknown> = Promise.resolve();
|
|
135
|
+
readonly #scriptStarts = new Set<AbortController>();
|
|
130
136
|
#startup: ChatStartupStatus | undefined;
|
|
131
137
|
#startCancellation: AbortController | undefined;
|
|
132
138
|
#unsubscribeJournal: (() => void) | undefined;
|
|
@@ -232,7 +238,7 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
232
238
|
const chosen = this.startLocked ? storedStartOption(state, optionId) : this.#startValues.get(optionId);
|
|
233
239
|
if (chosen !== undefined && !isDeepStrictEqual(chosen, accepted)) {
|
|
234
240
|
throw new DomainError("start-option-fixed", this.startLocked
|
|
235
|
-
? `The template "${entry.title}" fixes the start option ${optionId}, but this run already has a different value there.`
|
|
241
|
+
? `The template "${entry.title}" fixes the start option ${optionId} to ${JSON.stringify(accepted)}, but this run already has a different value there: ${JSON.stringify(chosen)}.`
|
|
236
242
|
: `The template "${entry.title}" fixes the start option ${optionId}, but a different value is chosen. Undo the choice or start without this template.`, 409);
|
|
237
243
|
}
|
|
238
244
|
return [optionId, accepted] as const;
|
|
@@ -319,24 +325,47 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
319
325
|
return { attachment: this.#attachmentInfo(artifact), content };
|
|
320
326
|
}
|
|
321
327
|
|
|
322
|
-
/** Starts
|
|
328
|
+
/** Starts a run script: in a new run its first turn builds the run, in a running run only an embeddable one joins it. */
|
|
323
329
|
start(entryId: string, input: unknown, user?: ChatUser): void {
|
|
324
|
-
this.#track(() => this.#start(entryId, input, user));
|
|
330
|
+
void this.#track(() => this.#start(entryId, input, user));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** startedBy is the actor that receives the script's result; without it, the owner. */
|
|
334
|
+
async startAndWait(entryId: string, input: unknown, user?: ChatUser, startedBy?: string): Promise<StartedScript> {
|
|
335
|
+
return this.#track(() => this.#start(entryId, input, user, startedBy));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** The script templates among these entries, and whether each can start in this run now. */
|
|
339
|
+
runScripts(entries: readonly PublicStartEntry[], userId: string | null): RunScriptListing[] {
|
|
340
|
+
const started = this.#runStarted();
|
|
341
|
+
return entries.flatMap((entry) => {
|
|
342
|
+
const found = this.#scriptEntryFor(entry.id);
|
|
343
|
+
if (!found) return [];
|
|
344
|
+
const reason = !started ? undefined
|
|
345
|
+
: !found.embeddable ? "It starts only a new run; its RUN.md does not set embeddable: true."
|
|
346
|
+
: this.#optionConflict(found.entry, userId);
|
|
347
|
+
return [{ id: entry.id, title: entry.title, description: entry.description, available: reason === undefined, ...(reason ? { reason } : {}) }];
|
|
348
|
+
});
|
|
325
349
|
}
|
|
326
350
|
|
|
327
|
-
|
|
328
|
-
|
|
351
|
+
#optionConflict(entry: PublicStartEntry, userId: string | null): string | undefined {
|
|
352
|
+
try {
|
|
353
|
+
this.#startChoice(entry, userId);
|
|
354
|
+
return undefined;
|
|
355
|
+
} catch (error) {
|
|
356
|
+
return messageOf(error);
|
|
357
|
+
}
|
|
329
358
|
}
|
|
330
359
|
|
|
331
|
-
async startPackageAndWait(script: RunScriptStart, input: unknown, user?: ChatUser): Promise<
|
|
332
|
-
|
|
360
|
+
async startPackageAndWait(script: RunScriptStart, input: unknown, user?: ChatUser): Promise<StartedScript> {
|
|
361
|
+
return this.#track(() => this.#startPackage(() => script, input, user));
|
|
333
362
|
}
|
|
334
363
|
|
|
335
|
-
#track(work: () => Promise<
|
|
364
|
+
#track<T>(work: () => Promise<T>, reportError = true): Promise<T> {
|
|
336
365
|
if (this.#disposed) throw new Error("The run was deleted");
|
|
337
366
|
this.#assertUsable(this.id);
|
|
338
367
|
const operation = work();
|
|
339
|
-
const tracked = operation.
|
|
368
|
+
const tracked = operation.then(() => undefined, (error: unknown) => {
|
|
340
369
|
if (reportError && !this.#disposed) this.#emit({ kind: "system", text: `Error: ${messageOf(error)}` });
|
|
341
370
|
});
|
|
342
371
|
this.#pendingSends.add(tracked);
|
|
@@ -356,8 +385,9 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
356
385
|
if (this.#startCancellation && !this.#startCancellation.signal.aborted) {
|
|
357
386
|
const message = "The start was cancelled by the operator.";
|
|
358
387
|
this.#startCancellation.abort(new DomainError("run-start-aborted", message, 409));
|
|
359
|
-
this.#setStartup({ status: "failed", message });
|
|
388
|
+
if (this.#startup?.status === "preparing") this.#setStartup({ status: "failed", message });
|
|
360
389
|
}
|
|
390
|
+
for (const controller of this.#scriptStarts) controller.abort(new DomainError("run-start-aborted", "The start was cancelled by the operator.", 409));
|
|
361
391
|
try {
|
|
362
392
|
if (this.#engine.journal.stateOf(this.id)) {
|
|
363
393
|
await this.#engine.stopRun(this.id, {
|
|
@@ -386,6 +416,7 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
386
416
|
if (this.#engine.journal.stateOf(this.id)) throw new Error("The old journal must be removed before the conversation reset");
|
|
387
417
|
this.#startCancellation?.abort(new Error("The start preparation was reset."));
|
|
388
418
|
this.#startCancellation = undefined;
|
|
419
|
+
for (const controller of this.#scriptStarts) controller.abort(new Error("The start preparation was reset."));
|
|
389
420
|
this.#startup = undefined;
|
|
390
421
|
this.#unsubscribeJournal?.();
|
|
391
422
|
this.#unsubscribeLive?.();
|
|
@@ -409,6 +440,7 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
409
440
|
this.#disposed = true;
|
|
410
441
|
this.#startCancellation?.abort(new Error("The run was deleted"));
|
|
411
442
|
this.#startCancellation = undefined;
|
|
443
|
+
for (const controller of this.#scriptStarts) controller.abort(new Error("The run was deleted"));
|
|
412
444
|
this.#startup = undefined;
|
|
413
445
|
this.#unsubscribeJournal?.();
|
|
414
446
|
this.#unsubscribeLive?.();
|
|
@@ -581,32 +613,35 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
581
613
|
return this.#starting;
|
|
582
614
|
}
|
|
583
615
|
|
|
584
|
-
|
|
585
|
-
|
|
616
|
+
#start(entryId: string, input: unknown, user?: ChatUser, startedBy?: string): Promise<StartedScript> {
|
|
617
|
+
return this.#startPackage(() => {
|
|
586
618
|
const found = this.#scriptEntryFor(entryId);
|
|
587
619
|
if (!found) throw new DomainError("entry-unknown", `The template ${entryId} is not a script template of this profile.`, 404);
|
|
588
620
|
return found;
|
|
589
|
-
}, input, user);
|
|
621
|
+
}, input, user, startedBy);
|
|
590
622
|
}
|
|
591
623
|
|
|
592
|
-
|
|
624
|
+
#runStarted(): boolean {
|
|
625
|
+
return this.startLocked && this.#engine.runtime.view(this.id).actors.some((actor) => actor.kind !== "human");
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
async #startPackage(resolve: () => RunScriptStart, input: unknown, user?: ChatUser, startedBy?: string): Promise<StartedScript> {
|
|
629
|
+
if (this.#runStarted()) return this.#startInRun(resolve(), input, user, startedBy);
|
|
593
630
|
if (this.#starting) throw new DomainError("run-starting", "The run is being started.", 409);
|
|
594
|
-
if (this.startLocked && this.#engine.runtime.view(this.id).actors.some((actor) => actor.kind !== "human")) {
|
|
595
|
-
throw new DomainError("run-started", "The run is already running; a run script only starts a new run.", 409);
|
|
596
|
-
}
|
|
597
631
|
const cancellation = new AbortController();
|
|
598
632
|
this.#startCancellation = cancellation;
|
|
633
|
+
let started: StartedScript | undefined;
|
|
599
634
|
const operation = this.#exclusiveStart(async () => {
|
|
600
635
|
const { signal } = cancellation;
|
|
601
636
|
try {
|
|
602
637
|
signal.throwIfAborted();
|
|
603
638
|
const found = resolve();
|
|
604
639
|
const choice = this.#startChoice(found.entry, userIdOf(user));
|
|
605
|
-
const startValue
|
|
640
|
+
const startValue = startValueOf(input);
|
|
606
641
|
await this.#prepare(this.id, this.#emitSystem());
|
|
607
642
|
signal.throwIfAborted();
|
|
608
643
|
this.#assertUsable(this.id);
|
|
609
|
-
await this.#startWithScript(found, startValue, signal, user, choice);
|
|
644
|
+
started = await this.#startWithScript(found, startValue, signal, user, choice);
|
|
610
645
|
signal.throwIfAborted();
|
|
611
646
|
this.#setStartup(undefined);
|
|
612
647
|
} catch (error) {
|
|
@@ -620,6 +655,41 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
620
655
|
});
|
|
621
656
|
this.#setStartup({ status: "preparing", message: "Preparing run." });
|
|
622
657
|
await operation;
|
|
658
|
+
if (!started) throw new Error("The run script start ended without a result");
|
|
659
|
+
return started;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/** Starts in a running run wait for each other; each checks what can refuse it before the run changes, and none touches the primary actor or the startup status. */
|
|
663
|
+
async #startInRun(found: RunScriptStart, input: unknown, user?: ChatUser, startedBy?: string): Promise<StartedScript> {
|
|
664
|
+
if (!found.embeddable) {
|
|
665
|
+
throw new DomainError("run-started", `The run is already running; the run script "${found.entry.title}" only starts a new run. A run script starts inside a running run only if its RUN.md sets embeddable: true.`, 409);
|
|
666
|
+
}
|
|
667
|
+
const startValue = startValueOf(input);
|
|
668
|
+
const cancellation = new AbortController();
|
|
669
|
+
this.#scriptStarts.add(cancellation);
|
|
670
|
+
const operation = this.#scriptQueue.then(async () => {
|
|
671
|
+
const { signal } = cancellation;
|
|
672
|
+
signal.throwIfAborted();
|
|
673
|
+
await this.#starting?.catch(() => undefined);
|
|
674
|
+
signal.throwIfAborted();
|
|
675
|
+
const choice = this.#startChoice(found.entry, userIdOf(user));
|
|
676
|
+
await this.#prepare(this.id, this.#emitSystem());
|
|
677
|
+
signal.throwIfAborted();
|
|
678
|
+
this.#assertUsable(this.id);
|
|
679
|
+
await this.#prepareWorkspace(this.id, this.#emitSystem());
|
|
680
|
+
signal.throwIfAborted();
|
|
681
|
+
this.#assertUsable(this.id);
|
|
682
|
+
const installed = await this.#installScript(found, signal);
|
|
683
|
+
signal.throwIfAborted();
|
|
684
|
+
this.#assertUsable(this.id);
|
|
685
|
+
return this.#enqueueStart(found, installed, startValue, choice, true, startedBy);
|
|
686
|
+
});
|
|
687
|
+
this.#scriptQueue = operation.catch(() => undefined);
|
|
688
|
+
try {
|
|
689
|
+
return await operation;
|
|
690
|
+
} finally {
|
|
691
|
+
this.#scriptStarts.delete(cancellation);
|
|
692
|
+
}
|
|
623
693
|
}
|
|
624
694
|
|
|
625
695
|
async #startRun(user: ChatUser | undefined, choice: StartChoice): Promise<void> {
|
|
@@ -632,8 +702,8 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
632
702
|
this.#assertUsable(this.id);
|
|
633
703
|
}
|
|
634
704
|
|
|
635
|
-
async #startWithScript(found: RunScriptStart, input: JsonValue | null, signal: AbortSignal, user: ChatUser | undefined, choice: StartChoice): Promise<
|
|
636
|
-
const { entry
|
|
705
|
+
async #startWithScript(found: RunScriptStart, input: JsonValue | null, signal: AbortSignal, user: ChatUser | undefined, choice: StartChoice): Promise<StartedScript> {
|
|
706
|
+
const { entry } = found;
|
|
637
707
|
this.#createRunIfNeeded(this.#initialTitle ?? entry.title, user, choice);
|
|
638
708
|
this.#assertUsable(this.id);
|
|
639
709
|
this.#setStartup({ status: "preparing", message: "Preparing working directory." });
|
|
@@ -643,50 +713,40 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
643
713
|
this.#assertUsable(this.id);
|
|
644
714
|
this.#setStartup({ status: "preparing", message: "Preparing UI." });
|
|
645
715
|
signal.throwIfAborted();
|
|
646
|
-
await this.#
|
|
647
|
-
signal.throwIfAborted();
|
|
648
|
-
const state = this.#engine.runtime.state(this.id);
|
|
649
|
-
const installed = await this.#actorPrograms.importPackage(
|
|
650
|
-
{actorId: state.ownerId, commandId: `run-script:${this.id}:${script.handle}`},
|
|
651
|
-
this.id, script.handle, script.files, signal, entry.id,
|
|
652
|
-
);
|
|
716
|
+
const installed = await this.#installScript(found, signal);
|
|
653
717
|
signal.throwIfAborted();
|
|
654
718
|
this.#assertUsable(this.id);
|
|
655
|
-
if (
|
|
719
|
+
if (found.coordinator) this.#ensureCoordinatorAsPrimary(choice);
|
|
656
720
|
else {
|
|
721
|
+
const state = this.#engine.runtime.state(this.id);
|
|
657
722
|
this.#engine.runtime.selectPrimaryActor({actorId: state.ownerId, commandId: `run-script-primary:${this.id}`}, this.id, installed.actorId);
|
|
658
723
|
this.#bind(installed.actorId);
|
|
659
724
|
}
|
|
660
725
|
await this.#started(this.id, choice.entry);
|
|
661
726
|
this.#assertUsable(this.id);
|
|
662
|
-
const options = Object.fromEntries(this.#engine.startOptions.entries()
|
|
663
|
-
.map((option) => [option.option.id, this.#startValueOf(option, choice)]));
|
|
664
727
|
signal.throwIfAborted();
|
|
665
|
-
this.#
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
728
|
+
const started = this.#enqueueStart(found, installed, input, choice, false);
|
|
729
|
+
if (found.coordinator) this.#emit({ kind: "system", text: `The run script "${entry.title}" runs as @${installed.actorHandle} and sets up the run.` });
|
|
730
|
+
return started;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
#installScript(found: RunScriptStart, signal: AbortSignal): Promise<ActivatedActorProgram> {
|
|
734
|
+
const { entry, handle, files, programs, sharedPrograms = [] } = found;
|
|
735
|
+
return this.#actorPrograms.installScript(
|
|
736
|
+
{actorId: this.#engine.runtime.state(this.id).ownerId, commandId: `run-script:${this.id}:${handle}:${randomUUID()}`},
|
|
737
|
+
this.id, {entryId: entry.id, handle, files, programs, sharedPrograms}, signal,
|
|
669
738
|
);
|
|
670
|
-
if (script.coordinator) {
|
|
671
|
-
this.#emit({ kind: "system", text: `The run script "${entry.title}" runs as @${installed.actorHandle} and sets up the run.` });
|
|
672
|
-
return;
|
|
673
|
-
}
|
|
674
739
|
}
|
|
675
740
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
const
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
const destination = path.join(target, file.path);
|
|
686
|
-
await mkdir(path.dirname(destination), {recursive: true});
|
|
687
|
-
await writeFile(destination, file.content, {flag: "wx"});
|
|
688
|
-
}
|
|
689
|
-
}
|
|
741
|
+
#enqueueStart(found: RunScriptStart, installed: ActivatedActorProgram, input: JsonValue | null, choice: StartChoice, embedded: boolean, startedBy?: string): StartedScript {
|
|
742
|
+
const ownerId = this.#engine.runtime.state(this.id).ownerId;
|
|
743
|
+
const options = Object.fromEntries(this.#engine.startOptions.entries()
|
|
744
|
+
.map((option) => [option.option.id, this.#startValueOf(option, choice)]));
|
|
745
|
+
const { count } = this.#actorPrograms.enqueueStart(
|
|
746
|
+
{actorId: ownerId, commandId: `run-script-input:${this.id}:${found.handle}:${randomUUID()}`},
|
|
747
|
+
this.id, found.handle, {content: JSON.stringify({ input, options }), embedded, startedBy: startedBy ?? ownerId},
|
|
748
|
+
);
|
|
749
|
+
return { actorId: installed.actorId, handle: installed.actorHandle, count };
|
|
690
750
|
}
|
|
691
751
|
|
|
692
752
|
#createRunIfNeeded(title: string, user: ChatUser | undefined, choice: StartChoice): void {
|
|
@@ -904,6 +964,8 @@ export class RunChatSession implements ChatSessionLike {
|
|
|
904
964
|
primaryActorId,
|
|
905
965
|
ownerId: this.#engine.runtime.state(this.id).ownerId,
|
|
906
966
|
labelOf: (actorId) => this.#engine.runtime.state(this.id).actors.get(actorId)?.displayName,
|
|
967
|
+
scriptActorHandle: (actorId) => this.#actorPrograms.isScriptActor(this.id, actorId)
|
|
968
|
+
? this.#engine.runtime.select(this.id, (state) => state.actors.get(actorId)?.handle) : undefined,
|
|
907
969
|
turnOf: (turnId) => {
|
|
908
970
|
const turn = this.#engine.runtime.state(this.id).turns.get(turnId);
|
|
909
971
|
if (!turn) throw new Error(`The turn ${turnId} is missing from run ${this.id}`);
|
|
@@ -4,7 +4,7 @@ import type { ModelRuntime } from "@ragents/agent";
|
|
|
4
4
|
import type { TitleModelSelection } from "./title-settings-contract.js";
|
|
5
5
|
|
|
6
6
|
const MAX_PROMPT_CHARS = 4_000;
|
|
7
|
-
const MAX_TITLE_CHARS = 80;
|
|
7
|
+
export const MAX_TITLE_CHARS = 80;
|
|
8
8
|
|
|
9
9
|
const instruction =
|
|
10
10
|
"You summarize the first task of a run as a list title. "
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r,S as d,E as p,j as E,c as f}from"./mermaid-HWGCJPDP-
|
|
1
|
+
import{r,S as d,E as p,j as E,c as f}from"./mermaid-HWGCJPDP-CSCkaArr.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 ue,r as s,j as e,D as fe,b as pe,d as ee,B as g,X as Le,M as Ie,C as xe,e as _e,f as Be,g as He,h as Ue,u as Fe,i as qe,k as Te,l as Ke,m as $e,A as We,n as Qe,o as Ve,U as Ge,P as Xe,W as Ye,R as Je,p as le,q as J,s as Ze,t as et,v as tt,w as st,x as nt,y as at,z as rt,Q as ot,F as it,G as lt}from"./mermaid-HWGCJPDP-CSCkaArr.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 me={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"]};me.node;const ct=ue(me);/**
|
|
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 dt=ue(he);function ut(n,r,a,u){if(!r||n.source!==r||n.origin!==a)return;const o=n.data;if(!(!o||typeof o!="object"||Array.isArray(o))&&"type"in o){if(o.type==="ragents:help-ready")return{type:"ready"};if(o.type==="ragents:start-sample"&&"entry"in o&&typeof o.entry=="string"&&u.includes(o.entry))return{type:"start",entry:o.entry}}}function ft({onClose:n,sampleEntries:r,onStartSample:a}){const u=s.useRef(null),o=s.useRef(null),p=s.useRef(void 0),m=s.useRef(!1);s.useEffect(()=>()=>{var i;return(i=p.current)==null?void 0:i.call(p)},[]),s.useEffect(()=>{var j;const i=(j=o.current)==null?void 0:j.contentWindow;if(!i)return;const l=()=>i.postMessage({type:"ragents:help-context",canStartSamples:r.length>0,entries:r},window.location.origin),h=k=>{const c=ut(k,i,window.location.origin,r);(c==null?void 0:c.type)==="ready"&&l(),(c==null?void 0:c.type)==="start"&&!m.current&&(m.current=!0,a(c.entry))};return window.addEventListener("message",h),l(),()=>window.removeEventListener("message",h)},[a,r]);const x=()=>{var k;(k=p.current)==null||k.call(p);const i=o.current,l=i==null?void 0:i.contentDocument,h=l==null?void 0:l.defaultView;if(!i||!l||!h)return;l.documentElement.dataset.helpEmbedded="true";for(const c of l.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 w=[...l.querySelectorAll("a[href], button, input, select, textarea, summary, [tabindex]")].filter(S=>S.tabIndex>=0&&!S.matches(":disabled")&&S.getClientRects().length>0),L=c.shiftKey?w[0]:w.at(-1);if(!w.length||l.activeElement===L||l.activeElement===l.body){if(!c.shiftKey&&l.activeElement===l.body&&w.length)return;c.preventDefault(),(v=u.current)==null||v.focus()}}}};h.addEventListener("keydown",j),p.current=()=>h.removeEventListener("keydown",j)};return e.jsx(fe,{open:!0,onOpenChange:i=>{i||n()},children:e.jsxs(pe,{className:"gap-0 p-0",initialFocus:u,scope:"page",showCloseButton:!1,size:"full",children:[e.jsx(ee,{className:"sr-only",children:"Help"}),e.jsx(g,{"aria-label":"Close help",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:x,ref:o,src:"/help/index.html",tabIndex:0,title:"RAgents: homepage and documentation"})]})})}const pt="button:not([disabled]), a[href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex='-1'])",ve="pointer-events-auto shadow-pop";function xt({onBusy:n,onClose:r,onOpen:a,open:u,panels:o,registry:p,runs:m}){const x=s.useRef(null);return s.useEffect(()=>{if(!u)return;const i=requestAnimationFrame(()=>{var h;const l=x.current;!l||l.contains(document.activeElement)||(h=l.querySelector(pt))==null||h.focus({preventScroll:!0})});return()=>cancelAnimationFrame(i)},[u]),e.jsxs(Ie,{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(ee,{className:"sr-only",children:"Overview"}),e.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1 gap-4 max-[900px]:flex-col",id:"app-overview",ref:x,children:[o.map(({id:i,Panel:l})=>e.jsx(mt,{id:i,onBusy:n,onClose:r,onOpen:a,open:u,Panel:l,registry:p},i)),m&&e.jsx(ht,{...m})]})]})}function mt({id:n,onBusy:r,onClose:a,onOpen:u,open:o,Panel:p,registry:m}){const x=s.useCallback(i=>r(n,i),[n,r]);return s.useEffect(()=>()=>r(n,!1),[n,r]),e.jsx(xe,{className:`${ve} min-h-0 min-w-0 flex-1 gap-0 p-0`,children:e.jsx(p,{onBusy:x,onClose:a,onOpen:u,open:o,registry:m})})}function ht({activeId:n,canCreate:r,canDelete:a,onCreate:u,onDelete:o,onOpen:p,registry:m,sessions:x,seenRevisions:i,unreachable:l}){const[h,j]=s.useState(),[k,c]=s.useState(!1),[v,w]=s.useState(()=>new Set),[L,S]=s.useState(!1),[E,B]=s.useState(!1),H=()=>{c(!1),w(new Set)},b=f=>{w(O=>{const I=new Set(O);return I.delete(f)||I.add(f),I})},D=async f=>{B(!0),j(void 0);try{await o(f)}catch(O){j(O instanceof Error?O.message:String(O))}finally{B(!1)}},C=async()=>{await D(x.filter(f=>v.has(f.id)).map(f=>f.id)),S(!1),H()};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(xe,{className:`${ve} 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:x.length})]}),l&&e.jsx("span",{className:"text-[0.72rem] font-medium text-destructive",role:"alert",children:"Server unreachable"}),a&&x.length>0&&e.jsx("div",{className:"ml-auto flex flex-wrap items-center gap-1",children:k?e.jsxs(e.Fragment,{children:[e.jsx(g,{onClick:()=>w(new Set(x.map(f=>f.id))),size:"sm",variant:"ghost",children:"All"}),e.jsx(g,{onClick:()=>w(new Set),size:"sm",variant:"ghost",children:"None"}),e.jsxs(g,{className:"ml-auto",disabled:v.size===0||E,onClick:()=>S(!0),size:"sm",variant:"destructive",children:["Delete (",v.size,")"]}),e.jsx(g,{onClick:H,size:"sm",variant:"ghost",children:"Done"})]}):e.jsx(g,{onClick:()=>c(!0),size:"sm",variant:"ghost",children:"Select"})})]}),h&&e.jsx("p",{className:"text-[0.72rem] font-medium text-destructive",role:"alert",children:h}),e.jsx("p",{className:"mb-5.5 text-[0.75rem] text-muted-foreground",children:"By last activity in the run. New activity has come in since you last viewed it."}),e.jsx(_e,{seenRevisions:i,activeId:n,onCreate:r?u:void 0,onDelete:a?f=>void D([f]):void 0,onSelect:p,onToggleSelected:b,registry:m,selectMode:k,selectedIds:v,sessions:x}),L&&e.jsx(fe,{open:!0,onOpenChange:f=>{!f&&!E&&S(!1)},children:e.jsxs(pe,{scope:"page",showCloseButton:!1,size:"small",children:[e.jsxs(Be,{children:[e.jsx(ee,{children:"Delete runs"}),e.jsx(He,{children:v.size===1?"One run will be permanently deleted.":`${v.size} runs will be permanently deleted.`})]}),e.jsxs(Ue,{children:[e.jsx(g,{disabled:E,onClick:()=>S(!1),variant:"outline",children:"Cancel"}),e.jsx(g,{disabled:E,onClick:()=>void C(),children:E?"Deleting ...":`Delete (${v.size})`})]})]})})]})})}const Z="flex min-h-0 min-w-0 flex-1 flex-col",vt="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 bt(){var ie;const n=Fe(),r=qe((ie=n.user)==null?void 0:ie.id),a=n.can("runs.read"),u=a&&n.can("runs.write"),o=n.can("runs.inspect"),p=a&&n.can("runs.delete"),m=Te(),x=s.useRef(null),i=s.useRef(null),[l,h]=s.useState(null),[j,k]=s.useState(null),[c,v]=s.useState(null),[w,L]=s.useState(null),[S,E]=s.useState(null),[B,H]=s.useState([]),[b,D]=s.useState(),[C,f]=s.useState(),[O,I]=s.useState(),[U,te]=s.useState(!1),[F,K]=s.useState(!1),[N,se]=s.useState(!1),[$,z]=s.useState(),[ge,we]=s.useState(!1),[ye,je]=s.useState(()=>new Set),[Se,ne]=s.useState(!1),_=s.useRef(void 0),W=s.useRef(!1),M=s.useCallback(()=>{if(!a)return Promise.resolve();if(_.current)return W.current=!0,_.current;const t=async()=>{do{W.current=!1;try{H(await et()),ne(!1)}catch{ne(!0)}}while(W.current)};return _.current=t().finally(()=>{_.current=void 0}),_.current},[a]);s.useEffect(()=>{if(!a||b)return;M();const t=Ke.subscribe($e.channels.runs,{},()=>void M()),d=setInterval(()=>void M(),5e3);return()=>{t(),clearInterval(d)}},[b,a,M]);const A=s.useCallback((t=!1)=>{var d;se(!1),t&&((d=x.current)==null||d.focus({preventScroll:!0}))},[]),Q=s.useCallback(()=>{z(void 0),we(!0),se(!0)},[]),V=s.useCallback(()=>{N?A(!0):Q()},[A,Q,N]);s.useEffect(()=>{const t=d=>{if(d.defaultPrevented||d.repeat||d.altKey||d.shiftKey||d.key.toLowerCase()!=="i"||d.metaKey===d.ctrlKey)return;const R=x.current;!R||R.closest("[inert]")||(d.preventDefault(),V())};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[V]);const G=s.useCallback((t,d)=>je(R=>{if(R.has(t)===d)return R;const P=new Set(R);return d?P.add(t):P.delete(t),P}),[]),ae=B,Ce=ae.find(t=>t.id===C),ke=s.useCallback(()=>{z(void 0),te(!0)},[]),Ne=s.useCallback(()=>K(!1),[]),Re=s.useCallback(()=>{te(!1),requestAnimationFrame(()=>{var t;return(t=i.current)==null?void 0:t.focus()})},[]),Ee=e.jsx(g,{"aria-label":"Open settings",onClick:ke,ref:i,size:"icon-lg",title:"Settings",variant:"ghost",children:e.jsx(tt,{})}),De=t=>{f(t),A(!0)},Oe=()=>{z(void 0),A(!0),D({id:crypto.randomUUID(),title:"New run",updatedAt:Date.now()})},ze=async t=>{const d=await Promise.allSettled(t.map(T=>st(T))),R=t.filter((T,Pe)=>d[Pe].status==="fulfilled");C!==void 0&&R.includes(C)&&f(void 0),await M();const P=d.find(T=>T.status==="rejected");if(P)throw P.reason};if(m.status==="loading")return e.jsx("div",{className:"m-auto p-6 text-muted-foreground",children:"Loading profile."});if(m.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:Z,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:"Profile unavailable"})}),e.jsxs(We,{className:"m-auto max-w-[560px] gap-3 p-6",variant:"destructive",children:[e.jsx("p",{children:m.error}),e.jsx(g,{variant:"outline",onClick:()=>window.location.reload(),children:"Reload"})]})]})})});const y=m.registry,X=y.overviewPanels.filter(t=>t.readRight===void 0||n.can(t.readRight)),Y=X.filter(t=>(t.placement??"overview")==="overview"),Ae=X.filter(t=>t.placement==="toolbar"),q=a?X.find(t=>t.placement==="idle"):void 0,Me=a||Y.length>0,re=Y.some(t=>ye.has(t.id)),oe=Qe(a?C:void 0,N,O);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:[Me&&e.jsx("div",{className:"relative flex flex-none self-stretch",children:e.jsx("button",{"aria-controls":"app-overview","aria-expanded":N,"aria-haspopup":"dialog","aria-keyshortcuts":"Meta+I Control+I","aria-label":N?"Close overview":"Open overview",className:vt,onClick:V,ref:x,title:`Overview (Cmd+I / Ctrl+I)${re?": processing":""}`,type:"button",children:re?e.jsx(Ve,{"aria-hidden":!0,className:"size-[18px]"}):e.jsx(dt,{size:22})})}),Ae.map(({id:t,Panel:d})=>e.jsx(ce,{id:t,onBusy:G,onClose:()=>z(void 0),onOpen:()=>{!U&&!F&&!b&&(A(),z(t))},open:$===t,Panel:d,registry:y,userLocation:oe},t)),e.jsx("div",{"aria-label":"Run title bar",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:h,role:"region",tabIndex:0}),e.jsx(Ge,{}),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:k}),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")&&Ee,o&&e.jsx(g,{"aria-haspopup":"dialog","aria-label":"Open help",onClick:()=>{z(void 0),K(!0)},size:"icon-lg",title:"Help",variant:"ghost",children:e.jsx(ct,{})})]})]})]}),e.jsx(Xe,{failures:m.failures}),e.jsx(Ye.Provider,{value:w,children:e.jsx("div",{className:"relative flex min-h-0 flex-1 flex-col",ref:L,children:e.jsxs(Je.Provider,{value:S,children:[e.jsxs("div",{className:"relative flex h-auto min-h-0 flex-1",ref:E,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&&C?e.jsx(le,{headerContainer:l,workspaceHeaderContainer:j,statusContainer:c,onLocationChange:I,onViewed:r.markViewed,viewing:!N&&!U&&!F&&!b&&!$,registry:y,session:Ce??{id:C,title:"New run",updatedAt:Date.now()}},C):q?e.jsx("div",{className:Z,children:e.jsx(ce,{id:q.id,onBusy:G,onClose:()=>{},onOpen:()=>{},open:!N&&!U&&!F&&!b&&!$,Panel:q.Panel,registry:y,userLocation:oe},q.id)}):e.jsx("div",{className:Z,children:e.jsx("div",{className:"m-auto text-center text-muted-foreground",children:a?u?"Open the overview at the top left to choose a run or start a new one.":"Open the overview at the top left to choose a run. You have read access.":"No runs are shared with this user account."})})}),ge&&e.jsx(xt,{onOpen:Q,onBusy:G,onClose:()=>A(!0),open:N,panels:Y,registry:y,runs:a?{activeId:C,canCreate:u&&(n.can("runs.create")||y.scriptEntries.some(t=>J(n,t.id))),canDelete:p,onCreate:Oe,onDelete:ze,onOpen:De,registry:y,sessions:ae,seenRevisions:r.revisions,unreachable:Se}:void 0}),b&&e.jsx(le,{onStarted:()=>{f(b.id),D(void 0),M()},registry:y,session:b,startDialog:{onClose:()=>D(void 0),initialEntryId:b.startEntryId}},b.id),U&&e.jsx(Ze,{onClose:Re,registry:y}),o&&F&&e.jsx(ft,{onClose:Ne,sampleEntries:y.scriptEntries.filter(t=>J(n,t.id)).map(t=>t.id),onStartSample:t=>{!J(n,t)||!y.scriptEntries.some(d=>d.id===t)||(K(!1),z(void 0),A(),D({id:crypto.randomUUID(),title:"New run",updatedAt:Date.now(),startEntryId:t}))}})]}),e.jsx("footer",{"aria-label":"Run status bar",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 ce({id:n,onBusy:r,Panel:a,...u}){const o=s.useCallback(p=>r(n,p),[n,r]);return s.useEffect(()=>()=>r(n,!1),[n,r]),e.jsx(a,{...u,onBusy:o})}nt();const be=document.getElementById("root");if(!be)throw new Error("Root element is missing");const de=at.createRoot(be);try{const n=rt(window);de.render(e.jsx(s.StrictMode,{children:e.jsx(ot,{children:e.jsx(it,{children:e.jsx(bt,{})})})}))}catch(n){de.render(e.jsxs(lt,{children:[e.jsx("h1",{className:"my-3 text-[1.5rem]",children:"The view could not be loaded"}),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:"Reload"})]}))}
|