@jskit-ai/agent-docs 0.1.247 → 0.1.249

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.
Files changed (55) hide show
  1. package/guide/agent/app-extras/assistant-conversation.md +4 -2
  2. package/guide/agent/framework/translation.md +227 -0
  3. package/guide/agent/index.md +1 -0
  4. package/package.json +1 -1
  5. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  6. package/patterns/minimal-foundation/example/package.json +3 -3
  7. package/patterns/shell-foundation/example/package.json +4 -4
  8. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  9. package/reference/autogen/KERNEL_MAP.md +27 -2
  10. package/reference/autogen/PATTERN_INDEX.md +37 -37
  11. package/reference/autogen/packages/assistant-core.md +21 -3
  12. package/reference/autogen/packages/assistant-runtime.md +15 -0
  13. package/reference/autogen/packages/assistant-voice.md +13 -5
  14. package/reference/autogen/packages/auth-core.md +14 -1
  15. package/reference/autogen/packages/auth-provider-local-core.md +1 -1
  16. package/reference/autogen/packages/auth-web.md +12 -2
  17. package/reference/autogen/packages/connector-google-calendar.md +6 -1
  18. package/reference/autogen/packages/connectors-catalog.md +19 -4
  19. package/reference/autogen/packages/connectors-core.md +5 -1
  20. package/reference/autogen/packages/connectors-web.md +5 -0
  21. package/reference/autogen/packages/http-runtime.md +6 -3
  22. package/reference/autogen/packages/http-web.md +27 -18
  23. package/reference/autogen/packages/kernel.md +74 -7
  24. package/reference/autogen/packages/mobile-capacitor.md +6 -1
  25. package/reference/autogen/packages/payments-core.md +2 -2
  26. package/reference/autogen/packages/payments-web.md +8 -0
  27. package/reference/autogen/packages/realtime.md +5 -0
  28. package/reference/autogen/packages/rewarded-web.md +5 -0
  29. package/reference/autogen/packages/shell-web.md +13 -3
  30. package/reference/autogen/packages/uploads-image-web.md +5 -0
  31. package/reference/autogen/packages/uploads-runtime.md +1 -1
  32. package/reference/autogen/packages/users-core.md +1 -0
  33. package/reference/autogen/packages/users-web.md +22 -0
  34. package/reference/autogen/packages/workspaces-core.md +10 -3
  35. package/reference/autogen/packages/workspaces-web.md +4 -0
  36. package/reference/autogen/tooling/jskit-catalog.md +28 -0
  37. package/skills/jskit/SKILL.md +3 -3
  38. package/skills/jskit/references/pattern-index.md +37 -37
  39. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +3 -3
  40. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +4 -4
  41. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  42. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  43. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  44. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  45. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  46. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
  47. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  48. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  49. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  50. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
  51. package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +10 -0
  52. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
  53. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
  54. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +7 -0
  55. package/skills/jskit/references/translation.md +227 -0
@@ -3212,8 +3212,10 @@ operation `"invalidateRuntimes"` and supplies the existing native owner
3212
3212
  synchronously. The runtime returns the native operation directly: shutdown
3213
3213
  fences and synchronous errors are not deferred behind another await. The host
3214
3214
  retains account policy and result presentation; the native owner retains its
3215
- original cleanup sequence and retryable failures. No conversation is opened,
3216
- and failed cleanup can be retried after runtime closure. This is not a browser
3215
+ original cleanup sequence and retryable failures. No conversation is opened:
3216
+ each native owner stops the processes this server runs, since none outlives the
3217
+ server that started it, and saved conversations are not reopened to be stopped.
3218
+ Failed cleanup can be retried after runtime closure. This is not a browser
3217
3219
  operation or a way to submit a caller-selected native owner.
3218
3220
 
3219
3221
  `runtime.reconcileNativeSessions({ context, sessions, options })` restores an
@@ -0,0 +1,227 @@
1
+ <!-- Generated by `npm run agent-docs:build` from `packages/agent-docs/site/guide/framework/translation.md`. Do not edit manually. -->
2
+
3
+ # Translating a JSKIT app
4
+
5
+ JSKIT ships every screen, message and error in English and can show all of them
6
+ in another language. An app supplies translation files only: it never copies or
7
+ overrides JSKIT components to translate them. An app that supplies no
8
+ translations looks and behaves exactly as an English-only app.
9
+
10
+ ## How it fits together
11
+
12
+ - Every JSKIT package with user-visible text ships `locales/en.json`, a nested
13
+ catalog under its own namespace: `jskit.auth.*`, `jskit.users.*`,
14
+ `jskit.shell.*`, `jskit.http.*`, and so on.
15
+ - JSKIT components translate through the app's
16
+ [vue-i18n](https://vue-i18n.intlify.dev/) instance when the app supplies one,
17
+ and through the bundled English otherwise. `vue-i18n` is an optional peer
18
+ dependency; install it only when the app is translated.
19
+ - The server never decides the language of an error. Every error response
20
+ carries a stable `code`, its `params` and the English `message`; the client
21
+ renders the code in the user's language.
22
+ - Choosing and switching the language is the app's job. JSKIT components follow
23
+ vue-i18n's active locale.
24
+
25
+ ## Pass the app's vue-i18n instance
26
+
27
+ Create the instance in composition mode and give it to the client bootstrap:
28
+
29
+ ```js
30
+ import { createI18n } from "vue-i18n";
31
+ import { bootstrapClientShellApp } from "@jskit-ai/kernel/client";
32
+ import it from "./locales/it/jskit.json" with { type: "json" };
33
+
34
+ const i18n = createI18n({
35
+ legacy: false,
36
+ locale: "en",
37
+ fallbackLocale: "en",
38
+ messages: { it }
39
+ });
40
+
41
+ await bootstrapClientShellApp({ /* existing options */, i18n });
42
+ ```
43
+
44
+ The bootstrap installs the instance (unless `appPlugins` already does) and
45
+ merges every installed package's English into its `en` messages. The app's own
46
+ `en` messages win, so an app can reword a JSKIT text by defining the same key.
47
+ JSKIT refuses a legacy-mode instance (`createI18n({ legacy: true })`).
48
+
49
+ ## Add a language
50
+
51
+ 1. Write the merged English of the app's installed JSKIT packages to a file for
52
+ translators:
53
+
54
+ ```bash
55
+ npx jskit i18n export it
56
+ ```
57
+
58
+ This creates `src/locales/it/jskit.json`. Running it again after upgrading
59
+ JSKIT adds new keys in English and keeps every existing translation.
60
+ 2. Translate the values. Keep every `{placeholder}` exactly; plural messages
61
+ keep the same number of `|`-separated choices as the English.
62
+ 3. Check the file against the installed packages:
63
+
64
+ ```bash
65
+ npx jskit i18n check it
66
+ ```
67
+
68
+ It reports missing and extra keys, invalid messages, placeholder and plural
69
+ mismatches, and (as warnings) values still identical to the English. It exits
70
+ non-zero when keys are missing, a message is invalid or placeholders differ,
71
+ so it can run in CI.
72
+ 4. Load the file into the vue-i18n instance under its locale code, as above.
73
+
74
+ Missing keys fall back to English, so a partly translated language still works.
75
+
76
+ ### Message syntax
77
+
78
+ JSKIT catalogs use a subset of vue-i18n's syntax, and translations must too:
79
+
80
+ - named placeholders: `Use at least {min} characters.`
81
+ - literal text in quotes for the characters `{ } @ $ |`: `support{'@'}example.com`
82
+ - plural choices separated by `|`, chosen by `count`:
83
+ `{count} file | {count} files` (one | other) or
84
+ `no files | one file | {count} files` (zero | one | other)
85
+
86
+ Linked messages (`@:key`), list placeholders (`{0}`) and HTML are not used.
87
+
88
+ ## Use the user's saved language
89
+
90
+ Account preferences store the user's language in `user_settings.locale` as a
91
+ BCP 47 code (for example `it-IT`). The "Language / locale" select offers the
92
+ app's configured languages:
93
+
94
+ ```js
95
+ // config/public.js
96
+ config.languages = [
97
+ { code: "en-US", name: "English (US)" },
98
+ { code: "it-IT", name: "Italiano" }
99
+ ];
100
+ ```
101
+
102
+ Each `name` may also be a message key. A saved locale that is not among the
103
+ configured languages stays selectable under its language name. Without
104
+ `config.languages` the select keeps JSKIT's built-in list, unchanged.
105
+
106
+ JSKIT never switches the app's language itself. `useAccountLocale()` from
107
+ `@jskit-ai/users-web/client` is a read-only ref holding the signed-in user's
108
+ saved locale (`""` when nobody is signed in); it updates after sign-in and after
109
+ the preferences are saved. Follow it in the app:
110
+
111
+ ```js
112
+ import { watch } from "vue";
113
+ import { useAccountLocale } from "@jskit-ai/users-web/client";
114
+
115
+ watch(useAccountLocale(), (locale) => {
116
+ if (locale) i18n.global.locale.value = pickSupportedLocale(locale);
117
+ }, { immediate: true });
118
+ ```
119
+
120
+ `pickSupportedLocale` is the app's own choice, for example `it-IT` → `it` when
121
+ the app ships only `src/locales/it/jskit.json`.
122
+
123
+ ## How errors are shown
124
+
125
+ Every error response from a JSKIT HTTP API has a `code` and `params` next to
126
+ the English `message`:
127
+
128
+ ```json
129
+ { "error": "Invalid email or password.", "code": "auth.login.invalidCredentials", "params": {} }
130
+ ```
131
+
132
+ - Codes added for translation are dotted (`<namespace>.<area>.<name>`) and
133
+ render from the key `jskit.<code>`.
134
+ - Older codes such as `ACTION_PERMISSION_DENIED` or `not_found` keep their
135
+ values and render from `jskit.errors.<code>`.
136
+ - Validation errors keep `details.fieldErrors` (English) and add
137
+ `details.fieldErrorCodes: { field: { code, params } }`.
138
+ - Where one code covers several different sentences (for example
139
+ `connector_input_invalid`), the response also has `messageCode` and
140
+ `messageParams` for the exact sentence.
141
+
142
+ The client translates a code only when the English the server sent is JSKIT's
143
+ English for that code. An app's own sentence under a shared code (for example
144
+ `throw new NotFoundError("Contact not found.")`) is shown exactly as written, and
145
+ so is any text whose code has no catalog entry.
146
+
147
+ App code that shows errors uses the same helper JSKIT's components use:
148
+
149
+ ```js
150
+ import { useJskitText } from "@jskit-ai/kernel/client";
151
+
152
+ const { serverMessage, fieldErrorMessages } = useJskitText();
153
+ const message = serverMessage(error); // translated, or the English sent
154
+ const fieldMessages = fieldErrorMessages(error); // { field: text }
155
+ ```
156
+
157
+ To give the app's own errors codes, throw them with a code and params and add
158
+ the app's English and translations to its vue-i18n messages under the key the
159
+ code maps to:
160
+
161
+ ```js
162
+ throw new AppError(409, "That slug is taken.", { code: "app.project.slugTaken" });
163
+ // en: { jskit: { app: { project: { slugTaken: "That slug is taken." } } } }
164
+ ```
165
+
166
+ ## Placement labels
167
+
168
+ A placement `label` or `title` may be a message key, `{ key, fallback, params }`
169
+ or plain text. JSKIT's menus, tabs, profile menu and account-settings sections
170
+ translate a key and show any other string as written:
171
+
172
+ ```js
173
+ { label: "jskit.users.accountSettings.menuLabel" }
174
+ { label: { key: "app.menu.reports", fallback: "Reports" } }
175
+ { label: "Reports" }
176
+ ```
177
+
178
+ ## Dates and numbers
179
+
180
+ JSKIT formats dates, times, numbers and relative times with `Intl` in the
181
+ active vue-i18n locale. Without an instance, each text keeps the format it had
182
+ before translation support (usually the browser's default).
183
+ App code can use the same helpers from `useJskitText()`: `formatDate`,
184
+ `formatTime`, `formatDateTime`, `formatNumber` and `formatRelativeTime`.
185
+
186
+ ## Emails
187
+
188
+ The workspace invitation email is rendered in the recipient's saved
189
+ `user_settings.locale` when the recipient already has an account, and in English
190
+ otherwise. The server reads the same `src/locales/<code>/jskit.json` files the
191
+ client uses, so translating `jskit.workspaces.inviteEmail.*` there translates
192
+ the email too. It looks for the exact locale (`it-IT`), then the language
193
+ (`it`), then English. The app's invite mailer also receives the chosen `locale`.
194
+
195
+ Server code that renders JSKIT-style messages itself uses the same lookup:
196
+
197
+ ```js
198
+ import { createServerI18n } from "@jskit-ai/kernel/server/i18n";
199
+
200
+ const i18n = createServerI18n({ appRoot, catalogs: [english] });
201
+ i18n.t("it-IT", "jskit.workspaces.inviteEmail.subject", { workspace: "Acme" });
202
+ ```
203
+
204
+ Password-reset emails are sent by the app's own recovery sender (local
205
+ accounts) or by the identity provider (Supabase, OIDC), so their language is
206
+ the app's or the provider's choice.
207
+
208
+ ## What the app translates itself
209
+
210
+ JSKIT's catalogs cover JSKIT's own code. These texts belong to the app:
211
+
212
+ - Vuetify's built-in texts (close buttons, pagination, "No data available").
213
+ Translate them through Vuetify's locale options, or let Vuetify share the
214
+ vue-i18n instance with its `createVueI18nAdapter`.
215
+ - Files the app copied from a JSKIT starter or pattern, such as its
216
+ account-settings sections, placement entries and pages. Once copied they are
217
+ app code: give their texts the app's own keys.
218
+ - The startup HTML in `index.html` (for example "Loading application…"), shown
219
+ before any JavaScript runs.
220
+
221
+ ## Checks inside JSKIT
222
+
223
+ Each JSKIT package with a catalog has a test that compiles every message with
224
+ vue-i18n, requires every key and dotted code its source uses to exist, rejects
225
+ unused keys and refuses a key another package already defines. ESLint's
226
+ `@intlify/vue-i18n/no-raw-text` rule rejects untranslated template text in JSKIT
227
+ client code.
@@ -28,6 +28,7 @@ apply or adapt. It does not prescribe an agent host or project orchestrator.
28
28
  - [Record form actions](/guide/framework/crud-form-actions)
29
29
  - [UI operations](/guide/framework/ui-operations)
30
30
  - [Material 3](/guide/framework/material-3)
31
+ - [Translating a JSKIT app](/guide/framework/translation)
31
32
  - [Complete source pattern library](/patterns/)
32
33
 
33
34
  ## Optional capabilities
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.247",
3
+ "version": "0.1.249",
4
4
  "description": "Distributed JSKIT agent references, prompts, guides, and generated reference maps.",
5
5
  "type": "module",
6
6
  "files": [
@@ -5,7 +5,7 @@
5
5
  "private": true,
6
6
  "type": "module",
7
7
  "dependencies": {
8
- "@jskit-ai/kernel": "0.1.248",
8
+ "@jskit-ai/kernel": "0.2.0",
9
9
  "json-rest-schema": "^1.0.17"
10
10
  },
11
11
  "exports": {
@@ -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.1.248",
37
+ "@jskit-ai/kernel": "0.2.0",
38
38
  "@tanstack/vue-query": "^5.101.0",
39
39
  "fastify": "^5.8.5",
40
40
  "json-rest-schema": "^1.0.17",
@@ -42,13 +42,13 @@
42
42
  "vue": "^3.5.44",
43
43
  "vue-router": "^5.3.1",
44
44
  "vuetify": "^4.1.2",
45
- "@jskit-ai/http-runtime": "0.1.246",
45
+ "@jskit-ai/http-runtime": "0.2.0",
46
46
  "@fastify/fast-json-stringify-compiler": "^5.1.0",
47
47
  "@vue/devtools-api": "^8.2.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@jskit-ai/config-eslint": "0.1.241",
51
- "@jskit-ai/jskit-catalog": "0.1.300",
51
+ "@jskit-ai/jskit-catalog": "0.2.1",
52
52
  "@playwright/test": "1.61.1",
53
53
  "@vitejs/plugin-vue": "^6.0.7",
54
54
  "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.1.248",
37
+ "@jskit-ai/kernel": "0.2.0",
38
38
  "@tanstack/vue-query": "^5.101.0",
39
39
  "fastify": "^5.8.5",
40
40
  "json-rest-schema": "^1.0.17",
@@ -42,15 +42,15 @@
42
42
  "vue": "^3.5.44",
43
43
  "vue-router": "^5.3.1",
44
44
  "vuetify": "^4.1.2",
45
- "@jskit-ai/http-runtime": "0.1.246",
45
+ "@jskit-ai/http-runtime": "0.2.0",
46
46
  "@mdi/js": "^7.4.47",
47
- "@jskit-ai/shell-web": "0.1.255",
47
+ "@jskit-ai/shell-web": "0.2.0",
48
48
  "@fastify/fast-json-stringify-compiler": "^5.1.0",
49
49
  "@vue/devtools-api": "^8.2.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@jskit-ai/config-eslint": "0.1.241",
53
- "@jskit-ai/jskit-catalog": "0.1.300",
53
+ "@jskit-ai/jskit-catalog": "0.2.1",
54
54
  "@playwright/test": "1.61.1",
55
55
  "@vitejs/plugin-vue": "^6.0.7",
56
56
  "eslint": "^10.8.0",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "description": "App-local runtime composition and lightweight glue.",
11
11
  "dependencies": {
12
- "@jskit-ai/kernel": "0.1.248"
12
+ "@jskit-ai/kernel": "0.2.0"
13
13
  },
14
14
  "jskit": {
15
15
  "kind": "runtime",
@@ -278,7 +278,9 @@ Exports
278
278
  - `resolveSchemaTransportSchemaDefinition`
279
279
  - `executeJsonRestSchemaDefinition`
280
280
  - `buildSchemaValidationError`
281
+ - `codedFieldErrors`
281
282
  - `validateSchemaPayload`
283
+ - `resolveValidationIssueCode`
282
284
  - `RECORD_ID_PATTERN`
283
285
  - `recordIdSchema`
284
286
  - `nullableRecordIdSchema`
@@ -301,7 +303,8 @@ Local functions
301
303
  - `requireJsonRestSchemaInstance(schemaDefinition = null, { context = "schema definition.schema" } = {})`
302
304
  - `resolveJsonRestSchemaFieldMessages(schemaDefinition = null, fieldName = "")`
303
305
  - `resolveJsonRestSchemaParentFieldMessages(schemaDefinition = null, fieldName = "")`
304
- - `resolveJsonRestSchemaFieldErrorMessage(fieldName, entry, schemaDefinition = null)`
306
+ - `resolveFieldMessageOverride(messages, key)`
307
+ - `resolveJsonRestSchemaFieldError(fieldName, entry, schemaDefinition = null)`
305
308
 
306
309
  ### `validators/mergeObjectSchemas.js`
307
310
  Exports
@@ -335,9 +338,15 @@ Local functions
335
338
 
336
339
  ### `validators/schemaPayloadValidation.js`
337
340
  Exports
338
- - `buildSchemaValidationError({ message = "Schema validation failed.", fieldErrors = null, errors = null, cause, statusCode = null } = {})`
341
+ - `buildSchemaValidationError({ message = SCHEMA_VALIDATION_FAILED_MESSAGE, fieldErrors = null, fieldErrorCodes = null, errors = null, cause, statusCode = null } = {})`
342
+ - `codedFieldErrors(error)`
343
+ - `errorFieldErrors(error)`
339
344
  - `validateSchemaPayload(schemaDefinition, payload, { phase = "input", context = "schema definition", statusCode = null } = {})`
340
345
 
346
+ ### `validators/validationIssueCodes.js`
347
+ Exports
348
+ - `resolveValidationIssueCode(issue = {})`
349
+
341
350
  ### root
342
351
 
343
352
  ### `index.js`
@@ -373,3 +382,19 @@ Local functions
373
382
  - `buildProviderOrder(providers, inputCapabilities)`
374
383
  - `resolveProviderDependencies(provider, capabilities)`
375
384
  - `normalizeProviderOutputs(provider, value)`
385
+
386
+ ### i18n
387
+
388
+ ### `i18n/index.js`
389
+ Exports
390
+ - `catalogMessage(catalog, key = "")`
391
+ - `flattenCatalog(catalog, prefix = "")`
392
+ - `formatMessage(template = "", params = {})`
393
+ - `mergeCatalogs(...catalogs)`
394
+ - `messageKeyForCode(code = "")`
395
+ - `messageParams(template = "")`
396
+ Local functions
397
+ - `isRecord(value)`
398
+ - `placeholderEnd(template, start)`
399
+ - `parseMessage(template = "")`
400
+ - `pluralChoice(count, choices)`