@jskit-ai/agent-docs 0.1.265 → 0.1.267
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 +18 -4
- package/guide/agent/app-setup/authentication.md +8 -0
- package/guide/agent/app-setup/multi-homing.md +5 -3
- package/guide/agent/framework/translation.md +56 -10
- package/guide/agent/framework/ui-operations.md +11 -12
- package/package.json +1 -1
- package/patterns/feature-package/example/booking-engine/package.json +1 -1
- package/patterns/minimal-foundation/example/package.json +4 -4
- package/patterns/shell-foundation/example/package.json +5 -5
- package/patterns/shell-foundation/example/packages/main/package.json +1 -1
- package/reference/autogen/PATTERN_INDEX.md +37 -37
- package/reference/autogen/packages/assistant-core.md +5 -3
- package/reference/autogen/packages/auth-core.md +4 -1
- package/reference/autogen/packages/oidc-issuer-core.md +23 -4
- package/reference/autogen/packages/resource-crud-core.md +2 -1
- package/reference/autogen/packages/users-web.md +26 -0
- package/reference/autogen/packages/workspaces-core.md +2 -1
- package/reference/autogen/tooling/config-eslint.md +8 -0
- package/skills/jskit/references/multi-homing.md +5 -3
- package/skills/jskit/references/pattern-index.md +37 -37
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +4 -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/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/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
- package/skills/jskit/references/translation.md +56 -10
- package/skills/jskit/references/ui-operations.md +11 -12
|
@@ -486,7 +486,13 @@ fact cannot repair an older saved uncertain request or grant actor access.
|
|
|
486
486
|
When `draftStorage` restores a page, known failed deliveries remain failed and
|
|
487
487
|
accepted receipts remain accepted. Saved uncertain, pending or unrecognised
|
|
488
488
|
delivery states stay uncertain with the exact original ID, payload and draft;
|
|
489
|
-
closing a page during HTTP is not proof of rejection.
|
|
489
|
+
closing a page during HTTP is not proof of rejection. A draft message that was
|
|
490
|
+
never dispatched (one deferred behind a working turn, for example) can no longer
|
|
491
|
+
be sent once its conversation is released: its words return to the saved draft,
|
|
492
|
+
ahead of anything typed after it, and no delivery is saved for it. A draft
|
|
493
|
+
submission that settles undelivered without leaving a delivery record (refused
|
|
494
|
+
before one was recorded) gives its words back to the composer, as a steer
|
|
495
|
+
already did. Only the transient
|
|
490
496
|
inspection flag is reset so **Retry** is reachable again. A matching
|
|
491
497
|
canonical row marked `receipt: false` cannot settle delivery. Unknown inspection
|
|
492
498
|
never retries; an actual accepted receipt is required to acknowledge the request.
|
|
@@ -3425,8 +3431,13 @@ at shutdown each native owner stops the processes this server runs, since none
|
|
|
3425
3431
|
outlives the server that started it, and saved conversations are not reopened to
|
|
3426
3432
|
be stopped. Claude stops its sessions together, leaves an idle chat untouched
|
|
3427
3433
|
(nothing to stop, nothing written) and reports a session that cannot stop by ID
|
|
3428
|
-
in `failed` while the others still stop.
|
|
3429
|
-
|
|
3434
|
+
in `failed` while the others still stop. A turn still running when its process
|
|
3435
|
+
stops is not ended at shutdown: its saved record keeps the execution and the
|
|
3436
|
+
active turn, as after a crash, so the next server's recovery proves that exit,
|
|
3437
|
+
interrupts the turn and runs the host's interrupted checkpoint. A slow host
|
|
3438
|
+
checkpoint, such as a Git snapshot, never holds up shutdown. Claude stops its
|
|
3439
|
+
sessions even when its account-query cleanup fails; that failure is still the
|
|
3440
|
+
call's result. Once
|
|
3430
3441
|
shutdown has invalidated the owner, a later session close only releases retained
|
|
3431
3442
|
work. Failed cleanup can be retried after runtime closure. This is not a browser
|
|
3432
3443
|
operation or a way to submit a caller-selected native owner.
|
|
@@ -3453,7 +3464,10 @@ owners. The host synchronously supplies `{ engine, native, context, sessions,
|
|
|
3453
3464
|
options }` for operation `"reconcileSessions"`. The application retains its
|
|
3454
3465
|
session inventory, authorization and storage codecs. Codex retains its original
|
|
3455
3466
|
concurrent recovery and prune coordination; OpenCode retains per-session failure
|
|
3456
|
-
results and continues; Claude retains sequential, fail-fast restoration.
|
|
3467
|
+
results and continues; Claude retains sequential, fail-fast restoration. Like a
|
|
3468
|
+
session close, Claude reconciliation reopens only the saved custody an earlier
|
|
3469
|
+
server left, so a verified stop can retire it; idle saved conversations stay
|
|
3470
|
+
closed and unwritten.
|
|
3457
3471
|
|
|
3458
3472
|
`runtime.unsubscribeNativeSessions({ context, sessions })` supplies startup
|
|
3459
3473
|
subscription reset for Codex through operation `"unsubscribeSessions"` and a
|
|
@@ -236,5 +236,13 @@ A managed host instead supplies authenticated state through
|
|
|
236
236
|
file as a temporary secret, use relative URLs, and do not call the localhost
|
|
237
237
|
login helper or start a duplicate server.
|
|
238
238
|
|
|
239
|
+
The login state belongs to the host, which already fits it to the tested site.
|
|
240
|
+
Pass `process.env.PLAYWRIGHT_STORAGE_STATE` unchanged to `use.storageState`:
|
|
241
|
+
the config never reads, parses or edits that file or its `cookies` or
|
|
242
|
+
`origins`. `jskit/playwright-login-unchanged` reports a config that does, and
|
|
243
|
+
the host refuses to run its tests. If tests run signed out with the unchanged
|
|
244
|
+
state, that is a host defect: report it with the evidence; do not work around
|
|
245
|
+
it.
|
|
246
|
+
|
|
239
247
|
Never commit provider secrets, copy auth repositories into the app, or add an
|
|
240
248
|
installation questionnaire, mutation record, or setup receipt.
|
|
@@ -198,9 +198,11 @@ const InviteMailerProvider = defineProvider({
|
|
|
198
198
|
|
|
199
199
|
The optional `workspaces.invite-email-template` capability is a function that
|
|
200
200
|
renders that inner message; it receives `{ email, inviteUrl, workspace, inviter,
|
|
201
|
-
roleSid, roleLabel, expiresAt, locale, t }` (`roleLabel` only when
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
roleSid, roleLabel, expiresAt, locale, timeZone, t }` (`roleLabel` only when
|
|
202
|
+
configured; `locale` and `timeZone` are the recipient's saved settings, else
|
|
203
|
+
`en` and `UTC`). Provide it from an application feature, as for the mailer;
|
|
204
|
+
without it the built-in template renders the message, with the expiry written
|
|
205
|
+
as a date in that locale and time zone. Invitation links use `/invite/:token` unless
|
|
204
206
|
`workspaceInvitations.invitePath` names another path. The
|
|
205
207
|
`workspaces/workspace-server` pattern includes an example renderer.
|
|
206
208
|
|
|
@@ -135,6 +135,9 @@ the English `message`:
|
|
|
135
135
|
values and render from `jskit.errors.<code>`.
|
|
136
136
|
- Validation errors keep `details.fieldErrors` (English) and add
|
|
137
137
|
`details.fieldErrorCodes: { field: { code, params } }`.
|
|
138
|
+
- A schema's field `messages` may give a message as a string or as
|
|
139
|
+
`{ code, message, params }` (see below); the coded form travels as that
|
|
140
|
+
field's code.
|
|
138
141
|
- Where one code covers several different sentences (for example
|
|
139
142
|
`connector_input_invalid`), the response also has `messageCode` and
|
|
140
143
|
`messageParams` for the exact sentence.
|
|
@@ -164,6 +167,33 @@ throw new AppError(409, "That slug is taken.", { code: "app.project.slugTaken" }
|
|
|
164
167
|
// en: { jskit: { app: { project: { slugTaken: "That slug is taken." } } } }
|
|
165
168
|
```
|
|
166
169
|
|
|
170
|
+
### Field messages in schemas
|
|
171
|
+
|
|
172
|
+
A field's `messages` in a resource or command schema map a validation keyword
|
|
173
|
+
(or `default`) to the message shown when that check fails. A plain string is
|
|
174
|
+
sent as written and is never translated. To make it translatable, give the
|
|
175
|
+
coded form instead: the code, the English (exactly the catalog's English with
|
|
176
|
+
the params filled in) and any params.
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
const NAME_MESSAGES = Object.freeze({
|
|
180
|
+
required: { code: "app.project.nameRequired", message: "Name is required." },
|
|
181
|
+
maxLength: { code: "app.project.nameTooLong", message: "Use at most 80 characters.", params: { max: 80 } }
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const schema = {
|
|
185
|
+
name: { type: "string", required: true, maxLength: 80, messages: NAME_MESSAGES }
|
|
186
|
+
};
|
|
187
|
+
// en: { jskit: { app: { project: {
|
|
188
|
+
// nameRequired: "Name is required.", nameTooLong: "Use at most {max} characters." } } } }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The server still sends the English in `details.fieldErrors` and adds the code
|
|
192
|
+
and params to `details.fieldErrorCodes`, so an untranslated app shows exactly
|
|
193
|
+
the English it showed before. The failed check's own params (for example
|
|
194
|
+
`limit`) are sent too, and the coded entry's `params` win over them. JSKIT's
|
|
195
|
+
own schemas use this form, which is why their field messages translate.
|
|
196
|
+
|
|
167
197
|
## Placement labels
|
|
168
198
|
|
|
169
199
|
A placement `label` or `title` may be a message key, `{ key, fallback, params }`
|
|
@@ -186,12 +216,21 @@ App code can use the same helpers from `useJskitText()`: `formatDate`,
|
|
|
186
216
|
|
|
187
217
|
## Emails
|
|
188
218
|
|
|
189
|
-
The
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
219
|
+
The server reads the same `src/locales/<code>/jskit.json` files the client
|
|
220
|
+
uses, so translating a JSKIT email's keys there translates the email too. It
|
|
221
|
+
looks for the exact locale (`it-IT`), then the language (`it`), then English.
|
|
222
|
+
|
|
223
|
+
- The workspace invitation email (`jskit.workspaces.inviteEmail.*`) is rendered
|
|
224
|
+
in the recipient's saved `user_settings.locale` when the recipient already
|
|
225
|
+
has an account, and in English otherwise. Its expiry date is written with
|
|
226
|
+
`Intl` in that locale and the recipient's saved time zone (UTC otherwise).
|
|
227
|
+
The app's invite mailer also receives the chosen `locale`.
|
|
228
|
+
- JSKIT's accounts hub (`@jskit-ai/oidc-issuer-core`) sends the account
|
|
229
|
+
confirmation, password recovery, Google link and test emails itself, from
|
|
230
|
+
`jskit.accounts.*`. Hub accounts keep no saved language, so each email
|
|
231
|
+
follows the request that sent it: the app's `ui_locales`, then the browser's
|
|
232
|
+
`Accept-Language`, then English. The hub reads the hub project's
|
|
233
|
+
`src/locales/<code>/jskit.json`; its README has the details.
|
|
195
234
|
|
|
196
235
|
Server code that renders JSKIT-style messages itself uses the same lookup:
|
|
197
236
|
|
|
@@ -202,9 +241,10 @@ const i18n = createServerI18n({ appRoot, catalogs: [english] });
|
|
|
202
241
|
i18n.t("it-IT", "jskit.workspaces.inviteEmail.subject", { workspace: "Acme" });
|
|
203
242
|
```
|
|
204
243
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
244
|
+
An app that signs in through JSKIT's accounts hub gets its password-reset
|
|
245
|
+
email from the hub, translated as above. With another identity provider
|
|
246
|
+
(Supabase, a third-party OIDC issuer) the provider sends it, so its language is
|
|
247
|
+
the provider's choice.
|
|
208
248
|
|
|
209
249
|
## What the app translates itself
|
|
210
250
|
|
|
@@ -223,6 +263,12 @@ JSKIT's catalogs cover JSKIT's own code. These texts belong to the app:
|
|
|
223
263
|
|
|
224
264
|
Each JSKIT package with a catalog has a test that compiles every message with
|
|
225
265
|
vue-i18n, requires every key and dotted code its source uses to exist, rejects
|
|
226
|
-
unused keys and refuses a key another package already defines.
|
|
266
|
+
unused keys and refuses a key another package already defines. It also requires
|
|
267
|
+
an undotted code sent with fixed English to have its `jskit.errors.<code>`
|
|
268
|
+
entry (or a `messageCode`), and a literal `{ code, message }` to send its
|
|
269
|
+
catalog's English. A browser test exports a pseudo-locale with
|
|
270
|
+
`jskit i18n export`, switches a fixture app to it, and fails on any English left
|
|
271
|
+
on the sign-in, registration, password reset, sign-out, profile menu, account
|
|
272
|
+
settings and error screens. ESLint's
|
|
227
273
|
`@intlify/vue-i18n/no-raw-text` rule rejects untranslated template text in JSKIT
|
|
228
274
|
client code.
|
|
@@ -26,7 +26,7 @@ template or relative string raw to Vue Router `to`.
|
|
|
26
26
|
## Back navigation
|
|
27
27
|
|
|
28
28
|
Check every page for a visible Back button that returns to the previous page.
|
|
29
|
-
Omit it only when returning makes no product sense, such as the
|
|
29
|
+
Omit it only when returning makes no product sense, such as the root
|
|
30
30
|
landing page or a completed flow that must not reopen an expired step. State
|
|
31
31
|
the reason in the implementation or review result; a drawer link is not Back.
|
|
32
32
|
|
|
@@ -70,7 +70,6 @@ hash, pattern receipt, or tool-owned source declaration.
|
|
|
70
70
|
- Keep screens phone/task-first with drawer-independent primary actions.
|
|
71
71
|
- Use direct surfaces instead of needless nested cards.
|
|
72
72
|
- Render all meaningful loading, empty, error, permission, and retry states.
|
|
73
|
-
- Follow the Material 3 contract for targets, loading and failure feedback.
|
|
74
73
|
- Extend shared CRUD screens through public slots and composables.
|
|
75
74
|
- Keep row actions and filters near the screen unless the framework owns them.
|
|
76
75
|
- Import neutral request and CRUD UI APIs from `@jskit-ai/http-web`. Install
|
|
@@ -87,25 +86,25 @@ when another navigation affordance remains.
|
|
|
87
86
|
The drawer omits the app bar's surface label. Open and rail icons share a
|
|
88
87
|
centreline. It uses a 12px outer item inset; `navigationItemSpacing` controls
|
|
89
88
|
icon/label and label/end gaps. The normal 80px rail centres 48px targets;
|
|
90
|
-
`railWidth` and `drawerWidth` are public density/width controls.
|
|
91
|
-
the shell
|
|
92
|
-
|
|
93
|
-
Restyle shell chrome only through the `--shell-*` tokens in the
|
|
94
|
-
`shell/application-shell` pattern.
|
|
89
|
+
`railWidth` and `drawerWidth` are public density/width controls. Restyle shell
|
|
90
|
+
chrome only through the `--shell-*` tokens in the `shell/application-shell`
|
|
91
|
+
pattern, never its private CSS.
|
|
95
92
|
|
|
96
93
|
## Browser verification
|
|
97
94
|
|
|
98
95
|
Exercise user-facing changes with Playwright at compact, medium, and expanded
|
|
99
96
|
widths. Check overflow, clipped text, duplicate navigation, route placement,
|
|
100
97
|
actions, skeleton replacement, error feedback, and target sizes. Use relative
|
|
101
|
-
URLs.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
URLs. With `PLAYWRIGHT_BASE_URL` set, start no duplicate server. For Back,
|
|
99
|
+
enter the same page from two origins and verify each returns to its own origin
|
|
100
|
+
with context intact. Also check direct entry, reload, browser back/forward,
|
|
101
|
+
fixed-destination exceptions, and any unsaved-change guard.
|
|
105
102
|
|
|
106
103
|
A managed host owns its browser and may provide
|
|
107
104
|
`PLAYWRIGHT_STORAGE_STATE`; never print or commit that value, bypass it,
|
|
108
|
-
or install another browser.
|
|
105
|
+
or install another browser. If tests run signed out despite that state, report
|
|
106
|
+
the host defect with evidence and stop; never rewrite its cookies or add a login.
|
|
107
|
+
For explicitly enabled direct-local auth, use
|
|
109
108
|
`loginAsExistingUser()` from `@jskit-ai/auth-web/test/playwright`; never expose
|
|
110
109
|
the exchange secret to browser code, URLs, or client environment.
|
|
111
110
|
|
package/package.json
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
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.6",
|
|
38
38
|
"@tanstack/vue-query": "^5.101.0",
|
|
39
39
|
"fastify": "^5.8.5",
|
|
40
40
|
"pino": "^10.3.1",
|
|
@@ -43,13 +43,13 @@
|
|
|
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.6",
|
|
47
47
|
"@fastify/fast-json-stringify-compiler": "^5.1.0",
|
|
48
48
|
"@vue/devtools-api": "^8.2.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@jskit-ai/config-eslint": "0.1.
|
|
52
|
-
"@jskit-ai/jskit-catalog": "0.2.
|
|
51
|
+
"@jskit-ai/config-eslint": "0.1.245",
|
|
52
|
+
"@jskit-ai/jskit-catalog": "0.2.19",
|
|
53
53
|
"@playwright/test": "1.61.1",
|
|
54
54
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
55
55
|
"eslint": "^10.8.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
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.6",
|
|
38
38
|
"@tanstack/vue-query": "^5.101.0",
|
|
39
39
|
"fastify": "^5.8.5",
|
|
40
40
|
"pino": "^10.3.1",
|
|
@@ -43,15 +43,15 @@
|
|
|
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.6",
|
|
47
47
|
"@mdi/js": "^7.4.47",
|
|
48
|
-
"@jskit-ai/shell-web": "0.2.
|
|
48
|
+
"@jskit-ai/shell-web": "0.2.7",
|
|
49
49
|
"@fastify/fast-json-stringify-compiler": "^5.1.0",
|
|
50
50
|
"@vue/devtools-api": "^8.2.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@jskit-ai/config-eslint": "0.1.
|
|
54
|
-
"@jskit-ai/jskit-catalog": "0.2.
|
|
53
|
+
"@jskit-ai/config-eslint": "0.1.245",
|
|
54
|
+
"@jskit-ai/jskit-catalog": "0.2.19",
|
|
55
55
|
"@playwright/test": "1.61.1",
|
|
56
56
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
57
57
|
"eslint": "^10.8.0",
|