@jskit-ai/assistant 0.1.38 → 0.1.39
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/package.descriptor.mjs +84 -319
- package/package.json +2 -2
- package/src/server/buildTemplateContext.js +39 -14
- package/templates/src/pages/assistant/index.vue +2 -2
- package/templates/src/pages/settings/assistant/index.vue +7 -0
- package/test/buildTemplateContext.test.js +42 -27
- package/test/packageDescriptor.test.js +26 -55
- package/test/templateContracts.test.js +8 -6
- package/templates/migrations/assistant_config_initial.cjs +0 -25
- package/templates/migrations/assistant_transcripts_initial.cjs +0 -56
- package/templates/src/local-package/client/components/AssistantSettingsClientElement.vue +0 -88
- package/templates/src/local-package/client/components/AssistantSurfaceClientElement.vue +0 -10
- package/templates/src/local-package/client/composables/useAssistantRuntime.js +0 -754
- package/templates/src/local-package/client/index.js +0 -4
- package/templates/src/local-package/client/providers/AssistantClientProvider.js +0 -16
- package/templates/src/local-package/package.descriptor.mjs +0 -85
- package/templates/src/local-package/package.json +0 -11
- package/templates/src/local-package/server/AssistantProvider.js +0 -143
- package/templates/src/local-package/server/actionIds.js +0 -9
- package/templates/src/local-package/server/actions.js +0 -183
- package/templates/src/local-package/server/registerRoutes.js +0 -296
- package/templates/src/local-package/server/repositories/assistantConfigRepository.js +0 -141
- package/templates/src/local-package/server/repositories/conversationsRepository.js +0 -240
- package/templates/src/local-package/server/repositories/messagesRepository.js +0 -166
- package/templates/src/local-package/server/services/assistantConfigService.js +0 -90
- package/templates/src/local-package/server/services/chatService.js +0 -995
- package/templates/src/local-package/server/services/transcriptService.js +0 -308
- package/templates/src/local-package/shared/assistantRuntimeConfig.js +0 -13
- package/templates/src/local-package/shared/index.js +0 -1
|
@@ -22,7 +22,8 @@ async function withTempApp(run) {
|
|
|
22
22
|
app: { id: "app", enabled: true, requiresWorkspace: false, accessPolicyId: "authenticated" },
|
|
23
23
|
admin: { id: "admin", enabled: true, requiresWorkspace: true, accessPolicyId: "workspace_member" },
|
|
24
24
|
console: { id: "console", enabled: true, requiresWorkspace: false, accessPolicyId: "console_owner" }
|
|
25
|
-
}
|
|
25
|
+
},
|
|
26
|
+
assistantSurfaces: {}
|
|
26
27
|
};
|
|
27
28
|
`,
|
|
28
29
|
"utf8"
|
|
@@ -45,12 +46,12 @@ async function withTempApp(run) {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
test("buildTemplateContext derives
|
|
49
|
+
test("buildTemplateContext derives per-surface placeholders from explicit surfaces", async () => {
|
|
49
50
|
await withTempApp(async (appRoot) => {
|
|
50
51
|
const context = await buildTemplateContext({
|
|
51
52
|
appRoot,
|
|
52
53
|
options: {
|
|
53
|
-
|
|
54
|
+
surface: "app",
|
|
54
55
|
"settings-surface": "console",
|
|
55
56
|
"config-scope": "global",
|
|
56
57
|
placement: "shell-layout:primary-menu",
|
|
@@ -58,55 +59,69 @@ test("buildTemplateContext derives runtime, settings, and table placeholders fro
|
|
|
58
59
|
}
|
|
59
60
|
});
|
|
60
61
|
|
|
61
|
-
assert.equal(context.
|
|
62
|
+
assert.equal(context.__ASSISTANT_SURFACE_ID__, "app");
|
|
62
63
|
assert.equal(context.__ASSISTANT_SETTINGS_SURFACE_ID__, "console");
|
|
63
|
-
assert.equal(context.__ASSISTANT_RUNTIME_SURFACE_REQUIRES_WORKSPACE__, "false");
|
|
64
|
-
assert.equal(context.__ASSISTANT_SETTINGS_SURFACE_REQUIRES_WORKSPACE__, "false");
|
|
65
|
-
assert.equal(context.__ASSISTANT_SETTINGS_SURFACE_REQUIRES_CONSOLE_OWNER__, "true");
|
|
66
64
|
assert.equal(context.__ASSISTANT_CONFIG_SCOPE__, "global");
|
|
67
65
|
assert.equal(context.__ASSISTANT_SETTINGS_HOST__, "console-settings");
|
|
68
|
-
assert.equal(context.
|
|
69
|
-
assert.equal(context.__ASSISTANT_MESSAGES_TABLE__, "assistant_app_messages");
|
|
66
|
+
assert.equal(context.__ASSISTANT_AI_CONFIG_PREFIX__, "APP_ASSISTANT");
|
|
70
67
|
assert.equal(context.__ASSISTANT_MENU_PLACEMENT_HOST__, "shell-layout");
|
|
71
68
|
assert.equal(context.__ASSISTANT_MENU_PLACEMENT_POSITION__, "primary-menu");
|
|
72
69
|
assert.equal(context.__ASSISTANT_MENU_LABEL__, "Copilot");
|
|
70
|
+
assert.equal(context.__ASSISTANT_SETTINGS_MENU_WORKSPACE_SUFFIX__, "/settings/assistant");
|
|
71
|
+
assert.equal(context.__ASSISTANT_SETTINGS_MENU_NON_WORKSPACE_SUFFIX__, "/settings/assistant");
|
|
73
72
|
});
|
|
74
73
|
});
|
|
75
74
|
|
|
76
|
-
test("buildTemplateContext rejects workspace config scope for non-workspace
|
|
75
|
+
test("buildTemplateContext rejects workspace config scope for a non-workspace assistant surface", async () => {
|
|
77
76
|
await withTempApp(async (appRoot) => {
|
|
78
77
|
await assert.rejects(
|
|
79
78
|
() =>
|
|
80
79
|
buildTemplateContext({
|
|
81
80
|
appRoot,
|
|
82
81
|
options: {
|
|
83
|
-
|
|
82
|
+
surface: "app",
|
|
84
83
|
"settings-surface": "console",
|
|
85
84
|
"config-scope": "workspace",
|
|
86
85
|
placement: "shell-layout:primary-menu"
|
|
87
86
|
}
|
|
88
87
|
}),
|
|
89
|
-
/config-scope "workspace" requires
|
|
88
|
+
/config-scope "workspace" requires surface "app" with requiresWorkspace=true/
|
|
90
89
|
);
|
|
91
90
|
});
|
|
92
91
|
});
|
|
93
92
|
|
|
94
|
-
test("buildTemplateContext
|
|
93
|
+
test("buildTemplateContext rejects duplicate assistant surfaces already configured in public config", async () => {
|
|
95
94
|
await withTempApp(async (appRoot) => {
|
|
96
|
-
|
|
97
|
-
appRoot,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
await writeFile(
|
|
96
|
+
path.join(appRoot, "config", "public.js"),
|
|
97
|
+
`export const config = {
|
|
98
|
+
surfaceDefinitions: {
|
|
99
|
+
app: { id: "app", enabled: true, requiresWorkspace: false, accessPolicyId: "authenticated" },
|
|
100
|
+
console: { id: "console", enabled: true, requiresWorkspace: false, accessPolicyId: "console_owner" }
|
|
101
|
+
},
|
|
102
|
+
assistantSurfaces: {
|
|
103
|
+
app: {
|
|
104
|
+
settingsSurfaceId: "console",
|
|
105
|
+
configScope: "global"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
`,
|
|
110
|
+
"utf8"
|
|
111
|
+
);
|
|
105
112
|
|
|
106
|
-
assert.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
await assert.rejects(
|
|
114
|
+
() =>
|
|
115
|
+
buildTemplateContext({
|
|
116
|
+
appRoot,
|
|
117
|
+
options: {
|
|
118
|
+
surface: "app",
|
|
119
|
+
"settings-surface": "console",
|
|
120
|
+
"config-scope": "global",
|
|
121
|
+
placement: "shell-layout:primary-menu"
|
|
122
|
+
}
|
|
123
|
+
}),
|
|
124
|
+
/already has an assistant configured/
|
|
125
|
+
);
|
|
111
126
|
});
|
|
112
127
|
});
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
2
|
import test from "node:test";
|
|
5
3
|
import descriptor from "../package.descriptor.mjs";
|
|
6
4
|
|
|
@@ -14,69 +12,42 @@ function findTextMutation(id) {
|
|
|
14
12
|
return mutations.find((entry) => String(entry?.id || "") === id) || null;
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
test("assistant descriptor exposes
|
|
15
|
+
test("assistant descriptor exposes per-surface generation options and depends on assistant-runtime", () => {
|
|
18
16
|
assert.equal(descriptor.kind, "generator");
|
|
19
|
-
assert.equal(descriptor.
|
|
20
|
-
assert.equal(descriptor.options?.["runtime-surface"]?.required, true);
|
|
17
|
+
assert.equal(descriptor.options?.surface?.required, true);
|
|
21
18
|
assert.equal(descriptor.options?.["settings-surface"]?.required, true);
|
|
22
19
|
assert.equal(descriptor.options?.["config-scope"]?.defaultValue, "global");
|
|
20
|
+
assert.equal(descriptor.options?.["ai-config-prefix"]?.required, false);
|
|
21
|
+
assert.deepEqual(descriptor.dependsOn, ["@jskit-ai/assistant-runtime"]);
|
|
23
22
|
});
|
|
24
23
|
|
|
25
|
-
test("assistant descriptor
|
|
26
|
-
const installMetadata = descriptor.metadata?.generatorSubcommands?.install || {};
|
|
27
|
-
const examples = Array.isArray(installMetadata.examples) ? installMetadata.examples : [];
|
|
28
|
-
const labels = examples.map((entry) => String(entry?.label || ""));
|
|
29
|
-
|
|
30
|
-
assert.equal(examples.length, 4);
|
|
31
|
-
assert.deepEqual(labels, [
|
|
32
|
-
"App runtime, console settings, global config",
|
|
33
|
-
"App runtime, app settings, global config",
|
|
34
|
-
"Workspace runtime, console settings, global config",
|
|
35
|
-
"Workspace runtime, workspace settings, workspace config"
|
|
36
|
-
]);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("assistant descriptor installs generated local runtime files instead of shipping a framework runtime", () => {
|
|
24
|
+
test("assistant descriptor generates only assistant runtime/settings pages and no local runtime package", () => {
|
|
40
25
|
const runtimePage = findFileMutation("assistant-page-runtime");
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
26
|
+
const settingsPageStandard = findFileMutation("assistant-page-settings-standard");
|
|
27
|
+
const settingsPageAdmin = findFileMutation("assistant-page-settings-admin");
|
|
28
|
+
const fileMutations = Array.isArray(descriptor?.mutations?.files) ? descriptor.mutations.files : [];
|
|
44
29
|
|
|
45
|
-
assert.equal(runtimePage?.toSurface, "${option:
|
|
30
|
+
assert.equal(runtimePage?.toSurface, "${option:surface|lower}");
|
|
46
31
|
assert.equal(runtimePage?.toSurfacePath, "assistant/index.vue");
|
|
47
|
-
assert.equal(
|
|
48
|
-
assert.equal(
|
|
49
|
-
assert.equal(
|
|
32
|
+
assert.equal(settingsPageStandard?.toSurfacePath, "settings/${option:settings-route-path|path}/index.vue");
|
|
33
|
+
assert.equal(settingsPageAdmin?.toSurfacePath, "workspace/settings/${option:settings-route-path|path}/index.vue");
|
|
34
|
+
assert.equal(fileMutations.length, 3);
|
|
50
35
|
});
|
|
51
36
|
|
|
52
|
-
test("assistant descriptor
|
|
37
|
+
test("assistant descriptor appends menu placement, settings menu placement, and per-surface config entries", () => {
|
|
53
38
|
const menuPlacement = findTextMutation("assistant-placement-menu");
|
|
54
|
-
const settingsPlacement = findTextMutation("assistant-settings-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
const settingsPlacement = findTextMutation("assistant-settings-menu-placement");
|
|
40
|
+
const publicConfig = findTextMutation("assistant-public-surface-config");
|
|
41
|
+
const serverConfig = findTextMutation("assistant-server-surface-config");
|
|
42
|
+
const envBlock = findTextMutation("assistant-ai-prefixed-env");
|
|
43
|
+
|
|
44
|
+
assert.match(String(menuPlacement?.value || ""), /assistant\.generated\.menu:\$\{option:surface\|lower\}/);
|
|
45
|
+
assert.match(String(menuPlacement?.value || ""), /surfaces: \["\$\{option:surface\|lower\}"\]/);
|
|
46
|
+
assert.match(String(settingsPlacement?.value || ""), /assistant\.generated\.settings\.menu:\$\{option:surface\|lower\}/);
|
|
59
47
|
assert.match(String(settingsPlacement?.value || ""), /host: "__ASSISTANT_SETTINGS_HOST__"/);
|
|
60
|
-
assert.match(String(settingsPlacement?.value || ""), /
|
|
61
|
-
assert.match(String(
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const runtimeDeps = descriptor?.mutations?.dependencies?.runtime || {};
|
|
66
|
-
const assistantCorePackageJsonPath = path.resolve(
|
|
67
|
-
path.dirname(new URL(import.meta.url).pathname),
|
|
68
|
-
"..",
|
|
69
|
-
"..",
|
|
70
|
-
"assistant-core",
|
|
71
|
-
"package.json"
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
return readFile(assistantCorePackageJsonPath, "utf8").then((source) => {
|
|
75
|
-
const assistantCorePackageJson = JSON.parse(source);
|
|
76
|
-
|
|
77
|
-
assert.equal(runtimeDeps["@local/assistant"], "file:packages/assistant");
|
|
78
|
-
assert.equal(runtimeDeps["@jskit-ai/assistant-core"], assistantCorePackageJson.version);
|
|
79
|
-
assert.equal(Object.hasOwn(runtimeDeps, "@jskit-ai/workspaces-core"), false);
|
|
80
|
-
assert.equal(Object.hasOwn(runtimeDeps, "@jskit-ai/workspaces-web"), false);
|
|
81
|
-
});
|
|
48
|
+
assert.match(String(settingsPlacement?.value || ""), /position: "primary-menu"/);
|
|
49
|
+
assert.match(String(publicConfig?.value || ""), /config\.assistantSurfaces\.\$\{option:surface\|lower\} = \{/);
|
|
50
|
+
assert.match(String(serverConfig?.value || ""), /config\.assistantServer\.\$\{option:surface\|lower\} = \{/);
|
|
51
|
+
assert.match(String(serverConfig?.value || ""), /aiConfigPrefix: "__ASSISTANT_AI_CONFIG_PREFIX__"/);
|
|
52
|
+
assert.match(String(envBlock?.value || ""), /__ASSISTANT_AI_CONFIG_PREFIX___AI_PROVIDER=\$\{option:ai-provider\}/);
|
|
82
53
|
});
|
|
@@ -9,14 +9,16 @@ async function readTemplateFile(relativePath) {
|
|
|
9
9
|
return readFile(path.join(packageRoot, relativePath), "utf8");
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
test("
|
|
13
|
-
const source = await readTemplateFile("templates/src/
|
|
12
|
+
test("assistant page template renders the shared runtime client element with an explicit surface id", async () => {
|
|
13
|
+
const source = await readTemplateFile("templates/src/pages/assistant/index.vue");
|
|
14
14
|
|
|
15
|
-
assert.match(source,
|
|
15
|
+
assert.match(source, /<AssistantSurfaceClientElement surface-id="__ASSISTANT_SURFACE_ID__" \/>/);
|
|
16
|
+
assert.match(source, /from "@jskit-ai\/assistant-runtime\/client"/);
|
|
16
17
|
});
|
|
17
18
|
|
|
18
|
-
test("
|
|
19
|
-
const source = await readTemplateFile("templates/src/
|
|
19
|
+
test("assistant settings page template renders the shared runtime settings client element with the target surface id", async () => {
|
|
20
|
+
const source = await readTemplateFile("templates/src/pages/settings/assistant/index.vue");
|
|
20
21
|
|
|
21
|
-
assert.
|
|
22
|
+
assert.match(source, /<AssistantSettingsClientElement target-surface-id="__ASSISTANT_SURFACE_ID__" \/>/);
|
|
23
|
+
assert.match(source, /from "@jskit-ai\/assistant-runtime\/client"/);
|
|
22
24
|
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
exports.up = async function up(knex) {
|
|
2
|
-
const hasTable = await knex.schema.hasTable("__ASSISTANT_CONFIG_TABLE__");
|
|
3
|
-
if (!hasTable) {
|
|
4
|
-
await knex.schema.createTable("__ASSISTANT_CONFIG_TABLE__", (table) => {
|
|
5
|
-
table.increments("id").unsigned().primary();
|
|
6
|
-
table.string("target_surface_id", 64).notNullable();
|
|
7
|
-
table.string("scope_key", 160).notNullable();
|
|
8
|
-
table.integer("workspace_id").unsigned().nullable();
|
|
9
|
-
if ("__ASSISTANT_CONFIG_SCOPE__" === "workspace") {
|
|
10
|
-
table.foreign("workspace_id").references("id").inTable("workspaces").onDelete("CASCADE");
|
|
11
|
-
}
|
|
12
|
-
table.text("system_prompt").notNullable().defaultTo("");
|
|
13
|
-
table.timestamp("created_at").notNullable().defaultTo(knex.fn.now());
|
|
14
|
-
table.timestamp("updated_at").notNullable().defaultTo(knex.fn.now());
|
|
15
|
-
|
|
16
|
-
table.unique(["target_surface_id", "scope_key"], "uq___ASSISTANT_CONFIG_TABLE___target_surface_scope");
|
|
17
|
-
table.index(["target_surface_id"], "idx___ASSISTANT_CONFIG_TABLE___target_surface");
|
|
18
|
-
table.index(["workspace_id"], "idx___ASSISTANT_CONFIG_TABLE___workspace");
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
exports.down = async function down(knex) {
|
|
24
|
-
await knex.schema.dropTableIfExists("__ASSISTANT_CONFIG_TABLE__");
|
|
25
|
-
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
exports.up = async function up(knex) {
|
|
2
|
-
const hasConversationsTable = await knex.schema.hasTable("__ASSISTANT_CONVERSATIONS_TABLE__");
|
|
3
|
-
if (!hasConversationsTable) {
|
|
4
|
-
await knex.schema.createTable("__ASSISTANT_CONVERSATIONS_TABLE__", (table) => {
|
|
5
|
-
table.increments("id").unsigned().primary();
|
|
6
|
-
table.integer("workspace_id").unsigned().nullable();
|
|
7
|
-
if (__ASSISTANT_RUNTIME_SURFACE_REQUIRES_WORKSPACE__) {
|
|
8
|
-
table.foreign("workspace_id").references("id").inTable("workspaces").onDelete("CASCADE");
|
|
9
|
-
}
|
|
10
|
-
table.integer("created_by_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL").index();
|
|
11
|
-
table.string("title", 160).notNullable().defaultTo("New conversation");
|
|
12
|
-
table.string("status", 32).notNullable().defaultTo("active");
|
|
13
|
-
table.string("provider", 64).notNullable().defaultTo("");
|
|
14
|
-
table.string("model", 128).notNullable().defaultTo("");
|
|
15
|
-
table.string("surface_id", 32).notNullable().defaultTo("__ASSISTANT_RUNTIME_SURFACE_ID__");
|
|
16
|
-
table.integer("message_count").unsigned().notNullable().defaultTo(0);
|
|
17
|
-
table.text("metadata_json").nullable();
|
|
18
|
-
table.timestamp("started_at").notNullable().defaultTo(knex.fn.now());
|
|
19
|
-
table.timestamp("ended_at").nullable();
|
|
20
|
-
table.timestamp("created_at").notNullable().defaultTo(knex.fn.now());
|
|
21
|
-
table.timestamp("updated_at").notNullable().defaultTo(knex.fn.now());
|
|
22
|
-
|
|
23
|
-
table.index(["workspace_id", "started_at"], "idx___ASSISTANT_CONVERSATIONS_TABLE___workspace_started_at");
|
|
24
|
-
table.index(["created_by_user_id", "started_at"], "idx___ASSISTANT_CONVERSATIONS_TABLE___creator_started_at");
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const hasMessagesTable = await knex.schema.hasTable("__ASSISTANT_MESSAGES_TABLE__");
|
|
29
|
-
if (!hasMessagesTable) {
|
|
30
|
-
await knex.schema.createTable("__ASSISTANT_MESSAGES_TABLE__", (table) => {
|
|
31
|
-
table.increments("id").unsigned().primary();
|
|
32
|
-
table.integer("conversation_id").unsigned().notNullable().references("id").inTable("__ASSISTANT_CONVERSATIONS_TABLE__").onDelete("CASCADE");
|
|
33
|
-
table.integer("workspace_id").unsigned().nullable();
|
|
34
|
-
if (__ASSISTANT_RUNTIME_SURFACE_REQUIRES_WORKSPACE__) {
|
|
35
|
-
table.foreign("workspace_id").references("id").inTable("workspaces").onDelete("CASCADE");
|
|
36
|
-
}
|
|
37
|
-
table.integer("seq").unsigned().notNullable();
|
|
38
|
-
table.string("role", 32).notNullable();
|
|
39
|
-
table.string("kind", 32).notNullable().defaultTo("chat");
|
|
40
|
-
table.string("client_message_sid", 128).notNullable().defaultTo("");
|
|
41
|
-
table.integer("actor_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL").index();
|
|
42
|
-
table.text("content_text").nullable();
|
|
43
|
-
table.text("metadata_json").nullable();
|
|
44
|
-
table.timestamp("created_at").notNullable().defaultTo(knex.fn.now());
|
|
45
|
-
|
|
46
|
-
table.unique(["conversation_id", "seq"], "uq___ASSISTANT_MESSAGES_TABLE___conversation_seq");
|
|
47
|
-
table.index(["conversation_id", "created_at"], "idx___ASSISTANT_MESSAGES_TABLE___conversation_created_at");
|
|
48
|
-
table.index(["workspace_id"], "idx___ASSISTANT_MESSAGES_TABLE___workspace");
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
exports.down = async function down(knex) {
|
|
54
|
-
await knex.schema.dropTableIfExists("__ASSISTANT_MESSAGES_TABLE__");
|
|
55
|
-
await knex.schema.dropTableIfExists("__ASSISTANT_CONVERSATIONS_TABLE__");
|
|
56
|
-
};
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<AssistantSettingsFormCard
|
|
3
|
-
root-class="assistant-settings-client-element"
|
|
4
|
-
title="Assistant settings"
|
|
5
|
-
:subtitle="subtitle"
|
|
6
|
-
no-permission-message="You do not have permission to view assistant settings."
|
|
7
|
-
save-label="Save assistant settings"
|
|
8
|
-
:add-edit="addEdit"
|
|
9
|
-
:show-form-skeleton="showFormSkeleton"
|
|
10
|
-
>
|
|
11
|
-
<v-textarea
|
|
12
|
-
v-model="form.systemPrompt"
|
|
13
|
-
label="System prompt"
|
|
14
|
-
variant="outlined"
|
|
15
|
-
density="comfortable"
|
|
16
|
-
rows="8"
|
|
17
|
-
auto-grow
|
|
18
|
-
:readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
|
|
19
|
-
:error-messages="addEdit.fieldErrors.systemPrompt ? [addEdit.fieldErrors.systemPrompt] : []"
|
|
20
|
-
/>
|
|
21
|
-
</AssistantSettingsFormCard>
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
|
-
<script setup>
|
|
25
|
-
import { computed, reactive } from "vue";
|
|
26
|
-
import { validateOperationSection } from "@jskit-ai/http-runtime/shared/validators/operationValidation";
|
|
27
|
-
import { AssistantSettingsFormCard } from "@jskit-ai/assistant-core/client";
|
|
28
|
-
import {
|
|
29
|
-
assistantConfigResource,
|
|
30
|
-
assistantSettingsQueryKey
|
|
31
|
-
} from "@jskit-ai/assistant-core/shared";
|
|
32
|
-
import { useAddEdit } from "@jskit-ai/users-web/client/composables/useAddEdit";
|
|
33
|
-
import { assistantRuntimeConfig } from "../../shared/assistantRuntimeConfig.js";
|
|
34
|
-
|
|
35
|
-
const form = reactive({
|
|
36
|
-
systemPrompt: ""
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const subtitle = computed(() => {
|
|
40
|
-
if (assistantRuntimeConfig.configScope === "workspace") {
|
|
41
|
-
return `Configure the prompt used on the ${assistantRuntimeConfig.runtimeSurfaceId} surface for this workspace.`;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return `Configure the prompt used on the ${assistantRuntimeConfig.runtimeSurfaceId} surface.`;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const addEdit = useAddEdit({
|
|
48
|
-
ownershipFilter: assistantRuntimeConfig.settingsSurfaceRequiresWorkspace ? "workspace" : "public",
|
|
49
|
-
surfaceId: assistantRuntimeConfig.settingsSurfaceId,
|
|
50
|
-
access: "auto",
|
|
51
|
-
resource: assistantConfigResource,
|
|
52
|
-
apiSuffix: "/assistant/settings",
|
|
53
|
-
queryKeyFactory: (_surfaceId = "", workspaceSlug = "") =>
|
|
54
|
-
assistantSettingsQueryKey({
|
|
55
|
-
targetSurfaceId: assistantRuntimeConfig.runtimeSurfaceId,
|
|
56
|
-
workspaceSlug
|
|
57
|
-
}),
|
|
58
|
-
viewPermissions: assistantRuntimeConfig.settingsSurfaceRequiresWorkspace
|
|
59
|
-
? ["workspace.settings.view", "workspace.settings.update"]
|
|
60
|
-
: [],
|
|
61
|
-
savePermissions: assistantRuntimeConfig.settingsSurfaceRequiresWorkspace
|
|
62
|
-
? ["workspace.settings.update"]
|
|
63
|
-
: [],
|
|
64
|
-
writeMethod: "PATCH",
|
|
65
|
-
placementSource: "assistant.settings-view",
|
|
66
|
-
fallbackLoadError: "Unable to load assistant settings.",
|
|
67
|
-
fallbackSaveError: "Unable to update assistant settings.",
|
|
68
|
-
fieldErrorKeys: ["systemPrompt"],
|
|
69
|
-
model: form,
|
|
70
|
-
parseInput: (rawPayload) =>
|
|
71
|
-
validateOperationSection({
|
|
72
|
-
operation: assistantConfigResource.operations.patch,
|
|
73
|
-
section: "bodyValidator",
|
|
74
|
-
value: rawPayload
|
|
75
|
-
}),
|
|
76
|
-
mapLoadedToModel(model, payload = {}) {
|
|
77
|
-
const settings = payload?.settings && typeof payload.settings === "object" ? payload.settings : {};
|
|
78
|
-
model.systemPrompt = String(settings.systemPrompt || "");
|
|
79
|
-
},
|
|
80
|
-
buildRawPayload(model) {
|
|
81
|
-
return {
|
|
82
|
-
systemPrompt: model.systemPrompt
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const showFormSkeleton = computed(() => Boolean(addEdit.isInitialLoading));
|
|
88
|
-
</script>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<AssistantClientElement v-bind="runtime" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup>
|
|
6
|
-
import { AssistantClientElement } from "@jskit-ai/assistant-core/client";
|
|
7
|
-
import { useAssistantRuntime } from "../composables/useAssistantRuntime.js";
|
|
8
|
-
|
|
9
|
-
const runtime = useAssistantRuntime();
|
|
10
|
-
</script>
|