@jskit-ai/agent-docs 0.1.270 → 0.1.271
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/guide/agent/app-extras/assistant-conversation.md +3 -2
- package/guide/agent/app-extras/assistant.md +35 -0
- package/guide/agent/app-setup/database-layer.md +4 -0
- package/guide/agent/app-setup/initial-scaffolding.md +76 -0
- package/package.json +1 -1
- package/patterns/feature-package/example/booking-engine/package.json +1 -1
- package/patterns/minimal-foundation/PATTERN.md +3 -1
- package/patterns/minimal-foundation/example/package.json +4 -4
- package/patterns/minimal-foundation/example/server.js +9 -6
- package/patterns/minimal-foundation/example/tests/server/smoke.test.js +3 -4
- package/patterns/shell-foundation/example/package.json +5 -5
- package/patterns/shell-foundation/example/packages/main/package.json +1 -1
- package/patterns/shell-foundation/example/server.js +9 -6
- package/patterns/shell-foundation/example/tests/server/smoke.test.js +3 -4
- package/reference/autogen/PATTERN_INDEX.md +37 -37
- package/reference/autogen/packages/agent.md +1 -1
- package/reference/autogen/packages/assistant-runtime.md +1 -0
- package/reference/autogen/packages/crud-core.md +3 -2
- package/reference/autogen/packages/kernel.md +24 -1
- package/skills/jskit/references/pattern-index.md +37 -37
- package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +3 -1
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +4 -4
- package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +9 -6
- package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +3 -4
- package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +5 -5
- package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
- package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +9 -6
- package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +3 -4
- package/skills/jskit/references/patterns/assistant/assistant-surface/PATTERN.md +5 -0
- package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
- package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +11 -0
- package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
- package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
|
@@ -2473,8 +2473,9 @@ accounts) authorizes the same connection again and stops the reply when access i
|
|
|
2473
2473
|
gone. A configured `effort` reaches every provider as the AI SDK's standard
|
|
2474
2474
|
reasoning setting; without one, the engine's default applies (adaptive thinking at
|
|
2475
2475
|
high effort for Anthropic-format models). The system prompt is the configured
|
|
2476
|
-
instructions, then the summary
|
|
2477
|
-
|
|
2476
|
+
instructions, then the summary. The engine's state note with the current UTC time
|
|
2477
|
+
follows the conversation as its last message, so the provider's prompt cache keeps
|
|
2478
|
+
the whole history from one turn to the next.
|
|
2478
2479
|
|
|
2479
2480
|
An application can set server-owned `limits.maxApiToolProgressCharacters` to a
|
|
2480
2481
|
positive safe integer to bound the decoded text accompanying confirmed API tool
|
|
@@ -164,6 +164,41 @@ Workspace scope is valid only when both the runtime and its settings surface
|
|
|
164
164
|
are workspace-aware. Requests must retain the selected workspace through the
|
|
165
165
|
server action boundary.
|
|
166
166
|
|
|
167
|
+
### Who may change the instructions
|
|
168
|
+
|
|
169
|
+
The settings hold the instructions every conversation on the surface follows,
|
|
170
|
+
so changing them needs more than reading them. Any signed-in user may read
|
|
171
|
+
them (a workspace settings surface also needs `workspace.settings.view`, a
|
|
172
|
+
console-owner surface the console owner). Changing them needs:
|
|
173
|
+
|
|
174
|
+
| Settings surface | Permission that changes the instructions |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| requires a workspace | `workspace.settings.update` |
|
|
177
|
+
| console-owner access | the console owner |
|
|
178
|
+
| any other | `assistant.settings.update` |
|
|
179
|
+
|
|
180
|
+
Grant `assistant.settings.update` to the application's administrators through
|
|
181
|
+
the request context's permissions, or name another permission the application
|
|
182
|
+
already grants in server config:
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
// config/server.js
|
|
186
|
+
export const config = {
|
|
187
|
+
assistantServer: {
|
|
188
|
+
home: {
|
|
189
|
+
aiIntegrationId: "assistant",
|
|
190
|
+
settingsUpdatePermission: "app.admin"
|
|
191
|
+
// or { require: "any", permissions: ["app.admin", "app.owner"] }
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`settingsUpdatePermission: { require: "authenticated" }` lets every signed-in
|
|
198
|
+
user change the instructions; choose it only deliberately. A malformed value
|
|
199
|
+
stops the server from starting. Anyone else is refused with
|
|
200
|
+
`assistant.runtime.settings.updateForbidden` (403).
|
|
201
|
+
|
|
167
202
|
### Existing SQL conversations
|
|
168
203
|
|
|
169
204
|
The optional database integration uses the common conversation runtime for
|
|
@@ -45,6 +45,10 @@ also derives its dialect from the installed driver and rejects a conflicting
|
|
|
45
45
|
The application or hosting environment creates the database and provides its
|
|
46
46
|
credentials. JSKIT never guesses or commits them.
|
|
47
47
|
|
|
48
|
+
The running database provider registers a `database` health check that runs
|
|
49
|
+
`select 1` within two seconds. The foundations' `GET /api/health` answers `503`
|
|
50
|
+
while it fails; see [Health endpoint](./initial-scaffolding.md#health-endpoint).
|
|
51
|
+
|
|
48
52
|
## Migration configuration
|
|
49
53
|
|
|
50
54
|
Use the fixed-dialect pattern owned by the selected driver. The important
|
|
@@ -100,6 +100,82 @@ loading. Do not replace them with generic spinners. Keep failures local when a
|
|
|
100
100
|
resource cannot render; use shared toast/snackbar feedback for transient user
|
|
101
101
|
commands so errors do not push the working page down.
|
|
102
102
|
|
|
103
|
+
## Health endpoint
|
|
104
|
+
|
|
105
|
+
Both foundations register `GET /api/health` after `createInstalledRuntime` and
|
|
106
|
+
answer from the installed runtime's `health.check()`: `200` with
|
|
107
|
+
`{ ok: true, checks, app }` when every check the installed packages register
|
|
108
|
+
passes, and `503` with `ok: false` when one fails. `@jskit-ai/database-runtime`
|
|
109
|
+
registers a `database` check that runs `select 1`. Each check has two seconds;
|
|
110
|
+
a failure is logged on the server and the response only names which checks
|
|
111
|
+
passed, so the route can stay public for load balancers and uptime monitors.
|
|
112
|
+
Requests that arrive while a check runs share it. An application that adopted
|
|
113
|
+
an older foundation, where the route answered `ok: true` before the runtime was
|
|
114
|
+
created, moves the route after `createInstalledRuntime` in the same way.
|
|
115
|
+
|
|
116
|
+
A package adds its own check through the optional `runtime.health`
|
|
117
|
+
capability: `optional: { health: "runtime.health" }`, then
|
|
118
|
+
`health?.register("queue", () => queue.ping())` in `setup()`. The check resolves
|
|
119
|
+
when healthy and rejects or hangs when not.
|
|
120
|
+
|
|
121
|
+
## Security headers
|
|
122
|
+
|
|
123
|
+
`createInstalledRuntime` adds security headers to every response its Fastify
|
|
124
|
+
server sends, including error and not-found responses. A route that sets one of
|
|
125
|
+
these headers itself keeps its own value.
|
|
126
|
+
|
|
127
|
+
| Header | When | Default |
|
|
128
|
+
| --- | --- | --- |
|
|
129
|
+
| `X-Content-Type-Options: nosniff` | always | on |
|
|
130
|
+
| `Referrer-Policy` | always | `strict-origin-when-cross-origin` |
|
|
131
|
+
| `Strict-Transport-Security` | production | `max-age=31536000` |
|
|
132
|
+
| `Content-Security-Policy: frame-ancestors` | production | `'self'` |
|
|
133
|
+
| `Content-Security-Policy-Report-Only` | production | the content policy below |
|
|
134
|
+
|
|
135
|
+
Production means `NODE_ENV=production`. A host that starts the server with a
|
|
136
|
+
plain `npm start` runs it in development; its Serve command must set the
|
|
137
|
+
variable, for example `env NODE_ENV=production npm start`. Development sends only
|
|
138
|
+
nosniff and the Referrer-Policy, so an editor's preview, such as Vibe64's, can
|
|
139
|
+
frame the application and inject its bridge script.
|
|
140
|
+
|
|
141
|
+
The content policy allows JSKIT's client: the application's own scripts and
|
|
142
|
+
WebAssembly, inline styles (Vuetify and the loading shell use them), images
|
|
143
|
+
from the application, `data:`, `blob:` and any HTTPS source, fonts and media
|
|
144
|
+
from the application and `data:`, same-origin requests and sockets, and no
|
|
145
|
+
plugins, foreign base URLs or foreign form posts. It is reported, not enforced,
|
|
146
|
+
by default: browsers log violations in the console without blocking anything,
|
|
147
|
+
because an application's own additions, such as a sign-in provider, an
|
|
148
|
+
analytics script or a map, are not known to JSKIT. Enforce it once the
|
|
149
|
+
application's pages run without violations. Framing is always enforced, since
|
|
150
|
+
browsers ignore `frame-ancestors` in a report-only policy.
|
|
151
|
+
|
|
152
|
+
Change the defaults in `config/server.js`:
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
export const config = {
|
|
156
|
+
securityHeaders: {
|
|
157
|
+
// Another site that frames production, such as the editor that previews it.
|
|
158
|
+
frameAncestors: ["'self'", "https://editor.example.com"],
|
|
159
|
+
contentSecurityPolicy: {
|
|
160
|
+
mode: "enforce", // "report-only" (default), "enforce" or "off"
|
|
161
|
+
directives: {
|
|
162
|
+
"connect-src": ["'self'", "https://auth.example.com"],
|
|
163
|
+
"form-action": false // false leaves a directive out
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`noSniff: false`, `referrerPolicy: false`, `strictTransportSecurity: false` and
|
|
171
|
+
`frameAncestors: false` leave that header out; `referrerPolicy` and
|
|
172
|
+
`strictTransportSecurity` also take their own header value. A directive's
|
|
173
|
+
sources replace JSKIT's for that directive; framing is set only through
|
|
174
|
+
`frameAncestors`. An invalid value stops the server from starting. A server
|
|
175
|
+
composed without `createInstalledRuntime` calls
|
|
176
|
+
`registerSecurityHeaders(fastify, { config, env })` from
|
|
177
|
+
`@jskit-ai/kernel/server/http` before it registers any plugin.
|
|
178
|
+
|
|
103
179
|
## Verification
|
|
104
180
|
|
|
105
181
|
Pattern contract tests keep both examples concrete, parseable, npm-published,
|
package/package.json
CHANGED
|
@@ -146,7 +146,9 @@ verification, not only against Vite development mode.
|
|
|
146
146
|
After adapting the example, install the declared packages once and run
|
|
147
147
|
`npm run develop` for the live application. Then run the application's lint,
|
|
148
148
|
server tests, client tests, production build, and focused browser smoke.
|
|
149
|
-
Confirm `/api/health` and the first product route.
|
|
149
|
+
Confirm `/api/health` and the first product route. The health route answers
|
|
150
|
+
from the installed runtime's `health.check()` after `createInstalledRuntime`, so
|
|
151
|
+
it returns `503` while a registered check, such as the database's, fails.
|
|
150
152
|
|
|
151
153
|
## Avoid
|
|
152
154
|
|
|
@@ -34,22 +34,22 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@local/main": "0.1.0",
|
|
36
36
|
"@fastify/static": "^10.1.3",
|
|
37
|
-
"@jskit-ai/kernel": "0.2.
|
|
37
|
+
"@jskit-ai/kernel": "0.2.8",
|
|
38
38
|
"@tanstack/vue-query": "^5.101.0",
|
|
39
|
-
"fastify": "^5.
|
|
39
|
+
"fastify": "^5.12.7",
|
|
40
40
|
"pino": "^10.3.1",
|
|
41
41
|
"json-rest-schema": "^1.0.17",
|
|
42
42
|
"pinia": "^4.0.3",
|
|
43
43
|
"vue": "^3.5.44",
|
|
44
44
|
"vue-router": "^5.3.1",
|
|
45
45
|
"vuetify": "^4.1.2",
|
|
46
|
-
"@jskit-ai/http-runtime": "0.2.
|
|
46
|
+
"@jskit-ai/http-runtime": "0.2.8",
|
|
47
47
|
"@fastify/fast-json-stringify-compiler": "^5.1.0",
|
|
48
48
|
"@vue/devtools-api": "^8.2.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@jskit-ai/config-eslint": "0.1.245",
|
|
52
|
-
"@jskit-ai/jskit-catalog": "0.2.
|
|
52
|
+
"@jskit-ai/jskit-catalog": "0.2.23",
|
|
53
53
|
"@playwright/test": "1.61.1",
|
|
54
54
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
55
55
|
"eslint": "^10.8.0",
|
|
@@ -102,12 +102,6 @@ async function createServer({ runtimeEnv }) {
|
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
app.get("/api/health", async () => {
|
|
106
|
-
return {
|
|
107
|
-
ok: true,
|
|
108
|
-
app: "reading-room"
|
|
109
|
-
};
|
|
110
|
-
});
|
|
111
105
|
const appRoot = path.resolve(process.cwd());
|
|
112
106
|
const distRoot = path.resolve(appRoot, "dist");
|
|
113
107
|
const hasWebBuild = existsSync(path.resolve(distRoot, SPA_INDEX_FILE));
|
|
@@ -124,6 +118,15 @@ async function createServer({ runtimeEnv }) {
|
|
|
124
118
|
fastify: app
|
|
125
119
|
});
|
|
126
120
|
|
|
121
|
+
// Healthy when every check the installed packages register passes, such as the database's.
|
|
122
|
+
app.get("/api/health", async (request, reply) => {
|
|
123
|
+
const health = await runtime.health.check();
|
|
124
|
+
return reply.code(health.ok ? 200 : 503).send({
|
|
125
|
+
...health,
|
|
126
|
+
app: "reading-room"
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
127
130
|
registerSurfaceRequestConstraint({
|
|
128
131
|
fastify: app,
|
|
129
132
|
surfaceRuntime,
|
|
@@ -3,15 +3,14 @@ import test from "node:test";
|
|
|
3
3
|
import { createServer } from "../../server.js";
|
|
4
4
|
import { resolveRuntimeEnv } from "../../server/lib/runtimeEnv.js";
|
|
5
5
|
|
|
6
|
-
test("GET /api/health
|
|
6
|
+
test("GET /api/health reports the installed runtime's health checks", async (context) => {
|
|
7
7
|
const app = await createServer({ runtimeEnv: resolveRuntimeEnv() });
|
|
8
|
+
context.after(() => app.close());
|
|
8
9
|
const response = await app.inject({
|
|
9
10
|
method: "GET",
|
|
10
11
|
url: "/api/health"
|
|
11
12
|
});
|
|
12
13
|
|
|
13
14
|
assert.equal(response.statusCode, 200);
|
|
14
|
-
assert.
|
|
15
|
-
|
|
16
|
-
await app.close();
|
|
15
|
+
assert.deepEqual(response.json(), { ok: true, checks: {}, app: "reading-room" });
|
|
17
16
|
});
|
|
@@ -34,24 +34,24 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@local/main": "0.1.0",
|
|
36
36
|
"@fastify/static": "^10.1.3",
|
|
37
|
-
"@jskit-ai/kernel": "0.2.
|
|
37
|
+
"@jskit-ai/kernel": "0.2.8",
|
|
38
38
|
"@tanstack/vue-query": "^5.101.0",
|
|
39
|
-
"fastify": "^5.
|
|
39
|
+
"fastify": "^5.12.7",
|
|
40
40
|
"pino": "^10.3.1",
|
|
41
41
|
"json-rest-schema": "^1.0.17",
|
|
42
42
|
"pinia": "^4.0.3",
|
|
43
43
|
"vue": "^3.5.44",
|
|
44
44
|
"vue-router": "^5.3.1",
|
|
45
45
|
"vuetify": "^4.1.2",
|
|
46
|
-
"@jskit-ai/http-runtime": "0.2.
|
|
46
|
+
"@jskit-ai/http-runtime": "0.2.8",
|
|
47
47
|
"@mdi/js": "^7.4.47",
|
|
48
|
-
"@jskit-ai/shell-web": "0.2.
|
|
48
|
+
"@jskit-ai/shell-web": "0.2.9",
|
|
49
49
|
"@fastify/fast-json-stringify-compiler": "^5.1.0",
|
|
50
50
|
"@vue/devtools-api": "^8.2.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@jskit-ai/config-eslint": "0.1.245",
|
|
54
|
-
"@jskit-ai/jskit-catalog": "0.2.
|
|
54
|
+
"@jskit-ai/jskit-catalog": "0.2.23",
|
|
55
55
|
"@playwright/test": "1.61.1",
|
|
56
56
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
57
57
|
"eslint": "^10.8.0",
|
|
@@ -102,12 +102,6 @@ async function createServer({ runtimeEnv }) {
|
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
app.get("/api/health", async () => {
|
|
106
|
-
return {
|
|
107
|
-
ok: true,
|
|
108
|
-
app: "reading-room"
|
|
109
|
-
};
|
|
110
|
-
});
|
|
111
105
|
const appRoot = path.resolve(process.cwd());
|
|
112
106
|
const distRoot = path.resolve(appRoot, "dist");
|
|
113
107
|
const hasWebBuild = existsSync(path.resolve(distRoot, SPA_INDEX_FILE));
|
|
@@ -124,6 +118,15 @@ async function createServer({ runtimeEnv }) {
|
|
|
124
118
|
fastify: app
|
|
125
119
|
});
|
|
126
120
|
|
|
121
|
+
// Healthy when every check the installed packages register passes, such as the database's.
|
|
122
|
+
app.get("/api/health", async (request, reply) => {
|
|
123
|
+
const health = await runtime.health.check();
|
|
124
|
+
return reply.code(health.ok ? 200 : 503).send({
|
|
125
|
+
...health,
|
|
126
|
+
app: "reading-room"
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
127
130
|
registerSurfaceRequestConstraint({
|
|
128
131
|
fastify: app,
|
|
129
132
|
surfaceRuntime,
|
|
@@ -3,15 +3,14 @@ import test from "node:test";
|
|
|
3
3
|
import { createServer } from "../../server.js";
|
|
4
4
|
import { resolveRuntimeEnv } from "../../server/lib/runtimeEnv.js";
|
|
5
5
|
|
|
6
|
-
test("GET /api/health
|
|
6
|
+
test("GET /api/health reports the installed runtime's health checks", async (context) => {
|
|
7
7
|
const app = await createServer({ runtimeEnv: resolveRuntimeEnv() });
|
|
8
|
+
context.after(() => app.close());
|
|
8
9
|
const response = await app.inject({
|
|
9
10
|
method: "GET",
|
|
10
11
|
url: "/api/health"
|
|
11
12
|
});
|
|
12
13
|
|
|
13
14
|
assert.equal(response.statusCode, 200);
|
|
14
|
-
assert.
|
|
15
|
-
|
|
16
|
-
await app.close();
|
|
15
|
+
assert.deepEqual(response.json(), { ok: true, checks: {}, app: "reading-room" });
|
|
17
16
|
});
|