@schlenkr/ragents 0.1.14 → 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 +23 -4
- 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/web/dist/assets/{highlighted-body-KPVGNVTW-BslIwn_y.js → highlighted-body-KPVGNVTW-BwD4uYEe.js} +1 -1
- package/apps/web/dist/assets/{main-BUN8m8SW.js → main-KBrc5Q77.js} +1 -1
- package/apps/web/dist/assets/{mermaid-HWGCJPDP-B1erZlFM.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 +7 -2
- package/apps/web/dist/host-web.json +6 -6
- 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/run-panel/RunPanelApp.tsx +1 -1
- package/apps/web/src/run-panel/RunPanelMenu.tsx +47 -11
- 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 +1 -1
- 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.overseer/ragents-bundle.json +1 -1
- package/bundles/ragents.processes/ragents-bundle.json +1 -1
- 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 +1 -1
- 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.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.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/scripts/agent/agent-cli.ts +46 -2
- package/scripts/package/ragents.mjs +3 -1
- package/apps/web/dist/assets/runPanel-s8gGpr9M.js +0 -21
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineActor } from "@ragents/server";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
|
|
4
|
+
const KEPT_NOTES = 50;
|
|
5
|
+
|
|
6
|
+
const contract = {
|
|
7
|
+
state: Type.Object({ notes: Type.Optional(Type.Array(Type.String())) }, { additionalProperties: false }),
|
|
8
|
+
functions: {
|
|
9
|
+
clear: { label: "Clear notes", input: Type.Object({}, { additionalProperties: false }), output: Type.Object({ cleared: Type.Integer() }, { additionalProperties: false }) },
|
|
10
|
+
},
|
|
11
|
+
input: { capabilities: [] },
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
export default defineActor(contract, {
|
|
15
|
+
functions: {
|
|
16
|
+
clear: (_input, context) => {
|
|
17
|
+
const cleared = context.state.read().notes?.length ?? 0;
|
|
18
|
+
context.state.replace({ notes: [] });
|
|
19
|
+
return { cleared };
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
onInput: (input, context) => {
|
|
23
|
+
const note = input.content.trim();
|
|
24
|
+
if (!note) throw new Error("A note needs text.");
|
|
25
|
+
context.state.replace({ notes: [note, ...context.state.read().notes ?? []].slice(0, KEPT_NOTES) });
|
|
26
|
+
},
|
|
27
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { createTestContext } from "@ragents/server/testing";
|
|
4
|
+
import program from "../src/server.ts";
|
|
5
|
+
|
|
6
|
+
const input = (content: string) => ({ id: "input-1", content, artifactIds: [], sourceEventIds: [], subscriptionId: null, event: null });
|
|
7
|
+
|
|
8
|
+
test("keeps notes newest first and at most fifty", async () => {
|
|
9
|
+
const context = createTestContext<{ notes?: string[] }>({ state: { notes: Array.from({ length: 50 }, (_, index) => `old ${index}`) } });
|
|
10
|
+
await program.onInput!(input(" new note "), context);
|
|
11
|
+
const notes = context.state.read().notes!;
|
|
12
|
+
assert.equal(notes.length, 50);
|
|
13
|
+
assert.equal(notes[0], "new note");
|
|
14
|
+
assert.equal(notes.at(-1), "old 48");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("an empty note is refused and changes nothing", async () => {
|
|
18
|
+
const context = createTestContext<{ notes?: string[] }>({ state: { notes: ["kept"] } });
|
|
19
|
+
await assert.rejects(async () => program.onInput!(input(" "), context), /needs text/);
|
|
20
|
+
assert.deepEqual(context.state.read(), { notes: ["kept"] });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("clear empties the notebook and names how many notes it removed", async () => {
|
|
24
|
+
const context = createTestContext<{ notes?: string[] }>({ state: { notes: ["one", "two"] } });
|
|
25
|
+
assert.deepEqual(await program.functions.clear({}, context), { cleared: 2 });
|
|
26
|
+
assert.deepEqual(context.state.read(), { notes: [] });
|
|
27
|
+
});
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
]
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
-
"revision": "
|
|
24
|
-
"sourceRevision": "
|
|
23
|
+
"revision": "2c684e9daab9b2ffe4c002c03d4fa8549b2d4dd0b20513fb5eec0e4f10a396ee",
|
|
24
|
+
"sourceRevision": "0f2f0bb43908bed73e743ed21d07d35abed4bcc84563c893c5c32117ad559ade",
|
|
25
25
|
"server": "server/index.js",
|
|
26
26
|
"web": {
|
|
27
27
|
"entry": "web/index.js",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"uses": [],
|
|
35
35
|
"assets": [
|
|
36
36
|
"skills",
|
|
37
|
-
"run-scripts"
|
|
37
|
+
"run-scripts",
|
|
38
|
+
"actors"
|
|
38
39
|
]
|
|
39
40
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Add a quick note
|
|
3
|
+
description: "A prepared one-step script shows a shared actor package: it adds a note to the notebook it shares with the roster check, in a new or a running run."
|
|
4
|
+
order: 180
|
|
5
|
+
coordinator: false
|
|
6
|
+
embeddable: true
|
|
7
|
+
shared-programs: notebook
|
|
8
|
+
tags: Run scripts, Concept demo, TypeScript actors
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
The start value `{ "text": "..." }` is the note; without one, the script notes when it was
|
|
12
|
+
started. The script makes the shared notebook active with `actor_program_ensure`, sends it the
|
|
13
|
+
note, places the notebook's view with `canvas_layout_place`, and ends the start with
|
|
14
|
+
`context.finish`. Whether the roster check or this script comes first, the run has one notebook.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineActor } from "@ragents/server";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
|
|
4
|
+
const contract = {
|
|
5
|
+
state: Type.Object({}, { additionalProperties: false }),
|
|
6
|
+
functions: {},
|
|
7
|
+
input: { capabilities: ["actor_program_ensure", "actor_input", "canvas_layout_place"] },
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
const noteOf = (input: unknown, now: string): string => {
|
|
11
|
+
if (input === null) return `Started at ${now}.`;
|
|
12
|
+
const text = typeof input === "object" && input !== null && "text" in input ? (input as { text: unknown }).text : undefined;
|
|
13
|
+
if (typeof text !== "string" || !text.trim()) throw new Error('The start value is { "text": "..." } with the note, or none.');
|
|
14
|
+
return text.trim();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default defineActor(contract, {
|
|
18
|
+
functions: {},
|
|
19
|
+
onInput: () => {
|
|
20
|
+
throw new Error("The quick note answers only starts; start it again with the note as its start value.");
|
|
21
|
+
},
|
|
22
|
+
onStart: async (start, context) => {
|
|
23
|
+
const note = noteOf(start.input, context.std.now());
|
|
24
|
+
const notebook = await context.functions.actor_program_ensure({ name: "notebook" });
|
|
25
|
+
await context.functions.actor_input({ actor: `@${notebook.handle}`, content: note });
|
|
26
|
+
await context.functions.canvas_layout_place({ entity: "app:notebook/main" });
|
|
27
|
+
context.finish({ note, notebook: notebook.status }, { summary: `Noted: ${note}` });
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { createTestContext } from "@ragents/server/testing";
|
|
4
|
+
import program from "../src/server.ts";
|
|
5
|
+
|
|
6
|
+
const start = (input: unknown) => ({ input, options: {}, embedded: true, startedBy: "owner-id", count: 1 });
|
|
7
|
+
|
|
8
|
+
const note = (status: "active" | "installed" = "installed") => {
|
|
9
|
+
const calls: { name: string; input: unknown }[] = [];
|
|
10
|
+
const record = <T>(name: string, answer: T) => (input: unknown): T => { calls.push({ name, input }); return answer; };
|
|
11
|
+
const context = createTestContext<Record<string, never>>({ state: {}, functions: {
|
|
12
|
+
actor_program_ensure: record("actor_program_ensure", { actorId: "id-notebook", handle: "notebook", status }),
|
|
13
|
+
actor_input: record("actor_input", []),
|
|
14
|
+
canvas_layout_place: record("canvas_layout_place", { placed: status === "installed" }),
|
|
15
|
+
} });
|
|
16
|
+
return { calls, context };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
test("sends the note to the shared notebook and reports it", async () => {
|
|
20
|
+
const { calls, context } = note();
|
|
21
|
+
await program.onStart!(start({ text: " Ask about the budget " }), context);
|
|
22
|
+
assert.deepEqual(calls.map((call) => [call.name, call.input]), [
|
|
23
|
+
["actor_program_ensure", { name: "notebook" }],
|
|
24
|
+
["actor_input", { actor: "@notebook", content: "Ask about the budget" }],
|
|
25
|
+
["canvas_layout_place", { entity: "app:notebook/main" }],
|
|
26
|
+
]);
|
|
27
|
+
assert.deepEqual(context.finished, [{ result: { note: "Ask about the budget", notebook: "installed" }, summary: "Noted: Ask about the budget" }]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("without a start value it notes when it started; an invalid value changes nothing", async () => {
|
|
31
|
+
const { calls, context } = note("active");
|
|
32
|
+
await program.onStart!(start(null), context);
|
|
33
|
+
assert.match(String((calls[1]!.input as { content: string }).content), /^Started at /);
|
|
34
|
+
const invalid = note();
|
|
35
|
+
await assert.rejects(async () => program.onStart!(start({ text: "" }), invalid.context), /start value/);
|
|
36
|
+
assert.deepEqual(invalid.calls, []);
|
|
37
|
+
assert.deepEqual(invalid.context.finished, []);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("an ordinary message is refused", async () => {
|
|
41
|
+
const { context } = note();
|
|
42
|
+
await assert.rejects(async () => program.onInput!({ id: "input-1", content: "hello", artifactIds: [], sourceEventIds: [], subscriptionId: null, event: null }, context), /answers only starts/);
|
|
43
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Take stock of the run
|
|
3
|
+
description: "A prepared check shows a run script that also joins a running run. It lists the other participants, notes them in the shared notebook, and reports them back as its result."
|
|
4
|
+
order: 170
|
|
5
|
+
coordinator: false
|
|
6
|
+
embeddable: true
|
|
7
|
+
shared-programs: notebook
|
|
8
|
+
tags: Run scripts, Concept demo, TypeScript actors
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
The TypeScript program reads the participants with `actor_list` and ends each start with
|
|
12
|
+
`context.finish`. The owner reads the summary in the chat; a coordinator that starts it through
|
|
13
|
+
`run_script_start` receives summary and list as a message. Started inside a running run through the
|
|
14
|
+
run menu, `ragents script`, or the coordinator, it changes neither the primary actor nor the tiles,
|
|
15
|
+
and a repeated start reuses the same actor. Started as a new run, it is the run's only participant.
|
|
16
|
+
|
|
17
|
+
It shares the notebook with the quick note script: `shared-programs: notebook` copies the plugin's
|
|
18
|
+
shared package into the run, `actor_program_ensure` makes it active once, and
|
|
19
|
+
`canvas_layout_place` puts its view next to what is arranged.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineActor } from "@ragents/server";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
|
|
4
|
+
const contract = {
|
|
5
|
+
state: Type.Object({ reports: Type.Optional(Type.Number()) }, { additionalProperties: false }),
|
|
6
|
+
functions: {},
|
|
7
|
+
input: { capabilities: ["actor_list", "actor_program_ensure", "actor_input", "canvas_layout_place"] },
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
export default defineActor(contract, {
|
|
11
|
+
functions: {},
|
|
12
|
+
onInput: () => {
|
|
13
|
+
throw new Error("The roster answers only starts; start it again from the run menu or with run_script_start.");
|
|
14
|
+
},
|
|
15
|
+
onStart: async (_start, context) => {
|
|
16
|
+
const actors = await context.functions.actor_list({});
|
|
17
|
+
const others = actors.filter((actor) => actor.kind !== "human" && actor.handle !== context.actor.handle);
|
|
18
|
+
const handles = others.map((actor) => `@${actor.handle}`);
|
|
19
|
+
const summary = handles.length === 0 ? "No other participants yet." : `${handles.length} participant${handles.length === 1 ? "" : "s"}: ${handles.join(", ")}.`;
|
|
20
|
+
const notebook = await context.functions.actor_program_ensure({ name: "notebook" });
|
|
21
|
+
await context.functions.actor_input({ actor: `@${notebook.handle}`, content: `Roster: ${summary}` });
|
|
22
|
+
await context.functions.canvas_layout_place({ entity: "app:notebook/main" });
|
|
23
|
+
context.state.replace({ reports: (context.state.read().reports ?? 0) + 1 });
|
|
24
|
+
context.finish({ actors: others.map(({ handle, kind, lifecycle }) => ({ handle, kind, lifecycle })) }, { summary });
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { createTestContext } from "@ragents/server/testing";
|
|
4
|
+
import program from "../src/server.ts";
|
|
5
|
+
|
|
6
|
+
const start = { input: null, options: {}, embedded: true, startedBy: "owner-id", count: 1 };
|
|
7
|
+
const actor = (handle: string, kind: "human" | "agent" | "script", lifecycle = "idle") =>
|
|
8
|
+
({ id: `id-${handle}`, handle, displayName: handle, kind, lifecycle, createdBy: null, description: null, toolCount: null });
|
|
9
|
+
|
|
10
|
+
const roster = (actors: ReturnType<typeof actor>[], state: { reports?: number } = {}) => {
|
|
11
|
+
const calls: { name: string; input: unknown }[] = [];
|
|
12
|
+
const record = <T>(name: string, answer: T) => (input: unknown): T => { calls.push({ name, input }); return answer; };
|
|
13
|
+
const context = createTestContext<{ reports?: number }>({ state, functions: {
|
|
14
|
+
actor_list: record("actor_list", actors),
|
|
15
|
+
actor_program_ensure: record("actor_program_ensure", { actorId: "id-notebook", handle: "notebook", status: "active" as const }),
|
|
16
|
+
actor_input: record("actor_input", []),
|
|
17
|
+
canvas_layout_place: record("canvas_layout_place", { placed: true }),
|
|
18
|
+
} });
|
|
19
|
+
return { calls, context };
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
test("reports the other participants as result and summary and notes them in the shared notebook", async () => {
|
|
23
|
+
const { calls, context } = roster([actor("owner", "human"), actor("coordinator", "agent", "running"), actor("helper", "agent"), actor("test", "script")]);
|
|
24
|
+
await program.onStart!(start, context);
|
|
25
|
+
assert.deepEqual(context.finished, [{
|
|
26
|
+
result: { actors: [{ handle: "coordinator", kind: "agent", lifecycle: "running" }, { handle: "helper", kind: "agent", lifecycle: "idle" }] },
|
|
27
|
+
summary: "2 participants: @coordinator, @helper.",
|
|
28
|
+
}]);
|
|
29
|
+
assert.deepEqual(calls.slice(1).map((call) => [call.name, call.input]), [
|
|
30
|
+
["actor_program_ensure", { name: "notebook" }],
|
|
31
|
+
["actor_input", { actor: "@notebook", content: "Roster: 2 participants: @coordinator, @helper." }],
|
|
32
|
+
["canvas_layout_place", { entity: "app:notebook/main" }],
|
|
33
|
+
]);
|
|
34
|
+
assert.deepEqual(context.state.read(), { reports: 1 });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("a run without other participants still gets a result, and every start counts", async () => {
|
|
38
|
+
const { context } = roster([actor("owner", "human"), actor("test", "script")], { reports: 2 });
|
|
39
|
+
await program.onStart!({ ...start, embedded: false, count: 3 }, context);
|
|
40
|
+
assert.deepEqual(context.finished, [{ result: { actors: [] }, summary: "No other participants yet." }]);
|
|
41
|
+
assert.deepEqual(context.state.read(), { reports: 3 });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("an ordinary message is refused", async () => {
|
|
45
|
+
const { context } = roster([]);
|
|
46
|
+
await assert.rejects(async () => program.onInput!({ id: "input-1", content: "hello", artifactIds: [], sourceEventIds: [], subscriptionId: null, event: null }, context), /answers only starts/);
|
|
47
|
+
});
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"revision": "5e18b249f3c8b53b61820ef05da59823d58163c6962e6d836dcb37c05034aad0",
|
|
36
|
-
"sourceRevision": "
|
|
36
|
+
"sourceRevision": "e69f899d1733ba54341bfc2fd8c6adbf6025126a4b21a74bdd8206378e86b87e",
|
|
37
37
|
"server": "server/index.js",
|
|
38
38
|
"web": {
|
|
39
39
|
"entry": "web/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"web": {}
|
|
24
24
|
},
|
|
25
25
|
"revision": "e3bb513053f6385f9d78d314d28302324095a5163c4e1563df6fc8b3251305f7",
|
|
26
|
-
"sourceRevision": "
|
|
26
|
+
"sourceRevision": "7df3be99d8024c7878a0afe2bcd698909b6389f4484d98f84a0e3bdead954ab4",
|
|
27
27
|
"server": "server/index.js",
|
|
28
28
|
"exports": {
|
|
29
29
|
"server": {},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"web": {}
|
|
26
26
|
},
|
|
27
27
|
"revision": "007ee50ab186e3070930f23e9795210fa36c723365657325d5440cc2f0b81d60",
|
|
28
|
-
"sourceRevision": "
|
|
28
|
+
"sourceRevision": "1ce434ee7a1752f72e3d7160d895130948b8bcd5bba466f5555fff6ff278cd19",
|
|
29
29
|
"server": "server/index.js",
|
|
30
30
|
"exports": {
|
|
31
31
|
"server": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
}
|
|
138
138
|
},
|
|
139
139
|
"revision": "db9370b7b3449c44be49986b074806351b857c430963aa878e209d2d5c9ba4f8",
|
|
140
|
-
"sourceRevision": "
|
|
140
|
+
"sourceRevision": "f91d81de973c9c7b46f1882a8cb4f067fbdf72c2e7617f24f8865f92d9ed05bc",
|
|
141
141
|
"server": "server/index.js",
|
|
142
142
|
"web": {
|
|
143
143
|
"entry": "web/index.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schlenkr/ragents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "RAgents host: server, engine, plugins and tools without a source checkout",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"lucide-react": "1.46.0",
|
|
56
56
|
"partial-json": "0.1.7",
|
|
57
57
|
"playwright-core": "1.61.1",
|
|
58
|
-
"quassel": "0.4.
|
|
58
|
+
"quassel": "0.4.2",
|
|
59
59
|
"react": "19.2.8",
|
|
60
60
|
"react-diff-view": "3.3.3",
|
|
61
61
|
"react-dom": "19.2.8",
|
|
@@ -70,6 +70,6 @@
|
|
|
70
70
|
"yaml": "2.9.0"
|
|
71
71
|
},
|
|
72
72
|
"ragents": {
|
|
73
|
-
"hostVersion": "
|
|
73
|
+
"hostVersion": "9d43afb1f899a9b2bf01b46d9173d1ea901c9088"
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -8,10 +8,14 @@ export const capabilityNames = [
|
|
|
8
8
|
"workspace.use",
|
|
9
9
|
"execution.stopOwned",
|
|
10
10
|
"run.configure",
|
|
11
|
+
"script.start",
|
|
11
12
|
] as const;
|
|
12
13
|
|
|
13
14
|
export type CapabilityName = (typeof capabilityNames)[number];
|
|
14
15
|
|
|
16
|
+
/** Whoever gets one of these from the owner holds it without passing it on, so it never reaches the agents they spawn. */
|
|
17
|
+
export const firstHandCapabilities: readonly CapabilityName[] = ["script.start"];
|
|
18
|
+
|
|
15
19
|
export const isCapabilityName = (value: unknown): value is CapabilityName =>
|
|
16
20
|
typeof value === "string" && (capabilityNames as readonly string[]).includes(value);
|
|
17
21
|
|
|
@@ -32,6 +32,7 @@ export {
|
|
|
32
32
|
SessionMetadataContributionRegistry,
|
|
33
33
|
SkillContributionRegistry,
|
|
34
34
|
StartEntryContributionRegistry,
|
|
35
|
+
ActorPackageContributionRegistry,
|
|
35
36
|
StartOptionContributionRegistry,
|
|
36
37
|
StorageRegistry,
|
|
37
38
|
ToolContributionRegistry,
|
|
@@ -123,10 +124,11 @@ export {
|
|
|
123
124
|
} from "./drivers/types.ts";
|
|
124
125
|
export * from "./domain/model.ts";
|
|
125
126
|
export { isPortableId, isRunId } from "./domain/portable-id.ts";
|
|
126
|
-
export { capabilityNames, isCapabilityName, type CapabilityName } from "./domain/vocabulary.ts";
|
|
127
|
+
export { capabilityNames, firstHandCapabilities, isCapabilityName, type CapabilityName } from "./domain/vocabulary.ts";
|
|
127
128
|
export { DirectoryArtifactContents, MemoryArtifactContents, type ArtifactContents } from "./runtime/artifacts.ts";
|
|
128
129
|
export type { CommandContext } from "./runtime/command.ts";
|
|
129
130
|
export { DomainError } from "./runtime/domain-error.ts";
|
|
131
|
+
export { inheritedGrants } from "./runtime/guards.ts";
|
|
130
132
|
export { throwFailures, throwRejected } from "./runtime/failures.ts";
|
|
131
133
|
export type { JournalEvent } from "./domain/events.ts";
|
|
132
134
|
export { Journal, journalFormatVersion, type CommandRecord, type JournalLoadFailure } from "./runtime/journal.ts";
|
|
@@ -52,6 +52,8 @@ import type {
|
|
|
52
52
|
SkillContribution,
|
|
53
53
|
RunScriptPackage,
|
|
54
54
|
StartEntryContribution,
|
|
55
|
+
ActorPackageContribution,
|
|
56
|
+
ActorProgramFile,
|
|
55
57
|
StartOptionContext,
|
|
56
58
|
StartOptionContribution,
|
|
57
59
|
ScriptContribution,
|
|
@@ -442,6 +444,7 @@ export class SkillContributionRegistry {
|
|
|
442
444
|
const SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
|
|
443
445
|
const GUIDE_ID = /^[a-z0-9][a-z0-9.-]*$/;
|
|
444
446
|
const SCRIPT_HANDLE = /^[a-z0-9][a-z0-9-]*$/;
|
|
447
|
+
const ACTOR_PACKAGE_NAME = /^[a-z][a-z0-9-]{0,63}$/;
|
|
445
448
|
|
|
446
449
|
const requireText = (entry: { id: unknown }, value: unknown, field: string): void => {
|
|
447
450
|
if (typeof value !== "string" || !value.trim()) {
|
|
@@ -456,33 +459,38 @@ const assertKnownFields = (entry: { id: unknown }, value: object, fields: readon
|
|
|
456
459
|
}
|
|
457
460
|
};
|
|
458
461
|
|
|
459
|
-
const validateProgramFiles = (
|
|
462
|
+
const validateProgramFiles = (owner: string, files: unknown): void => {
|
|
460
463
|
if (!Array.isArray(files) || files.length === 0)
|
|
461
|
-
throw new Error(
|
|
464
|
+
throw new Error(`${owner}: files needs package files`);
|
|
462
465
|
const names = new Set<string>();
|
|
463
466
|
for (const file of files) {
|
|
464
467
|
if (typeof file !== "object" || file === null || typeof file.path !== "string" || typeof file.content !== "string")
|
|
465
|
-
throw new Error(
|
|
466
|
-
assertKnownFields(
|
|
468
|
+
throw new Error(`${owner}: every file needs path and content`);
|
|
469
|
+
assertKnownFields({ id: owner }, file, ["path", "content"], "Package file of");
|
|
467
470
|
if (!file.path || file.path.includes("\\") || file.path.includes("\0") || path.posix.isAbsolute(file.path)
|
|
468
471
|
|| file.path.split("/").some((part: string) => !part || part === "." || part === ".."))
|
|
469
|
-
throw new Error(
|
|
470
|
-
if (names.has(file.path)) throw new Error(
|
|
472
|
+
throw new Error(`${owner}: invalid package path ${file.path}`);
|
|
473
|
+
if (names.has(file.path)) throw new Error(`${owner}: file ${file.path} is duplicated`);
|
|
471
474
|
names.add(file.path);
|
|
472
475
|
}
|
|
473
|
-
if (!names.has("package.json")) throw new Error(
|
|
476
|
+
if (!names.has("package.json")) throw new Error(`${owner}: package.json is missing`);
|
|
474
477
|
};
|
|
475
478
|
|
|
476
479
|
const validateScriptPackage = (entry: StartEntryContribution, script: unknown): void => {
|
|
477
480
|
if (typeof script !== "object" || script === null)
|
|
478
481
|
throw new Error(`Template ${entry.id} has no run script package`);
|
|
479
|
-
assertKnownFields(entry, script, ["handle", "coordinator", "files", "programs"], "Run script");
|
|
482
|
+
assertKnownFields(entry, script, ["handle", "coordinator", "embeddable", "sharedPrograms", "files", "programs"], "Run script");
|
|
480
483
|
const value = script as Record<string, unknown>;
|
|
481
484
|
if (typeof value.handle !== "string" || !SCRIPT_HANDLE.test(value.handle))
|
|
482
485
|
throw new Error(`Run script ${entry.id}: handle must be a handle like roundtable (lowercase letters, digits, hyphen)`);
|
|
483
486
|
if (typeof value.coordinator !== "boolean")
|
|
484
487
|
throw new Error(`Run script ${entry.id}: coordinator must be true or false`);
|
|
485
|
-
|
|
488
|
+
if (value.embeddable !== undefined && typeof value.embeddable !== "boolean")
|
|
489
|
+
throw new Error(`Run script ${entry.id}: embeddable must be true or false`);
|
|
490
|
+
const shared = value.sharedPrograms;
|
|
491
|
+
if (shared !== undefined && (!Array.isArray(shared) || shared.some((name) => typeof name !== "string" || !ACTOR_PACKAGE_NAME.test(name)) || new Set(shared).size !== shared.length))
|
|
492
|
+
throw new Error(`Run script ${entry.id}: sharedPrograms must name each shared actor package once`);
|
|
493
|
+
validateProgramFiles(`Run script ${entry.id}`, value.files);
|
|
486
494
|
if (!Array.isArray(value.programs)) throw new Error(`Run script ${entry.id}: programs must be a list`);
|
|
487
495
|
const names = new Set<string>();
|
|
488
496
|
for (const program of value.programs) {
|
|
@@ -492,7 +500,7 @@ const validateScriptPackage = (entry: StartEntryContribution, script: unknown):
|
|
|
492
500
|
if (program.name === value.handle || names.has(program.name))
|
|
493
501
|
throw new Error(`Run script ${entry.id}: program ${program.name} is duplicated`);
|
|
494
502
|
names.add(program.name);
|
|
495
|
-
validateProgramFiles(entry
|
|
503
|
+
validateProgramFiles(`Run script ${entry.id}`, program.files);
|
|
496
504
|
}
|
|
497
505
|
};
|
|
498
506
|
|
|
@@ -555,6 +563,29 @@ const skillNameOf = (directory: string): string => directory.split(/[\\/]/).filt
|
|
|
555
563
|
const byOrderThenId = (left: { order?: number; id: string }, right: { order?: number; id: string }): number =>
|
|
556
564
|
(left.order ?? 0) - (right.order ?? 0) || left.id.localeCompare(right.id);
|
|
557
565
|
|
|
566
|
+
/** Actor packages a plugin shares with the run scripts of the profile; one name, one package. */
|
|
567
|
+
export class ActorPackageContributionRegistry {
|
|
568
|
+
readonly #packages = new ContributionRegistry<ActorPackageContribution & { id: string }>("Shared actor package");
|
|
569
|
+
|
|
570
|
+
register(owner: string, packages: readonly ActorPackageContribution[]): void {
|
|
571
|
+
for (const entry of packages) {
|
|
572
|
+
if (typeof entry.name !== "string" || !ACTOR_PACKAGE_NAME.test(entry.name))
|
|
573
|
+
throw new Error(`Shared actor package ${String(entry.name)} of ${owner}: the name must be a package name like notes (lowercase letters, digits, hyphen)`);
|
|
574
|
+
validateProgramFiles(`Shared actor package ${entry.name}`, entry.files);
|
|
575
|
+
}
|
|
576
|
+
this.#packages.register(owner, packages.map((entry) => ({ id: entry.name, name: entry.name, files: entry.files })));
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
get(name: string): { pluginId: string; files: readonly ActorProgramFile[] } | undefined {
|
|
580
|
+
const found = this.#packages.entries().find(({ value }) => value.name === name);
|
|
581
|
+
return found ? { pluginId: found.owner, files: found.value.files } : undefined;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
names(): readonly string[] {
|
|
585
|
+
return this.#packages.entries().map(({ value }) => value.name);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
558
589
|
/** Skills with a start prompt and executable run scripts share one registry. */
|
|
559
590
|
export class StartEntryContributionRegistry {
|
|
560
591
|
readonly #entries = new ContributionRegistry<StartEntryContribution>("Template");
|
|
@@ -614,6 +645,24 @@ export class StartEntryContributionRegistry {
|
|
|
614
645
|
return this.describe().find((candidate) => candidate.id === entryId);
|
|
615
646
|
}
|
|
616
647
|
|
|
648
|
+
/** Names share one namespace per run: a shared package is neither a script's handle nor its bundled program, and every name a script needs exists. */
|
|
649
|
+
assertSharedPrograms(packages: ActorPackageContributionRegistry): void {
|
|
650
|
+
for (const { value } of this.#entries.entries()) {
|
|
651
|
+
if (value.action !== "script") continue;
|
|
652
|
+
const script = value.script;
|
|
653
|
+
const clash = [script.handle, ...script.programs.map((program) => program.name)].find((name) => packages.get(name));
|
|
654
|
+
if (clash !== undefined) {
|
|
655
|
+
throw new Error(`Run script ${value.id} uses the name ${clash}, which is also the shared actor package of ${packages.get(clash)!.pluginId}; `
|
|
656
|
+
+ "run script handles, their bundled programs and shared packages share one namespace per run");
|
|
657
|
+
}
|
|
658
|
+
const missing = (script.sharedPrograms ?? []).filter((name) => !packages.get(name));
|
|
659
|
+
if (missing.length > 0) {
|
|
660
|
+
throw new Error(`Run script ${value.id} needs the shared actor packages ${missing.join(", ")}, which no plugin of this profile provides`
|
|
661
|
+
+ (packages.names().length > 0 ? `; shared are ${packages.names().join(", ")}` : ""));
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
617
666
|
/** The run script behind a script template; undefined for unknown ids and templates of another action. */
|
|
618
667
|
scriptPackage(entryId: string): (RunScriptPackage & { entry: PublicStartEntry }) | undefined {
|
|
619
668
|
const found = this.#entries.entries().find(({ value }) => value.id === entryId);
|
|
@@ -1164,6 +1213,7 @@ export class PluginHost {
|
|
|
1164
1213
|
readonly prompts = new PromptContributionRegistry(this.runConditions);
|
|
1165
1214
|
readonly skills = new SkillContributionRegistry(this.runConditions);
|
|
1166
1215
|
readonly startEntries = new StartEntryContributionRegistry();
|
|
1216
|
+
readonly actorPackages = new ActorPackageContributionRegistry();
|
|
1167
1217
|
readonly profiles = new ProfileContributionRegistry();
|
|
1168
1218
|
readonly script = new ScriptContributionRegistry();
|
|
1169
1219
|
readonly lifecycle = new LifecycleContributionRegistry();
|
|
@@ -1220,6 +1270,7 @@ export class PluginHost {
|
|
|
1220
1270
|
sessionMetadata: (...entries) => this.sessionMetadata.register(manifest.id, entries),
|
|
1221
1271
|
skills: (...entries) => this.skills.register(manifest.id, entries),
|
|
1222
1272
|
startEntries: (...entries) => this.startEntries.register(manifest.id, entries),
|
|
1273
|
+
actorPackages: (...entries) => this.actorPackages.register(manifest.id, entries),
|
|
1223
1274
|
startOptions: (...entries) => this.startOptions.register(manifest.id, entries),
|
|
1224
1275
|
accessProjections: (...entries) => this.accessProjections.register(manifest.id, entries),
|
|
1225
1276
|
functions: (...entries) => this.tools.registerFunctions(manifest.id, entries),
|
|
@@ -1240,6 +1291,7 @@ export class PluginHost {
|
|
|
1240
1291
|
}
|
|
1241
1292
|
}
|
|
1242
1293
|
this.startEntries.assertFixedStartOptionsKnown(this.startOptions);
|
|
1294
|
+
this.startEntries.assertSharedPrograms(this.actorPackages);
|
|
1243
1295
|
const defaultStartEntry = this.#defaultStartEntry;
|
|
1244
1296
|
if (defaultStartEntry !== undefined) {
|
|
1245
1297
|
const entries = this.startEntries.describe().map((entry) => entry.id);
|
|
@@ -242,10 +242,20 @@ export interface BundledActorProgram {
|
|
|
242
242
|
export interface RunScriptPackage {
|
|
243
243
|
handle: string;
|
|
244
244
|
coordinator: boolean;
|
|
245
|
+
/** Whether the script may also start inside a run that is already running; without it, only a new run. */
|
|
246
|
+
embeddable?: boolean;
|
|
247
|
+
/** Shared actor packages of the profile that the host copies into the run before the setup, by name. */
|
|
248
|
+
sharedPrograms?: readonly string[];
|
|
245
249
|
files: readonly ActorProgramFile[];
|
|
246
250
|
programs: readonly BundledActorProgram[];
|
|
247
251
|
}
|
|
248
252
|
|
|
253
|
+
/** An actor package that a plugin shares with the run scripts of the profile; its name is the package name in every run. */
|
|
254
|
+
export interface ActorPackageContribution {
|
|
255
|
+
name: string;
|
|
256
|
+
files: readonly ActorProgramFile[];
|
|
257
|
+
}
|
|
258
|
+
|
|
249
259
|
export type StartEntryContribution = StartEntryBase & (
|
|
250
260
|
| { action: "skill"; skill: string; category: string; prompt: string }
|
|
251
261
|
/** A run script may name a category of its own; without one the start pages group it as a run script. */
|
|
@@ -448,6 +458,7 @@ export interface PluginRegistration {
|
|
|
448
458
|
sessionMetadata: (...contributions: readonly SessionMetadataContribution[]) => void;
|
|
449
459
|
skills: (...contributions: readonly SkillContribution[]) => void;
|
|
450
460
|
startEntries: (...contributions: readonly StartEntryContribution[]) => void;
|
|
461
|
+
actorPackages: (...contributions: readonly ActorPackageContribution[]) => void;
|
|
451
462
|
startOptions: (...contributions: readonly StartOptionContribution[]) => void;
|
|
452
463
|
/** How accesses without runs.inspect see the states of this plugin and their chat events, per state id. */
|
|
453
464
|
accessProjections: (...contributions: readonly AccessProjectionContribution[]) => void;
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
Turn,
|
|
12
12
|
} from "../domain/model.ts";
|
|
13
13
|
import { actorByReference, handleKey } from "../domain/actor-reference.ts";
|
|
14
|
+
import { firstHandCapabilities } from "../domain/vocabulary.ts";
|
|
14
15
|
import { DomainError } from "./domain-error.ts";
|
|
15
16
|
|
|
16
17
|
export const clean = (value: string, name: string) => {
|
|
@@ -167,7 +168,7 @@ export const inheritedGrants = (
|
|
|
167
168
|
scope: grant.scope.kind === "run"
|
|
168
169
|
? { kind: "run" as const }
|
|
169
170
|
: { kind: "workspace" as const, path: grant.scope.path },
|
|
170
|
-
delegable:
|
|
171
|
+
delegable: !firstHandCapabilities.includes(grant.capability),
|
|
171
172
|
}));
|
|
172
173
|
};
|
|
173
174
|
|
|
@@ -51,9 +51,19 @@ const pool: PooledWorker[] = [];
|
|
|
51
51
|
const workerWaiters: WorkerWaiter[] = [];
|
|
52
52
|
let nextRequestId = 0;
|
|
53
53
|
|
|
54
|
+
const LOADER_FLAGS = ["--import", "--loader", "--experimental-loader", "--require", "-r"] as const;
|
|
55
|
+
|
|
56
|
+
/** Only the loader flags of the host (such as --import tsx); Node strips no types under node_modules, and debugger or memory flags stay behind. */
|
|
57
|
+
const loaderArguments = (execArgv: readonly string[]): readonly string[] =>
|
|
58
|
+
execArgv.flatMap((argument, index) => {
|
|
59
|
+
if (LOADER_FLAGS.some((flag) => argument.startsWith(`${flag}=`))) return [argument];
|
|
60
|
+
if (LOADER_FLAGS.some((flag) => argument === flag) && index + 1 < execArgv.length) return [argument, execArgv[index + 1]!];
|
|
61
|
+
return [];
|
|
62
|
+
});
|
|
63
|
+
|
|
54
64
|
const spawnWorker = (): PooledWorker => {
|
|
55
65
|
const worker = new Worker(new URL("./compiler-worker.ts", import.meta.url), {
|
|
56
|
-
execArgv: [],
|
|
66
|
+
execArgv: [...loaderArguments(process.execArgv)],
|
|
57
67
|
name: "ragents-typescript-compiler",
|
|
58
68
|
resourceLimits: COMPILER_RESOURCE_LIMITS,
|
|
59
69
|
});
|
|
@@ -3,6 +3,7 @@ import type { PluginHost, RAgentsPlugin } from "@ragents/engine";
|
|
|
3
3
|
import type { PluginModule } from "@ragents/host/plugin-support/plugin-module.js";
|
|
4
4
|
import { runtimeProviderToken, runGuardToken } from "@ragents/host/ragents/host-services.js";
|
|
5
5
|
import { askServiceToken } from "@ragents/plugins/ragents.ask/server/contract.js";
|
|
6
|
+
import { surfacePlacementToken } from "@ragents/plugins/ragents.orchestration/server/contract.js";
|
|
6
7
|
import { agentToolsFrom } from "./agent-tools.js";
|
|
7
8
|
import { createActorProgramMethods } from "./methods.js";
|
|
8
9
|
import { createMiniAppFrameRoutes, miniAppsApiPrefix } from "./routes.js";
|
|
@@ -26,6 +27,8 @@ const actorProgramsPlugin = (pluginHost: PluginHost): RAgentsPlugin => ({
|
|
|
26
27
|
const script = pluginHost.startEntries.scriptPackage(entryId);
|
|
27
28
|
return !script ? undefined : script.handle === name ? script.files : script.programs.find((program) => program.name === name)?.files;
|
|
28
29
|
},
|
|
30
|
+
sharedPackage: (name) => pluginHost.actorPackages.get(name),
|
|
31
|
+
placeView: (context, runId, entity) => { host.service(surfacePlacementToken).place(context, runId, { entity }); },
|
|
29
32
|
});
|
|
30
33
|
host.provide(actorProgramsToken, runtime);
|
|
31
34
|
const diagnostics = createProjectDiagnostics({
|