@jskit-ai/assistant 0.1.42 → 0.1.44

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.
@@ -1,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/assistant",
4
- version: "0.1.42",
4
+ version: "0.1.44",
5
5
  kind: "generator",
6
6
  description: "Install assistant runtime/config for one surface and scaffold assistant pages at explicit target files.",
7
7
  options: {
@@ -49,7 +49,7 @@ export default Object.freeze({
49
49
  inputType: "text",
50
50
  defaultValue: "",
51
51
  promptLabel: "Link placement",
52
- promptHint: "Optional host:position target for the generated page link placement."
52
+ promptHint: "Optional target for the generated page link placement (format: host:position)."
53
53
  },
54
54
  "link-component-token": {
55
55
  required: false,
@@ -158,6 +158,7 @@ export default Object.freeze({
158
158
  ]
159
159
  },
160
160
  page: {
161
+ requiresShellWeb: true,
161
162
  entrypoint: "src/server/subcommands/page.js",
162
163
  export: "runGeneratorSubcommand",
163
164
  description: "Create an assistant runtime page at an explicit target file relative to src/pages/.",
@@ -194,6 +195,7 @@ export default Object.freeze({
194
195
  ]
195
196
  },
196
197
  "settings-page": {
198
+ requiresShellWeb: true,
197
199
  entrypoint: "src/server/subcommands/settingsPage.js",
198
200
  export: "runGeneratorSubcommand",
199
201
  description: "Create an assistant settings page at an explicit target file relative to src/pages/.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/assistant",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -9,6 +9,6 @@
9
9
  "./server/buildTemplateContext": "./src/server/buildTemplateContext.js"
10
10
  },
11
11
  "dependencies": {
12
- "@jskit-ai/kernel": "0.1.33"
12
+ "@jskit-ai/kernel": "0.1.35"
13
13
  }
14
14
  }
@@ -56,11 +56,11 @@ async function resolveAssistantPageGenerationContext({
56
56
  return Object.freeze({
57
57
  pageTarget,
58
58
  pageLabel: normalizeText(options?.name) || pageTarget.defaultName,
59
- linkPlacementHost: String(linkTarget.placementTarget?.host || ""),
60
- linkPlacementPosition: String(linkTarget.placementTarget?.position || ""),
59
+ linkPlacementTarget: String(linkTarget.placementTarget?.id || ""),
61
60
  linkComponentToken: String(linkTarget.componentToken || ""),
62
61
  linkWorkspaceSuffix: pageTarget.routeUrlSuffix,
63
62
  linkNonWorkspaceSuffix: pageTarget.routeUrlSuffix,
63
+ linkWhenLine: String(linkTarget.whenLine || ""),
64
64
  linkToPropLine: resolveLinkToPropLine(linkTarget.linkTo)
65
65
  });
66
66
  }
@@ -75,8 +75,7 @@ function renderAssistantPageLinkPlacementBlock({
75
75
  "{\n" +
76
76
  " addPlacement({\n" +
77
77
  ` id: "${String(pageTarget?.placementId || "")}",\n` +
78
- ` host: "${String(generationContext?.linkPlacementHost || "")}",\n` +
79
- ` position: "${String(generationContext?.linkPlacementPosition || "")}",\n` +
78
+ ` target: "${String(generationContext?.linkPlacementTarget || "")}",\n` +
80
79
  ` surfaces: ["${String(pageTarget?.surfaceId || "")}"],\n` +
81
80
  " order: 155,\n" +
82
81
  ` componentToken: "${String(generationContext?.linkComponentToken || "")}",\n` +
@@ -86,7 +85,7 @@ function renderAssistantPageLinkPlacementBlock({
86
85
  ` workspaceSuffix: "${String(generationContext?.linkWorkspaceSuffix || "")}",\n` +
87
86
  ` nonWorkspaceSuffix: "${String(generationContext?.linkNonWorkspaceSuffix || "")}",\n` +
88
87
  `${String(generationContext?.linkToPropLine || "")} },\n` +
89
- " when: ({ auth }) => Boolean(auth?.authenticated)\n" +
88
+ `${String(generationContext?.linkWhenLine || "")}` +
90
89
  " });\n" +
91
90
  "}\n"
92
91
  );
@@ -25,11 +25,12 @@ function toPagePath(targetFile = "") {
25
25
  return path.join("src/pages", targetFile);
26
26
  }
27
27
 
28
- async function writeAppFixture(appRoot) {
28
+ async function writeAppFixture(appRoot, { configSource = "" } = {}) {
29
29
  await writeFileInApp(
30
30
  appRoot,
31
31
  "config/public.js",
32
- `export const config = {
32
+ configSource ||
33
+ `export const config = {
33
34
  surfaceDefinitions: {
34
35
  admin: {
35
36
  id: "admin",
@@ -55,8 +56,8 @@ async function writeAppFixture(appRoot) {
55
56
  "src/components/ShellLayout.vue",
56
57
  `<template>
57
58
  <div>
58
- <ShellOutlet host="shell-layout" position="primary-menu" default />
59
- <ShellOutlet host="shell-layout" position="top-right" />
59
+ <ShellOutlet target="shell-layout:primary-menu" default />
60
+ <ShellOutlet target="shell-layout:top-right" />
60
61
  </div>
61
62
  </template>
62
63
  `
@@ -95,8 +96,7 @@ test("assistant page subcommand creates a runtime page at an explicit target fil
95
96
  const placementSource = await readFile(path.join(appRoot, "src/placement.js"), "utf8");
96
97
  assert.match(placementSource, /jskit:assistant\.page\.link:admin:\/ops\/copilot/);
97
98
  assert.match(placementSource, /id: "ui-generator\.page\.admin\.ops\.copilot\.link"/);
98
- assert.match(placementSource, /host: "shell-layout"/);
99
- assert.match(placementSource, /position: "primary-menu"/);
99
+ assert.match(placementSource, /target: "shell-layout:primary-menu"/);
100
100
  assert.match(placementSource, /label: "Copilot"/);
101
101
  assert.match(placementSource, /workspaceSuffix: "\/ops\/copilot"/);
102
102
  });
@@ -111,7 +111,7 @@ test("assistant settings-page subcommand uses the target assistant surface and i
111
111
  `<template>
112
112
  <SectionContainerShell>
113
113
  <template #tabs>
114
- <ShellOutlet host="admin-settings" position="sub-pages" />
114
+ <ShellOutlet target="admin-settings:sub-pages" />
115
115
  </template>
116
116
  <RouterView />
117
117
  </SectionContainerShell>
@@ -137,14 +137,48 @@ test("assistant settings-page subcommand uses the target assistant surface and i
137
137
 
138
138
  const placementSource = await readFile(path.join(appRoot, "src/placement.js"), "utf8");
139
139
  assert.match(placementSource, /jskit:assistant\.settings-page\.link:admin:\/settings\/assistant:console/);
140
- assert.match(placementSource, /host: "admin-settings"/);
141
- assert.match(placementSource, /position: "sub-pages"/);
140
+ assert.match(placementSource, /target: "admin-settings:sub-pages"/);
142
141
  assert.match(placementSource, /componentToken: "local\.main\.ui\.tab-link-item"/);
143
142
  assert.match(placementSource, /to: "\.\/assistant"/);
144
143
  assert.match(placementSource, /label: "Assistant"/);
145
144
  });
146
145
  });
147
146
 
147
+ test("assistant page subcommand omits the auth guard for a public surface link", async () => {
148
+ await withTempApp(async (appRoot) => {
149
+ await writeAppFixture(appRoot, {
150
+ configSource: `export const config = {
151
+ surfaceAccessPolicies: {
152
+ public: {}
153
+ },
154
+ surfaceDefinitions: {
155
+ home: {
156
+ id: "home",
157
+ pagesRoot: "home",
158
+ enabled: true,
159
+ requiresWorkspace: false,
160
+ accessPolicyId: "public"
161
+ }
162
+ },
163
+ assistantSurfaces: {}
164
+ };
165
+ `
166
+ });
167
+
168
+ const targetFile = "home/assistant/index.vue";
169
+ await runPageSubcommand({
170
+ appRoot,
171
+ subcommand: "page",
172
+ args: [targetFile],
173
+ options: {}
174
+ });
175
+
176
+ const placementSource = await readFile(path.join(appRoot, "src", "placement.js"), "utf8");
177
+ assert.match(placementSource, /id: "ui-generator\.page\.home\.assistant\.link"/);
178
+ assert.doesNotMatch(placementSource, /when: \(\{ auth \}\) => Boolean\(auth\?\.authenticated\)/);
179
+ });
180
+ });
181
+
148
182
  test("assistant page subcommand refuses to overwrite an existing user-owned page", async () => {
149
183
  await withTempApp(async (appRoot) => {
150
184
  await writeAppFixture(appRoot);
@@ -213,7 +247,7 @@ test("assistant settings-page subcommand overwrites an existing page when --forc
213
247
  `<template>
214
248
  <SectionContainerShell>
215
249
  <template #tabs>
216
- <ShellOutlet host="admin-settings" position="sub-pages" />
250
+ <ShellOutlet target="admin-settings:sub-pages" />
217
251
  </template>
218
252
  <RouterView />
219
253
  </SectionContainerShell>
@@ -267,19 +301,20 @@ test("assistant settings-page subcommand requires the target assistant surface o
267
301
  });
268
302
  });
269
303
 
270
- test("assistant page subcommand rejects target files with a src/pages prefix", async () => {
304
+ test("assistant page subcommand accepts target files with a src/pages prefix", async () => {
271
305
  await withTempApp(async (appRoot) => {
272
306
  await writeAppFixture(appRoot);
273
307
 
274
- await assert.rejects(
275
- () =>
276
- runPageSubcommand({
277
- appRoot,
278
- subcommand: "page",
279
- args: ["src/pages/w/[workspaceSlug]/admin/assistant/index.vue"],
280
- options: {}
281
- }),
282
- /must be relative to src\/pages\/, without the src\/pages\/ prefix/
283
- );
308
+ const targetFile = "src/pages/w/[workspaceSlug]/admin/assistant/index.vue";
309
+ const result = await runPageSubcommand({
310
+ appRoot,
311
+ subcommand: "page",
312
+ args: [targetFile],
313
+ options: {}
314
+ });
315
+
316
+ assert.deepEqual(result.touchedFiles, [targetFile, "src/placement.js"]);
317
+ const pageSource = await readFile(path.join(appRoot, targetFile), "utf8");
318
+ assert.match(pageSource, /<AssistantSurfaceClientElement surface-id="admin" \/>/);
284
319
  });
285
320
  });
package/README.md DELETED
@@ -1,91 +0,0 @@
1
- # @jskit-ai/assistant
2
-
3
- Install assistant runtime/config for one surface, then scaffold assistant pages at explicit page files.
4
-
5
- ## Mental Model
6
-
7
- `@jskit-ai/assistant` is the generator package.
8
-
9
- - `setup` installs the assistant runtime/config/env wiring.
10
- - `page <target-file>` creates the assistant runtime page anywhere relative to `src/pages/...`.
11
- - `settings-page <target-file>` creates the assistant settings page anywhere relative to `src/pages/...`.
12
-
13
- There is no separate server command and no separate client command.
14
-
15
- The layering is:
16
-
17
- - `@jskit-ai/assistant`: generator package with `setup`, `page`, and `settings-page`
18
- - `@jskit-ai/assistant-runtime`: runtime package installed by `setup`
19
- - `@jskit-ai/assistant-core`: lower-level provider/client library pulled in by `assistant-runtime`
20
-
21
- So the normal flow is:
22
-
23
- - run `setup`
24
- - optionally create `page`
25
- - optionally create `settings-page`
26
-
27
- Page placement follows the same file-driven model as `@jskit-ai/ui-generator`.
28
-
29
- - The surface comes from where the page file lives.
30
- - The route URL comes from that file path.
31
- - The default page-link placement comes from the nearest real parent subpages host when there is one.
32
-
33
- Only one assistant can be installed per target surface. That rule is enforced by `setup`, which writes the per-surface config entries.
34
-
35
- ## Setup
36
-
37
- ```bash
38
- npx jskit generate @jskit-ai/assistant setup \
39
- --surface admin \
40
- --settings-surface console \
41
- --config-scope global \
42
- --ai-provider openai \
43
- --ai-api-key "$OPENAI_API_KEY" \
44
- --ai-base-url "" \
45
- --ai-timeout-ms 120000
46
- ```
47
-
48
- `setup` does not create pages.
49
-
50
- It only registers:
51
-
52
- - `config.assistantSurfaces.<surface>`
53
- - `config.assistantServer.<surface>`
54
- - prefixed AI env defaults in `.env`
55
- - the `@jskit-ai/assistant-runtime` dependency chain, including `@jskit-ai/assistant-core`
56
-
57
- ## Runtime Page
58
-
59
- ```bash
60
- npx jskit generate @jskit-ai/assistant page \
61
- admin/ops/copilot/index.vue
62
- ```
63
-
64
- The page surface id comes from the target file path.
65
-
66
- Optional page-link overrides:
67
-
68
- - `--name`
69
- - `--link-placement`
70
- - `--link-component-token`
71
- - `--link-to`
72
-
73
- ## Settings Page
74
-
75
- ```bash
76
- npx jskit generate @jskit-ai/assistant settings-page \
77
- admin/settings/index/assistant/index.vue \
78
- --surface admin
79
- ```
80
-
81
- For `settings-page`, the page location and the assistant target surface are separate concerns:
82
-
83
- - `<target-file>` decides where the settings page lives and how its page link is placed
84
- - `--surface` decides which assistant surface the settings page edits
85
-
86
- The same optional page-link overrides are supported:
87
-
88
- - `--name`
89
- - `--link-placement`
90
- - `--link-component-token`
91
- - `--link-to`