@jskit-ai/assistant-runtime 0.2.23 → 0.2.25
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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- The assistant surface pattern's icon is `$smartToy`, and the fixtures render with `@jskit-ai/material-web`.
|
|
5
6
|
- Changing an assistant's instructions needs `assistant.settings.update` on a settings surface that requires neither a workspace nor the console owner (it needed only a signed-in user), still `workspace.settings.update` on a workspace surface and the console owner on a console-owner surface. `assistantServer.<surface>.settingsUpdatePermission` names another permission, or `{ require: "authenticated" }` to keep the old behaviour. A refusal is `assistant.runtime.settings.updateForbidden` (403).
|
|
6
7
|
|
|
7
8
|
### New message keys (1)
|
|
@@ -3,8 +3,9 @@ import { createRouter, createWebHistory } from "vue-router";
|
|
|
3
3
|
import { createVuetify } from "vuetify";
|
|
4
4
|
import * as components from "vuetify/components";
|
|
5
5
|
import * as directives from "vuetify/directives";
|
|
6
|
-
import { aliases, mdi } from "vuetify/iconsets/mdi-svg";
|
|
7
6
|
import "vuetify/styles";
|
|
7
|
+
import "@jskit-ai/material-web/client/material.css";
|
|
8
|
+
import { createMaterialVuetifyOptions } from "@jskit-ai/material-web/client";
|
|
8
9
|
import App from "./App.vue";
|
|
9
10
|
import { createWebPlacementRuntime } from "../../../shell-web/src/client/placement/runtime.js";
|
|
10
11
|
import { createFixtureSocket } from "./socket.js";
|
|
@@ -69,7 +70,6 @@ if (new URLSearchParams(window.location.search).has("applicationDefaults")) {
|
|
|
69
70
|
app.provide("jskit.shell-web.runtime.web-placement.client", placement);
|
|
70
71
|
app.provide("jskit.realtime.runtime.client.socket", socket);
|
|
71
72
|
app.provide("fixture", { placement, socket });
|
|
72
|
-
app.use(router).use(createVuetify({
|
|
73
|
-
icons: { defaultSet: "mdi", aliases, sets: { mdi } } }));
|
|
73
|
+
app.use(router).use(createVuetify({ components, directives, ...createMaterialVuetifyOptions() }));
|
|
74
74
|
await router.isReady();
|
|
75
75
|
app.mount("#app");
|
|
@@ -4,8 +4,9 @@ import { VueQueryPlugin } from "@tanstack/vue-query";
|
|
|
4
4
|
import { createVuetify } from "vuetify";
|
|
5
5
|
import * as components from "vuetify/components";
|
|
6
6
|
import * as directives from "vuetify/directives";
|
|
7
|
-
import { aliases, mdi } from "vuetify/iconsets/mdi-svg";
|
|
8
7
|
import "vuetify/styles";
|
|
8
|
+
import "@jskit-ai/material-web/client/material.css";
|
|
9
|
+
import { createMaterialVuetifyOptions } from "@jskit-ai/material-web/client";
|
|
9
10
|
import App from "./App.vue";
|
|
10
11
|
import { createWebPlacementRuntime } from "../../../shell-web/src/client/placement/runtime.js";
|
|
11
12
|
import { silentLogger } from "@jskit-ai/kernel/shared/support/silentLogger";
|
|
@@ -27,6 +28,6 @@ placement.setContext({ user: { id: "1" }, surfaceConfig: {
|
|
|
27
28
|
app.provide("jskit.shell-web.runtime.web-placement.client", placement);
|
|
28
29
|
app.provide("jskit.workspaces.web.scope-support", { readRouteScope: ({ route }) => ({ workspaceSlug: route.query.workspace || "alpha" }) });
|
|
29
30
|
app.use(router).use(VueQueryPlugin, { queryClientConfig: { defaultOptions: { queries: { retry: false } } } });
|
|
30
|
-
app.use(createVuetify({
|
|
31
|
+
app.use(createVuetify({ components, directives, ...createMaterialVuetifyOptions() }));
|
|
31
32
|
await router.isReady();
|
|
32
33
|
app.mount("#app");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/assistant-runtime",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test --test-concurrency=1"
|
|
@@ -14,19 +14,19 @@
|
|
|
14
14
|
"./locales/en.json": "./locales/en.json"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@jskit-ai/assistant-core": "0.2.
|
|
17
|
+
"@jskit-ai/assistant-core": "0.2.23",
|
|
18
18
|
"json-rest-schema": "^1.0.17"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
|
-
"@jskit-ai/http-runtime": "0.2.
|
|
22
|
-
"@jskit-ai/http-web": "0.2.
|
|
23
|
-
"@jskit-ai/kernel": "0.2.
|
|
24
|
-
"@jskit-ai/realtime": "0.2.
|
|
25
|
-
"@jskit-ai/shell-web": "0.2.
|
|
21
|
+
"@jskit-ai/http-runtime": "0.2.10",
|
|
22
|
+
"@jskit-ai/http-web": "0.2.17",
|
|
23
|
+
"@jskit-ai/kernel": "0.2.10",
|
|
24
|
+
"@jskit-ai/realtime": "0.2.15",
|
|
25
|
+
"@jskit-ai/shell-web": "0.2.12",
|
|
26
26
|
"@tanstack/vue-query": "^5.90.5",
|
|
27
27
|
"vue": "^3.5.13",
|
|
28
28
|
"vuetify": "^4.0.0",
|
|
29
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
29
|
+
"@jskit-ai/database-runtime": "0.1.259"
|
|
30
30
|
},
|
|
31
31
|
"description": "Capability-based assistant runtime with per-surface chat, transcripts, settings, and action tools.",
|
|
32
32
|
"jskit": {
|
|
@@ -126,5 +126,8 @@
|
|
|
126
126
|
"@jskit-ai/database-runtime": {
|
|
127
127
|
"optional": true
|
|
128
128
|
}
|
|
129
|
+
},
|
|
130
|
+
"devDependencies": {
|
|
131
|
+
"@jskit-ai/material-web": "0.1.1"
|
|
129
132
|
}
|
|
130
133
|
}
|
|
@@ -146,10 +146,15 @@ test("optional goal controls follow declared command semantics and budgets witho
|
|
|
146
146
|
await f.notify("chat:1");
|
|
147
147
|
await f.primary.getByRole("button", { name: "Set goal", exact: true }).click();
|
|
148
148
|
const objective = budgets ? "Finish with a bounded budget" : "Finish without a budget";
|
|
149
|
-
|
|
149
|
+
const objectiveField = f.page.getByRole("textbox", { name: "Goal objective" });
|
|
150
150
|
const budget = f.page.getByRole("spinbutton", { name: "Token budget (optional)" });
|
|
151
|
-
|
|
151
|
+
// The second round's Set goal button is already there, so wait until the notified commands reach the form (its
|
|
152
|
+
// budget field follows them) before typing: a reread landing mid-typing remounts the form.
|
|
153
|
+
await expect(objectiveField).toBeVisible();
|
|
154
|
+
if (budgets) await expect(budget).toBeVisible();
|
|
152
155
|
else await expect(budget).toHaveCount(0);
|
|
156
|
+
await objectiveField.fill(objective);
|
|
157
|
+
if (budgets) await budget.fill("1000");
|
|
153
158
|
const start = f.page.getByRole("button", { name: "Start goal", exact: true });
|
|
154
159
|
await expect(start).toBeEnabled();
|
|
155
160
|
await start.click();
|
|
@@ -199,7 +204,11 @@ test("a paused goal stays cancellable while a message is sending or its delivery
|
|
|
199
204
|
await f.primary.getByRole("button", { name: "Set goal", exact: true }).click();
|
|
200
205
|
await f.page.getByRole("textbox", { name: "Goal objective" }).fill(objective);
|
|
201
206
|
await f.page.getByRole("button", { name: "Start goal", exact: true }).click();
|
|
202
|
-
|
|
207
|
+
// As in the commands test: the running goal can show before Start has closed its menu, so wait for it to close.
|
|
208
|
+
const running = f.primary.getByRole("button", { name: "Goal running", exact: true });
|
|
209
|
+
await expect(running).toBeVisible();
|
|
210
|
+
await expect(running).toHaveAttribute("aria-expanded", "false");
|
|
211
|
+
await running.click();
|
|
203
212
|
await f.page.getByRole("button", { name: "Pause goal", exact: true }).click();
|
|
204
213
|
await expect(f.primary.getByRole("button", { name: "Goal paused", exact: true })).toBeVisible();
|
|
205
214
|
await f.page.keyboard.press("Escape");
|
|
@@ -459,7 +468,9 @@ test("a Start accepted behind the running turn stays Starting… until its goal
|
|
|
459
468
|
// A Start the conversation finishes without says so and keeps its objective.
|
|
460
469
|
await control("Goal running").click();
|
|
461
470
|
await f.page.getByRole("button", { name: "Cancel goal", exact: true }).click();
|
|
462
|
-
|
|
471
|
+
// A successful Cancel closes the menu, as Start does; Set goal opens it again.
|
|
472
|
+
await expect(control("Set goal")).toHaveAttribute("aria-expanded", "false");
|
|
473
|
+
await control("Set goal").click();
|
|
463
474
|
await objective.fill("Never takes effect");
|
|
464
475
|
await start.click();
|
|
465
476
|
await expect.poll(async () => (await starts()).length).toBe(2);
|
|
@@ -1653,6 +1664,10 @@ test("canonical model controls use the supplied reactive owner and disappear wit
|
|
|
1653
1664
|
assert.deepEqual(await f.page.evaluate(() => window.conversationFixture.modelState()), {
|
|
1654
1665
|
selected: "large", applied: "large", saving: false, selections: ["large"]
|
|
1655
1666
|
});
|
|
1667
|
+
// A finished Apply closes the menu. Reopen it once it has finished closing: Vuetify 4.3 ignores a click on the
|
|
1668
|
+
// activator while the menu's close transition still runs.
|
|
1669
|
+
await expect(choose).toHaveAttribute("aria-expanded", "false");
|
|
1670
|
+
await expect(f.page.locator(".assistant-model-control")).toBeHidden();
|
|
1656
1671
|
await choose.click();
|
|
1657
1672
|
await f.page.evaluate(() => window.conversationFixture.modelError("Reconnect the application catalogue."));
|
|
1658
1673
|
await expect(f.page.getByText("Reconnect the application catalogue.", { exact: true })).toBeVisible();
|