modelroom 0.0.6 → 0.1.0

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 (64) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +40 -8
  3. package/dist/bin/modelroom.js +241 -75
  4. package/dist/bin/modelroom.js.map +1 -1
  5. package/dist/lib/agents/index.d.ts.map +1 -1
  6. package/dist/lib/agents/index.js +19 -4
  7. package/dist/lib/agents/index.js.map +1 -1
  8. package/dist/lib/artifact.d.ts +1 -1
  9. package/dist/lib/artifact.d.ts.map +1 -1
  10. package/dist/lib/artifact.js +9 -5
  11. package/dist/lib/artifact.js.map +1 -1
  12. package/dist/lib/config.d.ts +17 -1
  13. package/dist/lib/config.d.ts.map +1 -1
  14. package/dist/lib/config.js +40 -4
  15. package/dist/lib/config.js.map +1 -1
  16. package/dist/lib/frontmatter.d.ts +2 -0
  17. package/dist/lib/frontmatter.d.ts.map +1 -1
  18. package/dist/lib/frontmatter.js +11 -2
  19. package/dist/lib/frontmatter.js.map +1 -1
  20. package/dist/lib/i18n.d.ts +315 -0
  21. package/dist/lib/i18n.d.ts.map +1 -0
  22. package/dist/lib/i18n.js +651 -0
  23. package/dist/lib/i18n.js.map +1 -0
  24. package/dist/lib/lang.d.ts +4 -0
  25. package/dist/lib/lang.d.ts.map +1 -0
  26. package/dist/lib/lang.js +5 -0
  27. package/dist/lib/lang.js.map +1 -0
  28. package/dist/lib/lint.d.ts +3 -0
  29. package/dist/lib/lint.d.ts.map +1 -1
  30. package/dist/lib/lint.js +22 -12
  31. package/dist/lib/lint.js.map +1 -1
  32. package/dist/lib/locale.d.ts +9 -0
  33. package/dist/lib/locale.d.ts.map +1 -0
  34. package/dist/lib/locale.js +32 -0
  35. package/dist/lib/locale.js.map +1 -0
  36. package/dist/lib/server.d.ts +3 -0
  37. package/dist/lib/server.d.ts.map +1 -1
  38. package/dist/lib/server.js +44 -27
  39. package/dist/lib/server.js.map +1 -1
  40. package/dist/lib/templates.d.ts +7 -0
  41. package/dist/lib/templates.d.ts.map +1 -0
  42. package/dist/lib/templates.js +30 -0
  43. package/dist/lib/templates.js.map +1 -0
  44. package/docs/02-convention.md +10 -5
  45. package/docs/03-cli.md +59 -14
  46. package/docs/04-agents.md +10 -2
  47. package/package.json +9 -19
  48. package/templates/{AGENTS.md → en/AGENTS.md} +8 -3
  49. package/templates/ja/AGENTS.md +38 -0
  50. package/templates/ja/room/BEHAVIOUR.md +18 -0
  51. package/templates/ja/room/BRIEF.md +16 -0
  52. package/templates/ja/room/SPEC.md +9 -0
  53. package/templates/ja/room/index.html +53 -0
  54. package/templates/modelroom.json +3 -1
  55. package/ui/assets/app.js +120 -47
  56. package/ui/dashboard.html +11 -7
  57. package/ui/kit.html +13 -9
  58. package/ui/modelroom.css +1 -2
  59. package/ui/room.html +11 -7
  60. package/ui/settings.html +11 -7
  61. /package/templates/{room → en/room}/BEHAVIOUR.md +0 -0
  62. /package/templates/{room → en/room}/BRIEF.md +0 -0
  63. /package/templates/{room → en/room}/SPEC.md +0 -0
  64. /package/templates/{room → en/room}/index.html +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../lib/i18n.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type Lang = 'en' | 'ja';
2
+ export declare const LANGS: readonly Lang[];
3
+ export declare const isLang: (value: unknown) => value is Lang;
4
+ //# sourceMappingURL=lang.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../../lib/lang.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC/B,eAAO,MAAM,KAAK,EAAE,SAAS,IAAI,EAAiB,CAAC;AACnD,eAAO,MAAM,MAAM,UAAW,OAAO,KAAG,KAAK,IAAI,IAAwC,CAAC"}
@@ -0,0 +1,5 @@
1
+ // The languages the package ships. Kept apart from config.ts so the browser
2
+ // bundle can import the catalogs without dragging Node's filesystem in.
3
+ export const LANGS = ['en', 'ja'];
4
+ export const isLang = (value) => value === 'en' || value === 'ja';
5
+ //# sourceMappingURL=lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.js","sourceRoot":"","sources":["../../lib/lang.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,wEAAwE;AAGxE,MAAM,CAAC,MAAM,KAAK,GAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAc,EAAiB,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC"}
@@ -1,9 +1,11 @@
1
+ import type { Lang } from './lang.ts';
1
2
  export type IssueLevel = 'error' | 'warn';
2
3
  export interface LintIssue {
3
4
  level: IssueLevel;
4
5
  room: string;
5
6
  file: string | null;
6
7
  code: string;
8
+ params?: Record<string, string | number>;
7
9
  message: string;
8
10
  }
9
11
  export interface LintStats {
@@ -14,6 +16,7 @@ export interface LintStats {
14
16
  export interface LintConfig {
15
17
  roomsDir: string;
16
18
  docs: string[];
19
+ lang?: Lang;
17
20
  }
18
21
  /**
19
22
  * Check every room. Returns `{ issues, stats }`.
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../lib/lint.ts"],"names":[],"mappings":"AAmCA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AA4BD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,UAAU,GACd,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC,CAyHpD"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../lib/lint.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAwBtC,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AA4BD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,UAAU,GACd,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC,CA0GpD"}
package/dist/lib/lint.js CHANGED
@@ -9,6 +9,7 @@ import { join } from 'node:path';
9
9
  import { readFrontmatterFile } from './frontmatter.js';
10
10
  import { listRoomNames } from './rooms.js';
11
11
  import { normalize } from './facets.js';
12
+ import { t } from './i18n.js';
12
13
  /** Reserved keys and the shapes they must keep. Everything else is free. */
13
14
  const RESERVED_TYPES = {
14
15
  id: ['string'],
@@ -56,12 +57,14 @@ function variantGroups(entries) {
56
57
  * `issues[].level` is 'error' (fixable by an agent) or 'warn' (needs a human).
57
58
  */
58
59
  export async function lintRooms(cfg) {
60
+ const lang = cfg.lang ?? 'en';
59
61
  const names = await listRoomNames(cfg);
60
62
  const issues = [];
61
63
  const variants = [];
62
64
  const seen = new Set(names);
63
- const add = (level, room, file, code, message) => {
64
- issues.push({ level, room, file: file || null, code, message });
65
+ const add = (level, room, file, code, params) => {
66
+ const message = t(lang, code, params);
67
+ issues.push({ level, room, file: file || null, code, params, message });
65
68
  };
66
69
  for (const room of names) {
67
70
  for (const file of cfg.docs) {
@@ -73,25 +76,29 @@ export async function lintRooms(cfg) {
73
76
  continue; // a missing doc is reported by `doctor`, not here
74
77
  }
75
78
  for (const issue of doc.issues) {
76
- add('error', room, file, issue.code, issue.message);
79
+ add('error', room, file, issue.code, issue.params);
77
80
  }
78
81
  const data = doc.data || {};
79
82
  for (const [key, value] of Object.entries(data)) {
80
83
  const allowed = RESERVED_TYPES[key];
81
84
  if (allowed) {
82
- const t = typeOf(value);
83
- if (value !== null && !allowed.includes(t)) {
84
- add('error', room, file, 'reserved-type', `${key} must be ${allowed.join(' or ')}, got ${t}`);
85
+ const kind = typeOf(value);
86
+ if (value !== null && !allowed.includes(kind)) {
87
+ add('error', room, file, 'reserved-type', {
88
+ key,
89
+ allowed: allowed.join(` ${t(lang, 'lint.or')} `),
90
+ got: kind,
91
+ });
85
92
  }
86
93
  if (key === 'tags' &&
87
94
  Array.isArray(value) &&
88
95
  value.some((v) => typeof v === 'object' || Array.isArray(v))) {
89
- add('error', room, file, 'tags-shape', 'tags must be a flat list of strings');
96
+ add('error', room, file, 'tags-shape');
90
97
  }
91
98
  }
92
99
  for (const [canonical, aliases] of Object.entries(SYNONYMS)) {
93
100
  if (aliases.includes(key) && data[canonical] !== undefined) {
94
- add('warn', room, file, 'synonym', `${key} duplicates ${canonical} — keep one`);
101
+ add('warn', room, file, 'synonym', { key, canonical });
95
102
  }
96
103
  }
97
104
  if (['status', 'category', 'type'].includes(key) &&
@@ -101,12 +108,15 @@ export async function lintRooms(cfg) {
101
108
  }
102
109
  }
103
110
  if (!doc.hasFrontmatter && file === cfg.docs[0]) {
104
- add('warn', room, file, 'no-frontmatter', 'no frontmatter — add title, summary and tags');
111
+ add('warn', room, file, 'no-frontmatter');
105
112
  }
106
113
  if (file === cfg.docs[0] && data.title) {
107
114
  const h1 = /^#\s+(.+)$/m.exec(doc.body || '');
108
115
  if (h1 && normalize(h1[1].trim()) !== normalize(data.title)) {
109
- add('warn', room, file, 'h1-title', `H1 "${h1[1].trim()}" differs from title "${String(data.title)}"`);
116
+ add('warn', room, file, 'h1-title', {
117
+ h1: h1[1].trim(),
118
+ title: String(data.title),
119
+ });
110
120
  }
111
121
  }
112
122
  }
@@ -114,7 +124,7 @@ export async function lintRooms(cfg) {
114
124
  for (const group of variantGroups(variants)) {
115
125
  const values = group.map((x) => x.value).join(' / ');
116
126
  for (const item of group) {
117
- add('warn', item.room, item.file, 'variant', `${item.key}: ${values} — same value, different spelling`);
127
+ add('warn', item.room, item.file, 'variant', { key: item.key, values });
118
128
  }
119
129
  }
120
130
  for (const room of names) {
@@ -128,7 +138,7 @@ export async function lintRooms(cfg) {
128
138
  }
129
139
  const target = doc.data?.superseded_by;
130
140
  if (typeof target === 'string' && target && !seen.has(target)) {
131
- add('warn', room, file, 'superseded-missing', `superseded_by points to a room that does not exist: ${target}`);
141
+ add('warn', room, file, 'superseded-missing', { target });
132
142
  }
133
143
  }
134
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../lib/lint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../lib/lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Lang } from './lang.ts';
2
+ /** `ja_JP.UTF-8`, `ja-JP`, `Japanese_Japan` → `ja`; everything else → `en`. */
3
+ export declare function normalizeLang(value: string | null | undefined): Lang;
4
+ /** The OS / shell language, without looking at any config file. */
5
+ export declare function detectLang(env?: NodeJS.ProcessEnv): {
6
+ lang: Lang;
7
+ source: 'env' | 'default';
8
+ };
9
+ //# sourceMappingURL=locale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../lib/locale.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAOpE;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG;IAChE,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC;CAC3B,CAaA"}
@@ -0,0 +1,32 @@
1
+ // modelroom — which language the tool should speak.
2
+ //
3
+ // The committed `lang` in modelroom.json wins. Before there is a config (or
4
+ // when it has no lang yet), the environment and the OS locale decide. Only the
5
+ // languages the package ships are returned; everything else is English.
6
+ /** `ja_JP.UTF-8`, `ja-JP`, `Japanese_Japan` → `ja`; everything else → `en`. */
7
+ export function normalizeLang(value) {
8
+ const tag = String(value ?? '')
9
+ .trim()
10
+ .toLowerCase();
11
+ if (!tag)
12
+ return 'en';
13
+ if (tag.startsWith('ja') || tag.includes('japanese'))
14
+ return 'ja';
15
+ return 'en';
16
+ }
17
+ /** The OS / shell language, without looking at any config file. */
18
+ export function detectLang(env = process.env) {
19
+ const candidates = [env.MODELROOM_LANG, env.LC_ALL, env.LC_MESSAGES, env.LANG].filter((value) => Boolean(value && value.trim() && value !== 'C' && value !== 'POSIX'));
20
+ for (const candidate of candidates)
21
+ return { lang: normalizeLang(candidate), source: 'env' };
22
+ try {
23
+ const locale = new Intl.DateTimeFormat().resolvedOptions().locale;
24
+ if (locale)
25
+ return { lang: normalizeLang(locale), source: 'env' };
26
+ }
27
+ catch {
28
+ /* no Intl: fall through */
29
+ }
30
+ return { lang: 'en', source: 'default' };
31
+ }
32
+ //# sourceMappingURL=locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["../../lib/locale.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,4EAA4E;AAC5E,+EAA+E;AAC/E,wEAAwE;AAIxE,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,KAAgC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SAC5B,IAAI,EAAE;SACN,WAAW,EAAE,CAAC;IACjB,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,UAAU,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAI7D,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CACnF,CAAC,KAAK,EAAmB,EAAE,CACzB,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,OAAO,CAAC,CACvE,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC7F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC;QAClE,IAAI,MAAM;YAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC3C,CAAC"}
@@ -33,6 +33,8 @@ export interface CreateOptions {
33
33
  cwd?: string;
34
34
  port?: number | string;
35
35
  host?: string;
36
+ /** Override the committed language for this run (e.g. `serve --lang ja`). */
37
+ lang?: string;
36
38
  }
37
39
  export declare function createModelroom(opts?: CreateOptions): Promise<App>;
38
40
  export declare function publicConfig(cfg: Config): {
@@ -40,6 +42,7 @@ export declare function publicConfig(cfg: Config): {
40
42
  rooms: string;
41
43
  artifact: string;
42
44
  docs: string[];
45
+ lang: import("./lang.ts").Lang;
43
46
  agent: {
44
47
  adapter: import("./config.ts").AdapterName;
45
48
  command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../lib/server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AAOpF,OAAO,EAKL,KAAK,MAAM,EAEZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAmD,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG5F,OAAO,EAAkB,mBAAmB,EAAqB,MAAM,eAAe,CAAC;AA0BvF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/C,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,eAAe,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,CA4jB5E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM;IAEpC,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,IAAI;IACJ,KAAK;QACH,OAAO;QACP,OAAO;QACP,KAAK;QACL,KAAK;QACL,UAAU;;EAGf;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../lib/server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AAOpF,OAAO,EAKL,KAAK,MAAM,EAEZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAmD,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG5F,OAAO,EAAkB,mBAAmB,EAAqB,MAAM,eAAe,CAAC;AA2BvF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/C,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,eAAe,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,CA4kB5E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM;IAEpC,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,IAAI;IACJ,IAAI;IACJ,KAAK;QACH,OAAO;QACP,OAAO;QACP,KAAK;QACL,KAAK;QACL,UAAU;;EAGf;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,CAAC"}
@@ -16,6 +16,7 @@ import { buildFacets, searchRooms } from './facets.js';
16
16
  import { getAdapter, stripAnsi } from './agents/index.js';
17
17
  import { renderArtifact, playwrightAvailable } from './artifact.js';
18
18
  import { sessionView, watchParts } from './opencode.js';
19
+ import { t } from './i18n.js';
19
20
  function isRecord(value) {
20
21
  return typeof value === 'object' && value !== null && !Array.isArray(value);
21
22
  }
@@ -42,6 +43,9 @@ export async function createModelroom(opts = {}) {
42
43
  cfg.port = Number(opts.port);
43
44
  if (opts.host)
44
45
  cfg.host = String(opts.host);
46
+ if (opts.lang === 'ja' || opts.lang === 'en')
47
+ cfg.lang = opts.lang;
48
+ const tr = (key, params) => t(cfg.lang, key, params);
45
49
  await mkdir(cfg.stateDir, { recursive: true }); // keep state local, never in git
46
50
  const state = await loadState(cfg);
47
51
  // Settings saved from the UI are local state: re-apply them over modelroom.json
@@ -52,7 +56,7 @@ export async function createModelroom(opts = {}) {
52
56
  let rendering = false;
53
57
  const status = {
54
58
  phase: 'idle',
55
- message: 'ready',
59
+ message: tr('common.ready'),
56
60
  since: Date.now(),
57
61
  lastEvent: null,
58
62
  log: [],
@@ -129,7 +133,7 @@ export async function createModelroom(opts = {}) {
129
133
  catch (err) {
130
134
  // Log locally; the browser gets no path or stack information.
131
135
  process.stderr.write(`modelroom: cannot serve ${page}: ${err instanceof Error ? err.message : String(err)}\n`);
132
- return send(res, 500, 'text/plain; charset=utf-8', 'internal error');
136
+ return send(res, 500, 'text/plain; charset=utf-8', tr('server.internal'));
133
137
  }
134
138
  }
135
139
  /** Static assets of the tool itself (the built stylesheet and friends). */
@@ -165,7 +169,7 @@ export async function createModelroom(opts = {}) {
165
169
  return;
166
170
  status.lastEvent = { file, at };
167
171
  status.phase = 'change';
168
- status.message = `changed: ${file}`;
172
+ status.message = tr('server.changed', { file });
169
173
  status.since = at;
170
174
  broadcast('change', { file, at });
171
175
  broadcast('status', { phase: 'change', message: status.message, since: at });
@@ -180,13 +184,13 @@ export async function createModelroom(opts = {}) {
180
184
  // ── chat ──────────────────────────────────────────────────────────────────
181
185
  function runChat(room, prompt) {
182
186
  if (!prompt || !prompt.trim())
183
- return { started: false, reason: 'empty prompt' };
187
+ return { started: false, reason: tr('server.emptyPrompt') };
184
188
  if (chats.has(room))
185
- return { started: false, reason: 'this room is already running' };
189
+ return { started: false, reason: tr('server.roomRunningChat') };
186
190
  const adapter = getAdapter(cfg.agent.adapter);
187
191
  const sessionId = sessionOf(room);
188
192
  const startedAt = Date.now();
189
- setStatus('chat', `${room}: agent is working…`);
193
+ setStatus('chat', tr('server.agentWorking', { room }));
190
194
  broadcast('chat-start', { room, sessionId, prompt, at: startedAt });
191
195
  broadcast('chat', {
192
196
  room,
@@ -223,7 +227,7 @@ export async function createModelroom(opts = {}) {
223
227
  if (err)
224
228
  setStatus('error', err);
225
229
  else
226
- setStatus(code === 0 ? 'ok' : 'error', `${room}: agent exited (${code})`);
230
+ setStatus(code === 0 ? 'ok' : 'error', tr('server.agentExited', { room, code }));
227
231
  broadcast('chat-done', { room, sessionId, code, error: err || null, at: Date.now() });
228
232
  })();
229
233
  },
@@ -233,14 +237,15 @@ export async function createModelroom(opts = {}) {
233
237
  // ── artifact render (optional) ────────────────────────────────────────────
234
238
  async function render(room, device) {
235
239
  if (rendering)
236
- return { ok: false, error: 'already rendering' };
240
+ return { ok: false, error: tr('server.alreadyRendering') };
241
+ const png = cfg.artifact.replace(/\.html?$/i, '.png');
237
242
  rendering = true;
238
- setStatus('rendering', `${room}: rendering ${cfg.artifact.replace(/\.html?$/i, '.png')}…`);
243
+ setStatus('rendering', tr('server.rendering', { room, file: png }));
239
244
  broadcast('render-start', { room, device, at: Date.now() });
240
245
  try {
241
246
  const result = await renderArtifact({ cfg, room, device });
242
247
  if (result.ok) {
243
- setStatus('ok', `${room}: ${cfg.artifact.replace(/\.html?$/i, '.png')} updated`);
248
+ setStatus('ok', tr('server.rendered', { room, file: png }));
244
249
  }
245
250
  else {
246
251
  setStatus('error', result.error);
@@ -305,7 +310,7 @@ export async function createModelroom(opts = {}) {
305
310
  catch (err) {
306
311
  const detail = err instanceof Error ? err.message : String(err);
307
312
  process.stderr.write(`modelroom: cannot read request body: ${detail}\n`);
308
- sendJson(res, 400, { error: 'request body could not be read' });
313
+ sendJson(res, 400, { error: tr('server.badBodyRead') });
309
314
  return null;
310
315
  }
311
316
  if (!raw.trim() && optional)
@@ -313,7 +318,7 @@ export async function createModelroom(opts = {}) {
313
318
  try {
314
319
  const parsed = JSON.parse(raw || '{}');
315
320
  if (!isRecord(parsed)) {
316
- sendJson(res, 400, { error: 'body must be a JSON object' });
321
+ sendJson(res, 400, { error: tr('server.bodyObject') });
317
322
  return null;
318
323
  }
319
324
  return parsed;
@@ -321,7 +326,7 @@ export async function createModelroom(opts = {}) {
321
326
  catch (err) {
322
327
  const detail = err instanceof Error ? err.message : String(err);
323
328
  process.stderr.write(`modelroom: invalid JSON body: ${detail}\n`);
324
- sendJson(res, 400, { error: 'body must be valid JSON' });
329
+ sendJson(res, 400, { error: tr('server.bodyJson') });
325
330
  return null;
326
331
  }
327
332
  }
@@ -335,6 +340,10 @@ export async function createModelroom(opts = {}) {
335
340
  const room = isRoomName(param) && names.includes(param) ? param : (names[0] ?? null);
336
341
  if (path === '/health')
337
342
  return send(res, 200, 'text/plain; charset=utf-8', 'ok');
343
+ // The UI asks this once before its first paint: which language to speak.
344
+ if (path === '/api/meta') {
345
+ return sendJson(res, 200, { lang: cfg.lang, config: publicConfig(cfg) });
346
+ }
338
347
  if (path === '/favicon.ico') {
339
348
  res.writeHead(204);
340
349
  return res.end();
@@ -371,7 +380,7 @@ export async function createModelroom(opts = {}) {
371
380
  }
372
381
  if (path === '/api/room') {
373
382
  if (!room)
374
- return sendJson(res, 404, { error: 'no rooms' });
383
+ return sendJson(res, 404, { error: tr('server.noRooms') });
375
384
  const info = await roomInfo(cfg, room);
376
385
  return sendJson(res, 200, {
377
386
  room: publicRoom(info),
@@ -383,10 +392,10 @@ export async function createModelroom(opts = {}) {
383
392
  if (path === '/api/doc' && req.method === 'GET') {
384
393
  const name = url.searchParams.get('name') || '';
385
394
  if (!cfg.docs.includes(name)) {
386
- return sendJson(res, 400, { error: `name must be one of ${cfg.docs.join(', ')}` });
395
+ return sendJson(res, 400, { error: tr('server.docName', { docs: cfg.docs.join(', ') }) });
387
396
  }
388
397
  if (!room)
389
- return sendJson(res, 404, { error: 'no rooms' });
398
+ return sendJson(res, 404, { error: tr('server.noRooms') });
390
399
  try {
391
400
  const p = join(cfg.roomsDir, room, name);
392
401
  const { text, mtime } = await readDoc(p);
@@ -410,9 +419,9 @@ export async function createModelroom(opts = {}) {
410
419
  const target = isRoomName(body.room) && names.includes(body.room) ? body.room : room;
411
420
  const name = typeof body.name === 'string' ? body.name : '';
412
421
  if (!target)
413
- return sendJson(res, 404, { error: 'no rooms' });
422
+ return sendJson(res, 404, { error: tr('server.noRooms') });
414
423
  if (!cfg.docs.includes(name)) {
415
- return sendJson(res, 403, { error: 'this file is not editable' });
424
+ return sendJson(res, 403, { error: tr('server.notEditable') });
416
425
  }
417
426
  const p = join(cfg.roomsDir, target, name);
418
427
  // The version this save is based on: a content hash when the client sends
@@ -435,7 +444,7 @@ export async function createModelroom(opts = {}) {
435
444
  return {
436
445
  status: 409,
437
446
  body: {
438
- error: 'changed elsewhere',
447
+ error: tr('server.changedElsewhere'),
439
448
  text: current,
440
449
  mtime: s.mtimeMs,
441
450
  hash: currentHash,
@@ -466,14 +475,14 @@ export async function createModelroom(opts = {}) {
466
475
  return sendJson(res, outcome.status, outcome.body);
467
476
  }
468
477
  if (path === '/api/doc')
469
- return sendJson(res, 405, { error: 'GET or PUT' });
478
+ return sendJson(res, 405, { error: tr('server.methodDoc') });
470
479
  if (path === '/api/chat' && req.method === 'POST') {
471
480
  const body = await jsonBody(req, res);
472
481
  if (!body)
473
482
  return;
474
483
  const target = isRoomName(body.room) && names.includes(body.room) ? body.room : room;
475
484
  if (!target)
476
- return sendJson(res, 404, { error: 'no rooms' });
485
+ return sendJson(res, 404, { error: tr('server.noRooms') });
477
486
  const r = runChat(target, typeof body.prompt === 'string' ? body.prompt : '');
478
487
  return sendJson(res, r.started ? 202 : 409, { room: target, ...r });
479
488
  }
@@ -483,9 +492,9 @@ export async function createModelroom(opts = {}) {
483
492
  return; // malformed JSON: jsonBody already answered 400
484
493
  const target = isRoomName(body.room) && names.includes(body.room) ? body.room : room;
485
494
  if (!target)
486
- return sendJson(res, 404, { error: 'no rooms' });
495
+ return sendJson(res, 404, { error: tr('server.noRooms') });
487
496
  if (chats.has(target))
488
- return sendJson(res, 409, { error: 'room is running' });
497
+ return sendJson(res, 409, { error: tr('server.roomRunning') });
489
498
  const adapter = getAdapter(cfg.agent.adapter);
490
499
  const id = adapter.newSessionId();
491
500
  state.sessions[target] = id;
@@ -496,7 +505,7 @@ export async function createModelroom(opts = {}) {
496
505
  // opencode-only, and best-effort — a failure just means `available: false`.
497
506
  if (path === '/api/session' && req.method === 'GET') {
498
507
  if (!room)
499
- return sendJson(res, 404, { error: 'no rooms' });
508
+ return sendJson(res, 404, { error: tr('server.noRooms') });
500
509
  if (cfg.agent.adapter !== 'opencode') {
501
510
  return sendJson(res, 200, { available: false, room, session: null });
502
511
  }
@@ -521,7 +530,7 @@ export async function createModelroom(opts = {}) {
521
530
  return; // malformed JSON: jsonBody already answered 400
522
531
  const target = isRoomName(body.room) && names.includes(body.room) ? body.room : room;
523
532
  if (!target)
524
- return sendJson(res, 404, { error: 'no rooms' });
533
+ return sendJson(res, 404, { error: tr('server.noRooms') });
525
534
  const device = typeof body.device === 'string' ? body.device : 'tablet';
526
535
  const result = await render(target, device);
527
536
  return sendJson(res, result.ok ? 200 : 501, result);
@@ -530,11 +539,18 @@ export async function createModelroom(opts = {}) {
530
539
  return await serveFile(res, path);
531
540
  if (path.startsWith('/ui/'))
532
541
  return await serveUiAsset(res, path);
542
+ // The room address is `/rooms/<name>` — plural, like `/api/rooms` and the
543
+ // `rooms/` directory it reads. `/room/<name>` was the old one; it still
544
+ // lands on the room rather than a 404.
545
+ if (path.startsWith('/room/')) {
546
+ res.writeHead(302, { location: `/rooms/${path.slice('/room/'.length)}${url.search}` });
547
+ return res.end();
548
+ }
533
549
  const page = path === '/'
534
550
  ? 'dashboard.html'
535
551
  : path === '/settings'
536
552
  ? 'settings.html'
537
- : path.startsWith('/room/')
553
+ : path.startsWith('/rooms/')
538
554
  ? 'room.html'
539
555
  : null;
540
556
  if (page)
@@ -558,7 +574,7 @@ export async function createModelroom(opts = {}) {
558
574
  process.stderr.write(`modelroom: ${detail}\n`);
559
575
  }
560
576
  try {
561
- send(res, code, 'text/plain; charset=utf-8', code === 400 ? 'bad request' : 'internal error');
577
+ send(res, code, 'text/plain; charset=utf-8', code === 400 ? tr('server.badRequest') : tr('server.internal'));
562
578
  }
563
579
  catch {
564
580
  /* nothing we can do */
@@ -601,6 +617,7 @@ export function publicConfig(cfg) {
601
617
  rooms: cfg.rooms,
602
618
  artifact: cfg.artifact,
603
619
  docs: cfg.docs,
620
+ lang: cfg.lang,
604
621
  agent: {
605
622
  adapter: cfg.agent.adapter,
606
623
  command: cfg.agent.command,